More catalyst toolbar stuff

This commit is contained in:
Shadowfacts 2022-01-15 14:49:29 -05:00
parent 1d2e666c00
commit 36fda4d51f
5 changed files with 74 additions and 66 deletions

View File

@ -13,6 +13,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private(set) var fervorController: FervorController!
private(set) var toggleReadBarButtonItem: UIBarButtonItem?
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "SceneDelegate")
@ -144,23 +145,31 @@ extension SceneDelegate: HomeViewControllerDelegate {
#if targetEnvironment(macCatalyst)
extension NSToolbarItem.Identifier {
static let toggleItemRead = NSToolbarItem.Identifier("ToggleItemRead")
static let shareItem = NSToolbarItem.Identifier("ShareItem")
}
extension SceneDelegate: NSToolbarDelegate {
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
let item = NSToolbarItem(itemIdentifier: .toggleItemRead)
item.target = nil
item.action = #selector(AppSplitViewController.toggleItemRead)
item.image = UIImage(systemName: "checkmark.circle")
return item
if itemIdentifier == .toggleItemRead {
// need an item bar button item to make the size of the image match the share button
let item = NSToolbarItem(itemIdentifier: .toggleItemRead, barButtonItem: UIBarButtonItem(image: nil, style: .plain, target: nil, action: nil))
item.image = UIImage(systemName: "checkmark.circle")
item.target = nil
item.action = #selector(ReadViewController.toggleItemRead(_:))
return item
} else if itemIdentifier == .shareItem {
return NSSharingServicePickerToolbarItem(itemIdentifier: .shareItem)
} else {
return nil
}
}
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.toggleItemRead]
return [.shareItem, .toggleItemRead]
}
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.toggleItemRead]
return [.shareItem, .toggleItemRead]
}
}
#endif

View File

@ -51,55 +51,12 @@ class AppSplitViewController: UISplitViewController {
let nav = AppNavigationController(rootViewController: home)
setViewController(nav, for: .compact)
}
#if targetEnvironment(macCatalyst)
@objc func toggleItemRead(_ item: NSToolbarItem) {
guard let nav = viewController(for: .secondary) as? UINavigationController,
let read = nav.topViewController as? ReadViewController else {
return
}
Task {
await fervorController.markItem(read.item, read: !read.item.read)
updateImage(toolbarItem: item)
}
}
private func updateImage(toolbarItem: NSToolbarItem) {
if let nav = viewController(for: .secondary) as? UINavigationController,
let read = nav.topViewController as? ReadViewController {
toolbarItem.image = UIImage(systemName: read.item.read ? "checkmark.circle.fill" : "checkmark.circle")
} else {
toolbarItem.image = UIImage(systemName: "checkmark.circle")
}
}
#endif
}
extension AppSplitViewController: ItemsViewControllerDelegate {
func showReadItem(_ item: Item) {
secondaryNav.setViewControllers([ReadViewController(item: item, fervorController: fervorController)], animated: false)
#if targetEnvironment(macCatalyst)
if let titlebar = view.window?.windowScene?.titlebar,
let toggleRead = titlebar.toolbar?.items.first(where: { $0.itemIdentifier == .toggleItemRead }) {
updateImage(toolbarItem: toggleRead)
}
#endif
}
}
#if targetEnvironment(macCatalyst)
extension AppSplitViewController {
override func responds(to aSelector: Selector!) -> Bool {
if aSelector == #selector(toggleItemRead) {
guard let nav = viewController(for: .secondary) as? UINavigationController else {
return false
}
return nav.topViewController is ReadViewController
} else {
return super.responds(to: aSelector)
}
}
}
#endif

View File

@ -87,18 +87,21 @@ class ItemCollectionViewCell: UICollectionViewListCell {
}
func setRead(_ read: Bool, animated: Bool) {
guard self.item.read != read else { return }
Task {
await self.delegate?.fervorController.markItem(self.item, read: read)
if animated {
// i don't know why .transition works but .animate doesn't
UIView.transition(with: self, duration: 0.2, options: .transitionCrossDissolve) {
self.updateColors()
}
} else {
updateColors()
guard item.read != read else { return }
item.read = read
if animated {
// i don't know why .transition works but .animate doesn't
UIView.transition(with: self, duration: 0.2, options: .transitionCrossDissolve) {
self.updateColors()
}
} else {
updateColors()
}
Task {
await delegate?.fervorController.markItem(item, read: read)
}
}

View File

@ -127,16 +127,21 @@ extension ItemsViewController: UICollectionViewDelegate {
return UIContextMenuConfiguration(identifier: nil, previewProvider: {
ReadViewController(item: item, fervorController: self.fervorController)
}, actionProvider: { _ in
var children: [UIAction] = []
var children: [UIMenuElement] = []
if let url = item.url {
children.append(UIAction(title: "Open in Safari", image: UIImage(systemName: "safari"), handler: { [weak self] _ in
let vc = SFSafariViewController(url: url)
vc.preferredControlTintColor = .appTintColor
self?.present(vc, animated: true)
}))
#if targetEnvironment(macCatalyst)
self.activityItemsConfiguration = UIActivityItemsConfiguration(objects: [url as NSURL])
children.append(UICommand(title: "Share…", action: Selector(("unused")), propertyList: UICommandTagShare))
#else
children.append(UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up"), handler: { [weak self] _ in
self?.present(UIActivityViewController(activityItems: [url], applicationActivities: nil), animated: true)
}))
#endif
}
if item.read {
children.append(UIAction(title: "Mark as Unread", image: UIImage(systemName: "checkmark.circle"), handler: { [unowned self] _ in

View File

@ -22,6 +22,10 @@ class ReadViewController: UIViewController {
let fervorController: FervorController
let item: Item
#if targetEnvironment(macCatalyst)
private var itemReadObservation: NSKeyValueObservation?
#endif
override var prefersStatusBarHidden: Bool {
navigationController?.isNavigationBarHidden ?? false
}
@ -68,6 +72,15 @@ class ReadViewController: UIViewController {
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
if let url = item.url {
activityItemsConfiguration = UIActivityItemsConfiguration(objects: [url as NSURL])
}
#if targetEnvironment(macCatalyst)
itemReadObservation = item.observe(\.read) { [unowned self] _, _ in
self.updateToggleReadToolbarImage()
}
#endif
}
private static let css = try! String(contentsOf: Bundle.main.url(forResource: "read", withExtension: "css")!)
@ -125,6 +138,24 @@ class ReadViewController: UIViewController {
vc.preferredControlTintColor = .appTintColor
return vc
}
#if targetEnvironment(macCatalyst)
@objc func toggleItemRead(_ item: NSToolbarItem) {
Task {
await fervorController.markItem(self.item, read: !self.item.read)
updateToggleReadToolbarImage()
}
}
private func updateToggleReadToolbarImage() {
guard let titlebar = view.window?.windowScene?.titlebar,
let item = titlebar.toolbar?.items.first(where: { $0.itemIdentifier == .toggleItemRead }) else {
return
}
item.image = UIImage(systemName: self.item.read ? "checkmark.circle.fill" : "checkmark.circle")
}
#endif
}
@ -181,18 +212,21 @@ extension ReadViewController: StretchyMenuInteractionDelegate {
guard let url = item.url else {
return []
}
return [
var items = [
StretchyMenuItem(title: "Open in Safari", subtitle: nil, action: { [unowned self] in
self.present(createSafariVC(url: url), animated: true)
}),
StretchyMenuItem(title: "Share", subtitle: nil, action: { [unowned self] in
self.present(UIActivityViewController(activityItems: [url], applicationActivities: nil), animated: true)
}),
StretchyMenuItem(title: item.read ? "Mark as Unread" : "Mark as Read", subtitle: nil, action: { [unowned self] in
Task {
await self.fervorController.markItem(item, read: !item.read)
}
}),
]
#if !targetEnvironment(macCatalyst)
items.insert(StretchyMenuItem(title: "Share", subtitle: nil, action: { [unowned self] in
self.present(UIActivityViewController(activityItems: [url], applicationActivities: nil), animated: true)
}), at: 1)
#endif
return items
}
}