diff --git a/iOS/Account/CloudKitAccountViewController.swift b/iOS/Account/CloudKitAccountViewController.swift index d01741b0c..e6060a4c5 100644 --- a/iOS/Account/CloudKitAccountViewController.swift +++ b/iOS/Account/CloudKitAccountViewController.swift @@ -63,11 +63,10 @@ class CloudKitAccountViewController: UITableViewController { return super.tableView(tableView, viewForHeaderInSection: section) } } - + @IBAction func openLimitationsAndSolutions(_ sender: Any) { let vc = SFSafariViewController(url: CloudKitWebDocumentation.limitationsAndSolutionsURL) vc.modalPresentationStyle = .pageSheet present(vc, animated: true) } - } diff --git a/iOS/Account/FeedbinAccountViewController.swift b/iOS/Account/FeedbinAccountViewController.swift index c6e66844b..a988c748f 100644 --- a/iOS/Account/FeedbinAccountViewController.swift +++ b/iOS/Account/FeedbinAccountViewController.swift @@ -21,7 +21,7 @@ class FeedbinAccountViewController: UITableViewController { @IBOutlet weak var showHideButton: UIButton! @IBOutlet weak var actionButton: UIButton! @IBOutlet weak var footerLabel: UILabel! - + weak var account: Account? weak var delegate: AddAccountDismissDelegate? @@ -46,7 +46,6 @@ class FeedbinAccountViewController: UITableViewController { NotificationCenter.default.addObserver(self, selector: #selector(textDidChange(_:)), name: UITextField.textDidChangeNotification, object: passwordTextField) tableView.register(ImageHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader") - } private func setupFooter() { @@ -71,7 +70,6 @@ class FeedbinAccountViewController: UITableViewController { dismiss(animated: true, completion: nil) } - @IBAction func showHidePassword(_ sender: Any) { if passwordTextField.isSecureTextEntry { passwordTextField.isSecureTextEntry = false diff --git a/iOS/Account/ReaderAPIAccountViewController.swift b/iOS/Account/ReaderAPIAccountViewController.swift index d1f5377c0..c9d081069 100644 --- a/iOS/Account/ReaderAPIAccountViewController.swift +++ b/iOS/Account/ReaderAPIAccountViewController.swift @@ -23,7 +23,7 @@ class ReaderAPIAccountViewController: UITableViewController { @IBOutlet weak var actionButton: UIButton! @IBOutlet weak var footerLabel: UILabel! @IBOutlet weak var signUpButton: UIButton! - + weak var account: Account? var accountType: AccountType? weak var delegate: AddAccountDismissDelegate? diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index 4fbdec7df..e84167bb4 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -45,6 +45,8 @@ class ArticleViewController: UIViewController { weak var coordinator: SceneCoordinator! + private let poppableDelegate = PoppableGestureRecognizerDelegate() + var article: Article? { didSet { if let controller = currentWebViewController, controller.article != article { @@ -101,6 +103,11 @@ class ArticleViewController: UIViewController { articleExtractorButton.addTarget(self, action: #selector(toggleArticleExtractor(_:)), for: .touchUpInside) toolbarItems?.insert(UIBarButtonItem(customView: articleExtractorButton), at: 6) + if let parentNavController = navigationController?.parent as? UINavigationController { + poppableDelegate.navigationController = parentNavController + parentNavController.interactivePopGestureRecognizer?.delegate = poppableDelegate + } + pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:]) pageViewController.delegate = self pageViewController.dataSource = self @@ -154,6 +161,16 @@ class ArticleViewController: UIViewController { updateUI() } + + override func viewWillAppear(_ animated: Bool) { + let hideToolbars = AppDefaults.shared.articleFullscreenEnabled + if hideToolbars { + currentWebViewController?.hideBars() + } else { + currentWebViewController?.showBars() + } + super.viewWillAppear(animated) + } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(true) @@ -161,6 +178,7 @@ class ArticleViewController: UIViewController { } override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) if searchBar != nil && !searchBar.isHidden { endFind() } @@ -211,7 +229,6 @@ class ArticleViewController: UIViewController { starBarButtonItem.image = AppAssets.starOpenImage starBarButtonItem.accLabelText = NSLocalizedString("Star Article", comment: "Star Article") } - } // MARK: Notifications diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 77bdb1fc5..916bd9b5e 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -19,29 +19,39 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - window = UIWindow(windowScene: scene as! UIWindowScene) window!.tintColor = AppAssets.primaryAccentColor updateUserInterfaceStyle() - window!.rootViewController = coordinator.start(for: window!.frame.size) + UINavigationBar.appearance().scrollEdgeAppearance = UINavigationBarAppearance() + + let rootViewController = window!.rootViewController as! RootSplitViewController + rootViewController.presentsWithGesture = true + rootViewController.showsSecondaryOnlyButton = true + if AppDefaults.shared.isFirstRun { + // This ensures that the Feeds view shows on first-run. + rootViewController.preferredDisplayMode = .twoBesideSecondary + } else { + rootViewController.preferredDisplayMode = .oneBesideSecondary + } + + coordinator = SceneCoordinator(rootSplitViewController: rootViewController) + rootViewController.coordinator = coordinator + rootViewController.delegate = coordinator coordinator.restoreWindowState(session.stateRestorationActivity) NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil) if let _ = connectionOptions.urlContexts.first?.url { - window?.makeKeyAndVisible() self.scene(scene, openURLContexts: connectionOptions.urlContexts) return } if let shortcutItem = connectionOptions.shortcutItem { - window!.makeKeyAndVisible() handleShortcutItem(shortcutItem) return } if let notificationResponse = connectionOptions.notificationResponse { - window!.makeKeyAndVisible() coordinator.handle(notificationResponse) return } @@ -49,8 +59,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity { coordinator.handle(userActivity) } - - window!.makeKeyAndVisible() + } func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { @@ -68,11 +77,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { ArticleStringFormatter.emptyCaches() appDelegate.prepareAccountsForBackground() } - + func sceneWillEnterForeground(_ scene: UIScene) { appDelegate.resumeDatabaseProcessingIfNecessary() appDelegate.prepareAccountsForForeground() - coordinator.configurePanelMode(for: window!.frame.size) coordinator.resetFocus() } diff --git a/iOS/Settings/SettingsViewController.swift b/iOS/Settings/SettingsViewController.swift index b40381773..bfb9fed89 100644 --- a/iOS/Settings/SettingsViewController.swift +++ b/iOS/Settings/SettingsViewController.swift @@ -114,7 +114,7 @@ class SettingsViewController: UITableViewController { // MARK: UITableView override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - + switch section { case 1: return AccountManager.shared.accounts.count + 1 @@ -130,13 +130,13 @@ class SettingsViewController: UITableViewController { return super.tableView(tableView, numberOfRowsInSection: section) } } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell switch indexPath.section { case 1: - + let sortedAccounts = AccountManager.shared.sortedAccounts if indexPath.row == sortedAccounts.count { cell = tableView.dequeueReusableCell(withIdentifier: "SettingsTableViewCell", for: indexPath) @@ -151,9 +151,9 @@ class SettingsViewController: UITableViewController { } default: cell = super.tableView(tableView, cellForRowAt: indexPath) - + } - + return cell } @@ -218,27 +218,12 @@ class SettingsViewController: UITableViewController { openURL("https://netnewswire.com/help/ios/6.1/en/") tableView.selectRow(at: nil, animated: true, scrollPosition: .none) case 1: - openURL("https://netnewswire.com/") - tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 2: openURL(URL.releaseNotes.absoluteString) tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 3: - openURL("https://github.com/brentsimmons/NetNewsWire/blob/main/Technotes/HowToSupportNetNewsWire.markdown") - tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 4: - openURL("https://github.com/brentsimmons/NetNewsWire") - tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 5: + case 2: openURL("https://github.com/brentsimmons/NetNewsWire/issues") tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 6: - openURL("https://github.com/brentsimmons/NetNewsWire/tree/main/Technotes") - tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 7: - openURL("https://netnewswire.com/slack") - tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - case 8: + case 3: let timeline = UIStoryboard.settings.instantiateController(ofType: AboutViewController.self) self.navigationController?.pushViewController(timeline, animated: true) default: @@ -248,7 +233,7 @@ class SettingsViewController: UITableViewController { tableView.selectRow(at: nil, animated: true, scrollPosition: .none) } } - + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return false } diff --git a/iOS/Settings/TimelineCustomizerViewController.swift b/iOS/Settings/TimelineCustomizerViewController.swift index f9d15bb9a..7a76feaa5 100644 --- a/iOS/Settings/TimelineCustomizerViewController.swift +++ b/iOS/Settings/TimelineCustomizerViewController.swift @@ -36,7 +36,7 @@ class TimelineCustomizerViewController: UIViewController { } override func viewWillAppear(_ animated: Bool) { - super.viewDidAppear(animated) + super.viewWillAppear(animated) updatePreviewBorder() updatePreview() } diff --git a/iOS/Settings/TimelinePreviewTableViewController.swift b/iOS/Settings/TimelinePreviewTableViewController.swift index 6e19b5672..4c473fe05 100644 --- a/iOS/Settings/TimelinePreviewTableViewController.swift +++ b/iOS/Settings/TimelinePreviewTableViewController.swift @@ -71,7 +71,7 @@ private extension TimelinePreviewTableViewController { let iconImage = IconImage(AppAssets.faviconTemplateImage.withTintColor(AppAssets.secondaryAccentColor)) - return MainTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Feed Name", byline: nil, iconImage: iconImage, showIcon: true, featuredImage: nil, numberOfLines: AppDefaults.shared.timelineNumberOfLines, iconSize: AppDefaults.shared.timelineIconSize) + return MainTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Feed Name", byline: nil, iconImage: iconImage, showIcon: true, numberOfLines: AppDefaults.shared.timelineNumberOfLines, iconSize: AppDefaults.shared.timelineIconSize) } } diff --git a/iOS/UIKit Extensions/InteractiveLabel.swift b/iOS/UIKit Extensions/InteractiveLabel.swift index 12d12f105..989412278 100644 --- a/iOS/UIKit Extensions/InteractiveLabel.swift +++ b/iOS/UIKit Extensions/InteractiveLabel.swift @@ -15,12 +15,12 @@ class InteractiveLabel: UILabel, UIEditMenuInteractionDelegate { super.init(frame: frame) commonInit() } - + required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } - + func commonInit() { let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:))) self.addGestureRecognizer(gestureRecognizer) @@ -30,7 +30,7 @@ class InteractiveLabel: UILabel, UIEditMenuInteractionDelegate { self.isUserInteractionEnabled = true } - + @objc func handleLongPressGesture(_ recognizer: UIGestureRecognizer) { guard recognizer.state == .began, let recognizerView = recognizer.view else { return @@ -50,7 +50,7 @@ class InteractiveLabel: UILabel, UIEditMenuInteractionDelegate { override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { return (action == #selector(UIResponderStandardEditActions.copy(_:))) } - + override func copy(_ sender: Any?) { UIPasteboard.general.string = text } @@ -58,10 +58,11 @@ class InteractiveLabel: UILabel, UIEditMenuInteractionDelegate { // MARK: - UIEditMenuInteractionDelegate func editMenuInteraction(_ interaction: UIEditMenuInteraction, menuFor configuration: UIEditMenuConfiguration, suggestedActions: [UIMenuElement]) -> UIMenu? { - + let copyAction = UIAction(title: "Copy", image: nil) { [weak self] action in self?.copy(nil) } return UIMenu(title: "", children: [copyAction]) } } +