Skip to content

Prototype: UITab 18 #24461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ final class ReaderDiscoverTabViewController: ReaderDiscoverViewController {
navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "reader-menu-search"), style: .plain, target: self, action: #selector(buttonSearchTapped))
}

override func setupNavigation() {
headerView.configureForReaderAppMode()

navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true

title = SharedStrings.Reader.discover
navigationItem.titleView = nil
}

@objc private func buttonSearchTapped() {
let searchVC = ReaderSearchViewController()
searchVC.isStandaloneAppModeEnabled = true
Expand Down
25 changes: 9 additions & 16 deletions WordPress/Classes/Apps/Reader/Home/ReaderHomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@ final class ReaderHomeViewController: ReaderStreamViewController {
override func viewDidLoad() {
super.viewDidLoad()

setupNavigationItems()
}

private func setupNavigationItems() {
title = SharedStrings.Reader.home
titleView.textLabel.text = SharedStrings.Reader.home
navigationItem.titleView = titleView

navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "wpl-add-card")?.resized(to: CGSize(width: 28, height: 28)), style: .plain, target: self, action: #selector(buttonCreatePostTapped))

navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
}

override func headerForStream(_ topic: ReaderAbstractTopic?, container: UITableViewController) -> UIView? {
let view = ReaderHeaderView()
view.titleView.titleLabel.text = SharedStrings.Reader.home
view.titleView.detailsTextView.text = Strings.homeDetails
return view
override func configureTitleForTopic() {
// Do nothing
}

@objc override func headerForStream(_ topic: ReaderAbstractTopic?, container: UITableViewController) -> UIView? {
nil
}

@objc private func buttonCreatePostTapped() {
Expand All @@ -48,7 +45,3 @@ final class ReaderHomeViewController: ReaderStreamViewController {
present(editorVC, animated: true)
}
}

private enum Strings {
static let homeDetails = NSLocalizedString("reader.home.header.details", value: "Stay current with the blogs you've subscribed to.", comment: "Screen header details")
}
173 changes: 117 additions & 56 deletions WordPress/Classes/Apps/Reader/ReaderTabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,118 @@ final class ReaderTabViewController: UITabBarController, UITabBarControllerDeleg
}

private func setupViewControllers() {
if #available(iOS 18, *) {
setupModernTabBarItems()
} else {
setupLegacyTabBarItems()
}
}

@available(iOS 18, *)
private func setupModernTabBarItems() {
let home = UITab(title: SharedStrings.Reader.home, image: UIImage(named: "reader-menu-home"), identifier: "home") { [unowned self] _ in
self.makeHomeViewController()
}
let library = UITab(title: SharedStrings.Reader.library, image: UIImage(named: "reader-menu-subscriptions"), identifier: "library") { [unowned self] _ in
self.makeLibraryViewController()
}
let discover = UITab(title: SharedStrings.Reader.discover, image: UIImage(named: "reader-menu-explorer"), identifier: "discover") { [unowned self] _ in
self.makeDiscoverViewController()
}

let notifications = UITab(title: SharedStrings.Reader.activity, image: UIImage(named: "tab-bar-notifications"), identifier: "activity") { [unowned self] _ in
self.makeActivityViewController()
}
notificationsButtonViewModel.$counter.sink { [weak notifications] count in
notifications?.badgeValue = count == 0 ? nil : "1"
}.store(in: &cancellables)

let me = UITab(title: SharedStrings.Reader.me, image: UIImage(named: "tab-bar-me"), identifier: "me") { [unowned self] _ in
self.makeMeViewController()
}
// TODO: (reader) observe gravatar updates
if let account = try? WPAccount.lookupDefaultWordPressComAccount(in: ContextManager.shared.mainContext),
let avatarURL = account.avatarURL.flatMap(URL.init) {
Task { @MainActor [weak me] in
do {
let image = try await ImageDownloader.shared.image(from: avatarURL)
me?.image = image.gravatarIcon(size: 26.0)
// meVC?.tabBarItem.configureGravatarImage(image)
} catch {
// Do nothing
}
}
}

tabs = [
home,
library,
discover,
notifications,
me
]
}

private func setupLegacyTabBarItems() {
let homeVC = makeHomeViewController()
homeVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.home,
image: UIImage(named: "reader-menu-home"),
selectedImage: nil
)

let libraryVC = makeLibraryViewController()
libraryVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.library,
image: UIImage(named: "reader-menu-subscriptions"),
selectedImage: nil
)

let discoverVC = makeDiscoverViewController()
discoverVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.discover,
image: UIImage(named: "reader-menu-explorer"),
selectedImage: nil
)

let activityVC = makeActivityViewController()
activityVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.activity,
image: UIImage(named: "tab-bar-notifications"),
selectedImage: UIImage(named: "tab-bar-notifications")
)

notificationsButtonViewModel.$counter.sink { [weak activityVC] count in
let image = UIImage(named: count == 0 ? "tab-bar-notifications" : "tab-bar-notifications-unread")
activityVC?.tabBarItem.image = image
activityVC?.tabBarItem.selectedImage = image
}.store(in: &cancellables)

let meVC = makeMeViewController()
meVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.me,
image: UIImage(named: "tab-bar-me"),
selectedImage: UIImage(named: "tab-bar-me")
)
// TODO: (reader) observe gravatar updates
if let account = try? WPAccount.lookupDefaultWordPressComAccount(in: ContextManager.shared.mainContext),
let avatarURL = account.avatarURL.flatMap(URL.init) {
Task { @MainActor [weak meVC] in
do {
let image = try await ImageDownloader.shared.image(from: avatarURL)
meVC?.tabBarItem.configureGravatarImage(image)
} catch {
// Do nothing
}
}
}

self.viewControllers = [
makeHomeViewController(),
makeLibraryViewController(),
makeDiscoverViewController(),
makeNotificationsViewController(),
makeMeViewController()
homeVC,
libraryVC,
discoverVC,
activityVC,
meVC
]
}

Expand All @@ -54,11 +160,7 @@ final class ReaderTabViewController: UITabBarController, UITabBarControllerDeleg
let homeVC = ReaderHomeViewController()
// TODO: (reader) refactor to not require `topic`
homeVC.readerTopic = ReaderSidebarViewModel().getTopic(for: .following)
homeVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.home,
image: UIImage(named: "reader-menu-home"),
selectedImage: nil
)

// TODO: (reader) remove it; had to use due to how ghosts are implemented (separate table)
homeVC.tabBarItem.scrollEdgeAppearance = {
let appearance = UITabBarAppearance()
Expand All @@ -70,11 +172,7 @@ final class ReaderTabViewController: UITabBarController, UITabBarControllerDeleg

private func makeLibraryViewController() -> UIViewController {
let libraryVC = library.sidebar
libraryVC.tabBarItem = UITabBarItem(
title: SharedStrings.Reader.library,
image: UIImage(named: "reader-menu-subscriptions"),
selectedImage: nil
)

libraryVC.tabBarItem.scrollEdgeAppearance = {
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground()
Expand All @@ -92,11 +190,7 @@ final class ReaderTabViewController: UITabBarController, UITabBarControllerDeleg
UIViewController()
}
}()
discoverVC.tabBarItem = UITabBarItem(
title: Strings.discover,
image: UIImage(named: "reader-menu-explorer"),
selectedImage: nil
)

discoverVC.tabBarItem.scrollEdgeAppearance = {
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground()
Expand All @@ -107,47 +201,20 @@ final class ReaderTabViewController: UITabBarController, UITabBarControllerDeleg
return navigationVC
}

private func makeNotificationsViewController() -> UIViewController {
private func makeActivityViewController() -> UIViewController {
let notificationsVC = UIStoryboard(name: "Notifications", bundle: nil)
.instantiateInitialViewController() as! NotificationsViewController
notificationsVC.tabBarItem = UITabBarItem(
title: Strings.notifications,
image: UIImage(named: "tab-bar-notifications"),
selectedImage: UIImage(named: "tab-bar-notifications")
)

notificationsVC.title = SharedStrings.Reader.activity
notificationsVC.isReaderAppModeEnabled = true
let navigationVC = UINavigationController(rootViewController: notificationsVC)
notificationsVC.enableLargeTitles()

notificationsButtonViewModel.$counter.sink { [weak notificationsVC] count in
let image = UIImage(named: count == 0 ? "tab-bar-notifications" : "tab-bar-notifications-unread")
notificationsVC?.tabBarItem.image = image
notificationsVC?.tabBarItem.selectedImage = image
}.store(in: &cancellables)

return navigationVC
}

private func makeMeViewController() -> UIViewController {
let meVC = ReaderProfileViewController()
// TODO: (reader) display your profile icons
meVC.tabBarItem = UITabBarItem(
title: Strings.me,
image: UIImage(named: "tab-bar-me"),
selectedImage: UIImage(named: "tab-bar-me")
)
// TODO: (reader) observe gravatar updates
if let account = try? WPAccount.lookupDefaultWordPressComAccount(in: ContextManager.shared.mainContext),
let avatarURL = account.avatarURL.flatMap(URL.init) {
Task { @MainActor [weak meVC] in
do {
let image = try await ImageDownloader.shared.image(from: avatarURL)
meVC?.tabBarItem.configureGravatarImage(image)
} catch {
// Do nothing
}
}
}
return UINavigationController(rootViewController: meVC)
}

Expand All @@ -168,9 +235,3 @@ private extension UIViewController {
navigationController?.navigationBar.prefersLargeTitles = true
}
}

private enum Strings {
static let discover = NSLocalizedString("readerApp.tabBar.discover", value: "Discover", comment: "Reader app primary navigation tab bar")
static let notifications = NSLocalizedString("readerApp.tabBar.notifications", value: "Notifications", comment: "Reader app primary navigation tab bar")
static let me = NSLocalizedString("readerApp.tabBar.me", value: "Me", comment: "Reader app primary navigation tab bar")
}
2 changes: 2 additions & 0 deletions WordPress/Classes/Utility/SharedStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,7 @@ enum SharedStrings {
static let tags = NSLocalizedString("reader.tags.title", value: "Tags", comment: "Used in multiple contexts, usually as a screen title")
static let lists = NSLocalizedString("reader.lists.title", value: "Lists", comment: "Used in multiple contexts, usually as a screen title")
static let search = NSLocalizedString("reader.search.title", value: "Search", comment: "Used in multiple contexts, usually as a screen title")
static let activity = NSLocalizedString("reader.activity.title", value: "Activity", comment: "Used in multiple contexts, usually as a screen title")
static let me = NSLocalizedString("reader.me.title", value: "Me", comment: "Used in multiple contexts, usually as a screen title")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WordPressKit
import WordPressShared

class ReaderDiscoverViewController: UIViewController, ReaderDiscoverHeaderViewDelegate {
private let headerView = ReaderDiscoverHeaderView()
let headerView = ReaderDiscoverHeaderView()
private var selectedChannel: ReaderDiscoverChannel = .recommended
private let topic: ReaderAbstractTopic
private var streamVC: ReaderStreamViewController?
Expand Down Expand Up @@ -50,7 +50,7 @@ class ReaderDiscoverViewController: UIViewController, ReaderDiscoverHeaderViewDe
setupNotificationsBarButtonItem()
}

private func setupNavigation() {
func setupNavigation() {
navigationItem.largeTitleDisplayMode = .never
setupNotificationsBarButtonItem()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ import AutomatticTracks
}
}

private func configureTitleForTopic() {
func configureTitleForTopic() {
guard let topic = readerTopic else {
if contentType == .saved {
title = SharedStrings.Reader.saved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ final class ReaderDiscoverHeaderView: ReaderBaseHeaderView, UITextViewDelegate {
fatalError("init(coder:) has not been implemented")
}

func configureForReaderAppMode() {
titleView.removeFromSuperview()
channelsStackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
}

override func layoutSubviews() {
super.layoutSubviews()

Expand Down