malcommac / Owl

A declarative type-safe framework for building fast and flexible lists with UITableViews & UICollectionViews
MIT License
432 stars 31 forks source link

Custom indexTitles #27

Open wow-such-amazing opened 5 years ago

wow-such-amazing commented 5 years ago

Hello!

I have a suggestion to improve about indexTitles for sections. Below is the current code for section indexes. It is based on the indexTitle property of the TableSection. However pretty common case is to have the full alphabet in the indexes even if your table contains only couple sections with titles like C and H. So I think the best way would be to somehow divide indexTitles from sections.

I will be able to make a PR about that as soon as we switch our project from FlowKit to Owl.

// MARK: - Section Indexes -
public func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    let indexes = sections.compactMap({ $0.indexTitle })
    guard !indexes.isEmpty else {
        return nil
    }
    return indexes
}

public func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
    return sections.firstIndex(where: { $0.indexTitle == title }) ?? 0
}
wow-such-amazing commented 5 years ago

I think I found a way how this can work. Maybe we can document it

If I create a TableSection without models and without header, but with indexTitle then I will have index but no data in the table. And later I can update this section when I have some data 👍

wow-such-amazing commented 5 years ago

However in this case it would be useful to mark elements as open. So that we could update header in didSet of elements. Or maybe there could be an event that is triggered whenever elements are updated

wow-such-amazing commented 5 years ago

I think code will describe my idea in a better way. This is what I came up with for now

final class TestSection: TableSection {
    required init(original: TableSection) {
        super.init(original: original)
    }

    required init<C>(source: TableSection, elements: C) where C : Collection, C.Element == ElementRepresentable {
        super.init(source: source, elements: elements)
    }

    func apply(elements: [ElementRepresentable]) {
        removeAll()
        set(elements: elements)
        reloadHeader()
    }

    func reloadHeader() {
        guard let indexTitle = indexTitle else { return }
        if elements.isEmpty {
            headerView = nil
        } else {
            let someConfig = SomeHeaderConfig(title: indexTitle, color: .black)
            headerView = SomeHeaderAdapter(config: someConfig)
        }
    }
}