183 lines
6.5 KiB
Swift
183 lines
6.5 KiB
Swift
//
|
|
// NotificationsPageViewController.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 9/13/19.
|
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import Pachyderm
|
|
import TuskerPreferences
|
|
|
|
class NotificationsPageViewController: SegmentedPageViewController<NotificationsPageViewController.Page> {
|
|
|
|
weak var mastodonController: MastodonController!
|
|
|
|
var initialMode: NotificationsMode?
|
|
|
|
private lazy var announcementsButton: UIButton = {
|
|
#if os(visionOS)
|
|
var config = UIButton.Configuration.borderedProminent()
|
|
#else
|
|
var config = UIButton.Configuration.plain()
|
|
// We don't want a background for this button, even when accessibility button shapes are enabled, because it's in the navbar.
|
|
config.background.backgroundColor = .clear
|
|
#endif
|
|
config.image = UIImage(systemName: "megaphone.fill")
|
|
config.contentInsets = .zero
|
|
let button = UIButton(configuration: config)
|
|
button.addTarget(self, action: #selector(announcementsButtonPresesd), for: .touchUpInside)
|
|
return button
|
|
}()
|
|
private var unreadAnnouncements: AnnouncementsCollection?
|
|
|
|
init(initialMode: NotificationsMode? = nil, mastodonController: MastodonController) {
|
|
self.initialMode = initialMode
|
|
self.mastodonController = mastodonController
|
|
|
|
super.init(pages: [.all, .mentions]) { page in
|
|
let vc = NotificationsCollectionViewController(allowedTypes: page.allowedTypes, mastodonController: mastodonController)
|
|
vc.title = page.title
|
|
vc.userActivity = page.userActivity(accountID: mastodonController.accountInfo!.id)
|
|
vc.updatesNotificationsMarker = page == .all
|
|
return vc
|
|
}
|
|
|
|
title = Page.all.title
|
|
tabBarItem.image = UIImage(systemName: "bell.fill")
|
|
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: announcementsButton)
|
|
announcementsButton.isHidden = true
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
selectMode(initialMode ?? Preferences.shared.defaultNotificationsMode)
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
Task {
|
|
await checkForAnnouncements()
|
|
}
|
|
}
|
|
|
|
func selectMode(_ mode: NotificationsMode) {
|
|
let page: Page
|
|
switch mode {
|
|
case .allNotifications:
|
|
page = .all
|
|
case .mentionsOnly:
|
|
page = .mentions
|
|
}
|
|
selectPage(page, animated: false)
|
|
}
|
|
|
|
private func checkForAnnouncements() async {
|
|
guard mastodonController.instanceFeatures.instanceAnnouncements else {
|
|
navigationItem.rightBarButtonItem = nil
|
|
return
|
|
}
|
|
let announcements: [Announcement]
|
|
do {
|
|
(announcements, _) = try await mastodonController.run(Announcement.all())
|
|
} catch {
|
|
Logging.general.error("Error fetching announcements: \(String(describing: error))")
|
|
return
|
|
}
|
|
let unread = announcements.filter { $0.read == false }
|
|
if unread.isEmpty {
|
|
unreadAnnouncements = nil
|
|
if #available(iOS 17.0, *) {
|
|
announcementsButton.imageView!.addSymbolEffect(.disappear)
|
|
} else {
|
|
UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseInOut) {
|
|
self.announcementsButton.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
|
|
self.announcementsButton.layer.opacity = 0
|
|
} completion: { _ in
|
|
self.announcementsButton.transform = .identity
|
|
self.announcementsButton.layer.opacity = 1
|
|
}
|
|
}
|
|
} else {
|
|
announcementsButton.isHidden = false
|
|
announcementsButton.layer.opacity = 1
|
|
unreadAnnouncements = AnnouncementsCollection(announcements: unread)
|
|
if #available(iOS 17.0, *) {
|
|
// make sure to remove the .disappear effect, which stays around indefinitely
|
|
announcementsButton.imageView!.removeAllSymbolEffects()
|
|
announcementsButton.imageView!.addSymbolEffect(.bounce)
|
|
} else {
|
|
UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseInOut) {
|
|
self.announcementsButton.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
|
|
} completion: { _ in
|
|
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseInOut) {
|
|
self.announcementsButton.transform = .identity
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@objc private func announcementsButtonPresesd() {
|
|
guard let unreadAnnouncements else {
|
|
return
|
|
}
|
|
show(AnnouncementsHostingController(announcements: unreadAnnouncements, mastodonController: mastodonController), sender: nil)
|
|
}
|
|
}
|
|
|
|
extension NotificationsPageViewController {
|
|
enum Page: SegmentedPageViewControllerPage {
|
|
case all
|
|
case mentions
|
|
|
|
var title: String {
|
|
switch self {
|
|
case .all:
|
|
return NSLocalizedString("Notifications", comment: "notifications tab title")
|
|
case .mentions:
|
|
return NSLocalizedString("Mentions", comment: "mentions tab title")
|
|
}
|
|
}
|
|
|
|
var segmentedControlTitle: String {
|
|
title
|
|
}
|
|
|
|
var allowedTypes: [Pachyderm.Notification.Kind] {
|
|
switch self {
|
|
case .all:
|
|
var set = Set(Pachyderm.Notification.Kind.allCases)
|
|
set.remove(.unknown)
|
|
return Array(set)
|
|
case .mentions:
|
|
return [.mention]
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
func userActivity(accountID: String) -> NSUserActivity {
|
|
switch self {
|
|
case .all:
|
|
return UserActivityManager.checkNotificationsActivity(mode: .allNotifications, accountID: accountID)
|
|
case .mentions:
|
|
return UserActivityManager.checkNotificationsActivity(mode: .mentionsOnly, accountID: accountID)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension NotificationsPageViewController: StateRestorableViewController {
|
|
func stateRestorationActivity() -> NSUserActivity? {
|
|
return currentPage.userActivity(accountID: mastodonController.accountInfo!.id)
|
|
}
|
|
}
|