mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Create and use MainWindowController for iOS.
This commit is contained in:
@@ -17,6 +17,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationC
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
private var mainWindowController: MainWindowController?
|
||||
private var coordinator: SceneCoordinator?
|
||||
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
||||
|
||||
@@ -77,30 +78,10 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationC
|
||||
ArticleStatusSyncTimer.shared.update()
|
||||
#endif
|
||||
|
||||
// Create window.
|
||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||
self.window = window
|
||||
|
||||
// Create UI and add it to window.
|
||||
let rootSplitViewController = RootSplitViewController()
|
||||
coordinator = SceneCoordinator(rootSplitViewController: rootSplitViewController)
|
||||
rootSplitViewController.coordinator = coordinator
|
||||
rootSplitViewController.delegate = coordinator
|
||||
|
||||
window.rootViewController = rootSplitViewController
|
||||
|
||||
window.tintColor = AppColor.accent
|
||||
updateUserInterfaceStyle()
|
||||
UINavigationBar.appearance().scrollEdgeAppearance = UINavigationBarAppearance()
|
||||
|
||||
window.makeKeyAndVisible()
|
||||
// Create window and UI
|
||||
mainWindowController = MainWindowController()
|
||||
|
||||
Task { @MainActor in
|
||||
// Ensure Feeds view shows on first run on iPad — otherwise the UI is empty.
|
||||
if UIDevice.current.userInterfaceIdiom == .pad && AppDefaults.isFirstRun {
|
||||
rootSplitViewController.show(.primary)
|
||||
}
|
||||
|
||||
self.unreadCount = AccountManager.shared.unreadCount
|
||||
}
|
||||
|
||||
@@ -119,7 +100,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationC
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
prepareAccountsForForeground()
|
||||
coordinator?.resetFocus()
|
||||
mainWindowController?.resetFocus()
|
||||
}
|
||||
|
||||
private func prepareAccountsForForeground() {
|
||||
@@ -167,7 +148,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationC
|
||||
ArticleThemeDownloader.shared.cleanUp()
|
||||
|
||||
CoalescingQueue.standard.performCallsImmediately()
|
||||
coordinator?.suspend()
|
||||
mainWindowController?.suspend()
|
||||
logger.info("Application processing suspended.")
|
||||
}
|
||||
}
|
||||
@@ -195,7 +176,7 @@ extension AppDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
coordinator?.cleanUp(conditional: true)
|
||||
mainWindowController?.cleanUp(conditional: true)
|
||||
AccountManager.shared.refreshAll(errorHandler: errorHandler)
|
||||
}
|
||||
|
||||
@@ -225,7 +206,7 @@ extension AppDelegate {
|
||||
default:
|
||||
handle(response)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.coordinator?.dismissIfLaunchingFromExternalAction()
|
||||
self.mainWindowController?.dismissIfLaunchingFromExternalAction()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,6 +310,6 @@ private extension AppDelegate {
|
||||
|
||||
func handle(_ response: UNNotificationResponse) {
|
||||
AccountManager.shared.resumeAllIfSuspended()
|
||||
coordinator?.handle(response)
|
||||
mainWindowController?.handle(response)
|
||||
}
|
||||
}
|
||||
|
||||
88
iOS/MainWindow/MainWindowController.swift
Normal file
88
iOS/MainWindow/MainWindowController.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// MainWindowController.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Brent Simmons on 2/2/25.
|
||||
// Copyright © 2025 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
final class MainWindowController {
|
||||
|
||||
let window: UIWindow
|
||||
|
||||
let rootSplitViewController: RootSplitViewController
|
||||
let sidebarViewController = MainFeedViewController()
|
||||
let timelineViewController = TimelineViewController()
|
||||
let articleViewController = ArticleViewController()
|
||||
|
||||
let coordinator: SceneCoordinator
|
||||
|
||||
init() {
|
||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||
self.window = window
|
||||
|
||||
let rootSplitViewController = RootSplitViewController(
|
||||
sidebarViewController: sidebarViewController,
|
||||
timelineViewController: timelineViewController,
|
||||
articleViewController: articleViewController
|
||||
)
|
||||
|
||||
self.coordinator = SceneCoordinator(rootSplitViewController: rootSplitViewController)
|
||||
rootSplitViewController.coordinator = coordinator
|
||||
rootSplitViewController.delegate = coordinator
|
||||
self.rootSplitViewController = rootSplitViewController
|
||||
|
||||
window.rootViewController = rootSplitViewController
|
||||
|
||||
window.tintColor = AppColor.accent
|
||||
updateUserInterfaceStyle()
|
||||
UINavigationBar.appearance().scrollEdgeAppearance = UINavigationBarAppearance()
|
||||
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
Task { @MainActor in
|
||||
// Ensure Feeds view shows on first run on iPad — otherwise the UI is empty.
|
||||
if UIDevice.current.userInterfaceIdiom == .pad && AppDefaults.isFirstRun {
|
||||
rootSplitViewController.show(.primary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
|
||||
func resetFocus() {
|
||||
coordinator.resetFocus()
|
||||
}
|
||||
|
||||
func suspend() {
|
||||
coordinator.suspend()
|
||||
}
|
||||
|
||||
func cleanUp(conditional: Bool) {
|
||||
coordinator.cleanUp(conditional: conditional)
|
||||
}
|
||||
|
||||
func dismissIfLaunchingFromExternalAction() {
|
||||
coordinator.dismissIfLaunchingFromExternalAction()
|
||||
}
|
||||
|
||||
func handle(_ response: UNNotificationResponse) {
|
||||
coordinator.handle(response)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MainWindowController {
|
||||
|
||||
func updateUserInterfaceStyle() {
|
||||
|
||||
assert(Thread.isMainThread)
|
||||
|
||||
let updatedStyle = AppDefaults.userInterfaceColorPalette.uiUserInterfaceStyle
|
||||
if window.overrideUserInterfaceStyle != updatedStyle {
|
||||
window.overrideUserInterfaceStyle = updatedStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,16 +19,23 @@ final class RootSplitViewController: UISplitViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var sidebarViewController = MainFeedViewController()
|
||||
private lazy var timelineViewController = TimelineViewController()
|
||||
private lazy var articleViewController = ArticleViewController()
|
||||
private let sidebarViewController: MainFeedViewController
|
||||
private let timelineViewController: TimelineViewController
|
||||
private let articleViewController: ArticleViewController
|
||||
|
||||
init(sidebarViewController: MainFeedViewController,
|
||||
timelineViewController: TimelineViewController,
|
||||
articleViewController: ArticleViewController) {
|
||||
|
||||
self.sidebarViewController = sidebarViewController
|
||||
self.timelineViewController = timelineViewController
|
||||
self.articleViewController = articleViewController
|
||||
|
||||
init() {
|
||||
super.init(style: .tripleColumn)
|
||||
|
||||
setViewController(self.sidebarViewController, for: .primary)
|
||||
setViewController(self.timelineViewController, for: .supplementary)
|
||||
setViewController(self.articleViewController, for: .secondary)
|
||||
setViewController(sidebarViewController, for: .primary)
|
||||
setViewController(timelineViewController, for: .supplementary)
|
||||
setViewController(articleViewController, for: .secondary)
|
||||
|
||||
self.showsSecondaryOnlyButton = true
|
||||
self.preferredDisplayMode = .oneBesideSecondary
|
||||
|
||||
Reference in New Issue
Block a user