Skip to content

Commit

Permalink
Static Notification Payloads, Move more to IdentifiedArray (jellyfi…
Browse files Browse the repository at this point in the history
…n#1349)

* wip

* wip

* wip

* wip

* clean up

* clean up

* Update VideoPlayerManager.swift

* clean up
  • Loading branch information
LePips authored Dec 9, 2024
1 parent e856303 commit c8acd78
Show file tree
Hide file tree
Showing 32 changed files with 376 additions and 269 deletions.
15 changes: 5 additions & 10 deletions RedrawOnNotificationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,23 @@

import SwiftUI

struct RedrawOnNotificationView<Content: View>: View {
struct RedrawOnNotificationView<Content: View, P>: View {

@State
private var id = 0

private let name: NSNotification.Name
private let key: Notifications.Key<P>
private let content: () -> Content

init(name: NSNotification.Name, @ViewBuilder content: @escaping () -> Content) {
self.name = name
self.content = content
}

init(_ swiftfinNotification: Notifications.Key, @ViewBuilder content: @escaping () -> Content) {
self.name = swiftfinNotification.underlyingNotification.name
init(_ key: Notifications.Key<P>, @ViewBuilder content: @escaping () -> Content) {
self.key = key
self.content = content
}

var body: some View {
content()
.id(id)
.onNotification(name) { _ in
.onNotification(key) { _ in
id += 1
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@

import SwiftUI

struct OnReceiveNotificationModifier: ViewModifier {
struct OnReceiveNotificationModifier<P, K: Notifications.Key<P>>: ViewModifier {

let notification: NSNotification.Name
let onReceive: (Notification) -> Void
let key: K
let onReceive: (P) -> Void

func body(content: Content) -> some View {
content
.onReceive(NotificationCenter.default.publisher(for: notification)) {
onReceive($0)
}
.onReceive(key.publisher, perform: onReceive)
}
}
13 changes: 2 additions & 11 deletions Shared/Extensions/ViewExtensions/ViewExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -314,19 +314,10 @@ extension View {
}
}

func onNotification(_ name: NSNotification.Name, perform action: @escaping (Notification) -> Void) -> some View {
func onNotification<P>(_ key: Notifications.Key<P>, perform action: @escaping (P) -> Void) -> some View {
modifier(
OnReceiveNotificationModifier(
notification: name,
onReceive: action
)
)
}

func onNotification(_ swiftfinNotification: Notifications.Key, perform action: @escaping (Notification) -> Void) -> some View {
modifier(
OnReceiveNotificationModifier(
notification: swiftfinNotification.underlyingNotification.name,
key: key,
onReceive: action
)
)
Expand Down
27 changes: 27 additions & 0 deletions Shared/Objects/NotificationSet.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation

/// A container for `Notifications.Key`.
struct NotificationSet {

private var names: Set<String> = []

func contains<P>(_ key: Notifications.Key<P>) -> Bool {
names.contains(key.name.rawValue)
}

mutating func insert<P>(_ key: Notifications.Key<P>) {
names.insert(key.name.rawValue)
}

mutating func remove<P>(_ key: Notifications.Key<P>) {
names.remove(key.name.rawValue)
}
}
184 changes: 184 additions & 0 deletions Shared/Services/Notifications.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Combine
import Factory
import Foundation
import JellyfinAPI
import UIKit

extension Container {
var notificationCenter: Factory<NotificationCenter> {
self { NotificationCenter.default }.singleton
}
}

enum Notifications {

typealias Keys = _AnyKey

class _AnyKey {
typealias Key = Notifications.Key
}

final class Key<Payload>: _AnyKey {

@Injected(\.notificationCenter)
private var notificationCenter

let name: Notification.Name

var rawValue: String {
name.rawValue
}

init(_ string: String) {
self.name = Notification.Name(string)
}

init(_ name: Notification.Name) {
self.name = name
}

func post(_ payload: Payload) {
notificationCenter
.post(
name: name,
object: nil,
userInfo: ["payload": payload]
)
}

func post() where Payload == Void {
notificationCenter
.post(
name: name,
object: nil,
userInfo: nil
)
}

var publisher: AnyPublisher<Payload, Never> {
notificationCenter
.publisher(for: name)
.compactMap { notification in
notification.userInfo?["payload"] as? Payload
}
.eraseToAnyPublisher()
}

func subscribe(_ object: Any, selector: Selector) {
notificationCenter.addObserver(object, selector: selector, name: name, object: nil)
}
}

static subscript<Payload>(key: Key<Payload>) -> Key<Payload> {
key
}
}

// MARK: - Keys

extension Notifications.Key {

// MARK: - Authentication

static var didSignIn: Key<Void> {
Key("didSignIn")
}

static var didSignOut: Key<Void> {
Key("didSignOut")
}

// MARK: - App Flow

static var processDeepLink: Key<Void> {
Key("processDeepLink")
}

static var didPurge: Key<Void> {
Key("didPurge")
}

static var didChangeCurrentServerURL: Key<ServerState> {
Key("didChangeCurrentServerURL")
}

static var didSendStopReport: Key<Void> {
Key("didSendStopReport")
}

static var didRequestGlobalRefresh: Key<Void> {
Key("didRequestGlobalRefresh")
}

static var didFailMigration: Key<Void> {
Key("didFailMigration")
}

// MARK: - Media Items

/// - Payload: The new item with updated metadata.
static var itemMetadataDidChange: Key<BaseItemDto> {
Key("itemMetadataDidChange")
}

static var itemShouldRefresh: Key<(itemID: String, parentID: String?)> {
Key("itemShouldRefresh")
}

/// - Payload: The ID of the deleted item.
static var didDeleteItem: Key<String> {
Key("didDeleteItem")
}

// MARK: - Server

static var didConnectToServer: Key<ServerState> {
Key("didConnectToServer")
}

static var didDeleteServer: Key<ServerState> {
Key("didDeleteServer")
}

// MARK: - User

static var didChangeUserProfileImage: Key<Void> {
Key("didChangeUserProfileImage")
}

static var didAddServerUser: Key<UserDto> {
Key("didAddServerUser")
}

// MARK: - Playback

static var didStartPlayback: Key<Void> {
Key("didStartPlayback")
}

// MARK: - UIApplication

static var applicationDidEnterBackground: Key<Void> {
Key(UIApplication.didEnterBackgroundNotification)
}

static var applicationWillEnterForeground: Key<Void> {
Key(UIApplication.willEnterForegroundNotification)
}

static var applicationWillResignActive: Key<Void> {
Key(UIApplication.willResignActiveNotification)
}

static var applicationWillTerminate: Key<Void> {
Key(UIApplication.willTerminateNotification)
}
}
94 changes: 0 additions & 94 deletions Shared/Services/SwiftfinNotifications.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Shared/ViewModels/ConnectToServerViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ final class ConnectToServerViewModel: ViewModel, Eventful, Stateful {
return editServer.state
}

Notifications[.didChangeCurrentServerURL].post(object: newState)
Notifications[.didChangeCurrentServerURL].post(newState)
} catch {
logger.critical("\(error.localizedDescription)")
}
Expand Down
Loading

0 comments on commit c8acd78

Please sign in to comment.