mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Create TimelineCollectionViewController. Make navigation bar and toolbar solid.
This commit is contained in:
@@ -61,12 +61,36 @@ final class SidebarViewController: UICollectionViewController {
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
collectionView.backgroundColor = .systemRed
|
||||
|
||||
title = "Feeds"
|
||||
navigationController?.navigationBar.prefersLargeTitles = true
|
||||
|
||||
let appearance = UINavigationBarAppearance()
|
||||
appearance.configureWithOpaqueBackground() // Ensures solid background
|
||||
appearance.backgroundColor = AppColor.navigationBarBackground // Set your desired color
|
||||
appearance.titleTextAttributes = [.foregroundColor: UIColor.white] // Regular title text
|
||||
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white] // Large title text
|
||||
appearance.shadowColor = .clear
|
||||
|
||||
// Apply the appearance settings
|
||||
navigationController?.navigationBar.standardAppearance = appearance
|
||||
navigationController?.navigationBar.scrollEdgeAppearance = appearance
|
||||
navigationController?.navigationBar.compactAppearance = appearance // Optional
|
||||
navigationController?.navigationBar.compactScrollEdgeAppearance = appearance
|
||||
|
||||
navigationController?.navigationBar.isTranslucent = false
|
||||
|
||||
if let subviews = navigationController?.navigationBar.subviews {
|
||||
for subview in subviews {
|
||||
if subview.frame.height < 2 {
|
||||
subview.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigationItem.rightBarButtonItem = filterButton
|
||||
|
||||
toolbar.barTintColor = AppColor.toolbarBackground
|
||||
toolbar.isTranslucent = false
|
||||
toolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
view.addSubview(toolbar)
|
||||
|
||||
125
iOS/MainWindow/Timeline/TimelineCollectionViewController.swift
Normal file
125
iOS/MainWindow/Timeline/TimelineCollectionViewController.swift
Normal file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// TimelineCollectionViewController.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Brent Simmons on 2/9/25.
|
||||
// Copyright © 2025 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Articles
|
||||
|
||||
typealias TimelineSectionID = Int
|
||||
typealias TimelineArticleID = String
|
||||
|
||||
final class TimelineCell: UICollectionViewCell {
|
||||
|
||||
static let reuseIdentifier = "TimelineCell"
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = UIFont.boldSystemFont(ofSize: 16)
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
contentView.addSubview(titleLabel)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
|
||||
func configure(_ article: Article?, showFeedName: Bool, showIcon: Bool) {
|
||||
if let article {
|
||||
titleLabel.text = article.title
|
||||
} else {
|
||||
titleLabel.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class TimelineArticlesManager {
|
||||
|
||||
var articles = [Article]() {
|
||||
didSet {
|
||||
updateArticleIDsToArticles()
|
||||
}
|
||||
}
|
||||
|
||||
subscript(_ articleID: String) -> Article? {
|
||||
articleIDsToArticles[articleID]
|
||||
}
|
||||
|
||||
private var articleIDsToArticles = [String: Article]()
|
||||
|
||||
private func updateArticleIDsToArticles() {
|
||||
var d = [String: Article]()
|
||||
for article in articles {
|
||||
d[article.id] = article
|
||||
}
|
||||
articleIDsToArticles = d
|
||||
}
|
||||
}
|
||||
|
||||
final class TimelineCollectionViewController: UICollectionViewController {
|
||||
|
||||
private let timelineArticlesManager = TimelineArticlesManager()
|
||||
|
||||
typealias DataSource = UICollectionViewDiffableDataSource<TimelineSectionID, TimelineArticleID>
|
||||
private lazy var dataSource = createDataSource()
|
||||
|
||||
init() {
|
||||
var configuration = UICollectionLayoutListConfiguration(appearance: .plain)
|
||||
configuration.headerMode = .none
|
||||
let layout = UICollectionViewCompositionalLayout.list(using: configuration)
|
||||
|
||||
super.init(collectionViewLayout: layout)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
title = "Articles"
|
||||
|
||||
collectionView.register(TimelineCell.self, forCellWithReuseIdentifier: TimelineCell.reuseIdentifier)
|
||||
|
||||
timelineArticlesManager.articles = [Article]()
|
||||
applySnapshot()
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineCollectionViewController {
|
||||
|
||||
func createDataSource() -> DataSource {
|
||||
UICollectionViewDiffableDataSource<TimelineSectionID, TimelineArticleID>(collectionView: collectionView) { collectionView, indexPath, articleID -> UICollectionViewCell? in
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimelineCell.reuseIdentifier, for: indexPath) as! TimelineCell
|
||||
let article = self.timelineArticlesManager[articleID]
|
||||
cell.configure(article, showFeedName: false, showIcon: false)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
func applySnapshot() {
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<TimelineSectionID, TimelineArticleID>()
|
||||
|
||||
let oneAndOnlySectionID = 0
|
||||
snapshot.appendSections([oneAndOnlySectionID])
|
||||
|
||||
let articleIDs = timelineArticlesManager.articles.map { $0.id }
|
||||
snapshot.appendItems(articleIDs, toSection: oneAndOnlySectionID)
|
||||
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user