Skip to content

Commit

Permalink
Merge pull request #393 from LePips/improve-image-views
Browse files Browse the repository at this point in the history
  • Loading branch information
LePips authored Mar 19, 2022
2 parents e72bae1 + 0d69ae5 commit 1ab99a6
Show file tree
Hide file tree
Showing 49 changed files with 320 additions and 152 deletions.
14 changes: 6 additions & 8 deletions Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,10 @@ final class MainCoordinator: NavigationCoordinatable {
barAppearance.tintColor = UIColor(Color.jellyfinPurple)

// Notification setup for state
let nc = SwiftfinNotificationCenter.main
nc.addObserver(self, selector: #selector(didLogIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
nc.addObserver(self, selector: #selector(didLogOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
nc.addObserver(self, selector: #selector(processDeepLink), name: SwiftfinNotificationCenter.Keys.processDeepLink, object: nil)
nc.addObserver(self, selector: #selector(didChangeServerCurrentURI),
name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI, object: nil)
Notifications[.didSignIn].subscribe(self, selector: #selector(didSignIn))
Notifications[.didSignOut].subscribe(self, selector: #selector(didSignOut))
Notifications[.processDeepLink].subscribe(self, selector: #selector(processDeepLink(_:)))
Notifications[.didChangeServerCurrentURI].subscribe(self, selector: #selector(didChangeServerCurrentURI(_:)))

Defaults.publisher(.appAppearance)
.sink { _ in
Expand All @@ -60,13 +58,13 @@ final class MainCoordinator: NavigationCoordinatable {
}

@objc
func didLogIn() {
func didSignIn() {
LogManager.shared.log.info("Received `didSignIn` from SwiftfinNotificationCenter.")
root(\.mainTab)
}

@objc
func didLogOut() {
func didSignOut() {
LogManager.shared.log.info("Received `didSignOut` from SwiftfinNotificationCenter.")
root(\.serverList)
}
Expand Down
9 changes: 4 additions & 5 deletions Shared/Coordinators/MainCoordinator/tvOSMainCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,18 @@ final class MainCoordinator: NavigationCoordinatable {
DataLoader.sharedUrlCache.diskCapacity = 1000 * 1024 * 1024 // 1000MB disk

// Notification setup for state
let nc = SwiftfinNotificationCenter.main
nc.addObserver(self, selector: #selector(didLogIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
nc.addObserver(self, selector: #selector(didLogOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
Notifications[.didSignIn].subscribe(self, selector: #selector(didSignIn))
Notifications[.didSignOut].subscribe(self, selector: #selector(didSignOut))
}

@objc
func didLogIn() {
func didSignIn() {
LogManager.shared.log.info("Received `didSignIn` from NSNotificationCenter.")
root(\.mainTab)
}

@objc
func didLogOut() {
func didSignOut() {
LogManager.shared.log.info("Received `didSignOut` from NSNotificationCenter.")
root(\.serverList)
}
Expand Down
8 changes: 4 additions & 4 deletions Shared/Singleton/SessionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ final class SessionManager {
Defaults[.lastServerUserID] = user.id

currentLogin = (server: currentServer.state, user: currentUser.state)
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
Notifications[.didSignIn].post()
})
.map { _, user, _ in
user.state
Expand All @@ -255,7 +255,7 @@ final class SessionManager {
Defaults[.lastServerUserID] = user.id
setAuthHeader(with: user.accessToken)
currentLogin = (server: server, user: user)
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
Notifications[.didSignIn].post()
}

// MARK: logout
Expand All @@ -265,7 +265,7 @@ final class SessionManager {
JellyfinAPI.basePath = ""
setAuthHeader(with: "")
Defaults[.lastServerUserID] = nil
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
Notifications[.didSignOut].post()
}

// MARK: purge
Expand All @@ -278,7 +278,7 @@ final class SessionManager {
delete(server: server)
}

SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didPurge, object: nil)
Notifications[.didPurge].post()
}

// MARK: delete user
Expand Down
61 changes: 52 additions & 9 deletions Shared/Singleton/SwiftfinNotificationCenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,63 @@

import Foundation

enum SwiftfinNotificationCenter {
class SwiftfinNotification {

private let notificationName: Notification.Name

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

func post(object: Any? = nil) {
Notifications.main.post(name: notificationName, object: object)
}

func subscribe(_ observer: Any, selector: Selector) {
Notifications.main.addObserver(observer, selector: selector, name: notificationName, object: nil)
}

func unsubscribe(_ observer: Any) {
Notifications.main.removeObserver(self, name: notificationName, object: nil)
}
}

enum Notifications {

static let main: NotificationCenter = {
NotificationCenter()
}()

enum Keys {
static let didSignIn = Notification.Name("didSignIn")
static let didSignOut = Notification.Name("didSignOut")
static let processDeepLink = Notification.Name("processDeepLink")
static let didPurge = Notification.Name("didPurge")
static let didChangeServerCurrentURI = Notification.Name("didChangeCurrentLoginURI")
final class Key {
public typealias NotificationKey = Notifications.Key

public let key: String
public let underlyingNotification: SwiftfinNotification

// Send with an item id to check if current item for item views
static let didSendStopReport = Notification.Name("didSendStopReport")
public init(_ key: String) {
self.key = key
self.underlyingNotification = SwiftfinNotification(Notification.Name(key))
}
}

static subscript(key: Key) -> SwiftfinNotification {
key.underlyingNotification
}

static func unsubscribe(_ observer: Any) {
main.removeObserver(observer)
}
}

extension Notifications.Key {

static let didSignIn = NotificationKey("didSignIn")
static let didSignOut = NotificationKey("didSignOut")
static let processDeepLink = NotificationKey("processDeepLink")
static let didPurge = NotificationKey("didPurge")
static let didChangeServerCurrentURI = NotificationKey("didChangeCurrentLoginURI")
static let toggleOfflineMode = NotificationKey("toggleOfflineMode")
static let didDeleteOfflineItem = NotificationKey("didDeleteOfflineItem")
static let didAddDownload = NotificationKey("didAddDownload")
static let didSendStopReport = NotificationKey("didSendStopReport")
}
5 changes: 2 additions & 3 deletions Shared/ViewModels/HomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ final class HomeViewModel: ViewModel {
// Nov. 6, 2021
// This is a workaround since Stinsen doesn't have the ability to rebuild a root at the time of writing.
// See ServerDetailViewModel.swift for feature request issue
let nc = SwiftfinNotificationCenter.main
nc.addObserver(self, selector: #selector(didSignIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
nc.addObserver(self, selector: #selector(didSignOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
Notifications[.didSignIn].subscribe(self, selector: #selector(didSignIn))
Notifications[.didSignOut].subscribe(self, selector: #selector(didSignOut))
}

@objc
Expand Down
7 changes: 2 additions & 5 deletions Shared/ViewModels/ItemViewModel/ItemViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ class ItemViewModel: ViewModel {

getSimilarItems()

SwiftfinNotificationCenter.main.addObserver(self,
selector: #selector(receivedStopReport(_:)),
name: SwiftfinNotificationCenter.Keys.didSendStopReport,
object: nil)
Notifications[.didSendStopReport].subscribe(self, selector: #selector(receivedStopReport(_:)))

refreshItemVideoPlayerViewModel(for: item)
}
Expand All @@ -72,7 +69,7 @@ class ItemViewModel: ViewModel {
} else {
// Remove if necessary. Note that this cannot be in deinit as
// holding as an observer won't allow the object to be deinit-ed
SwiftfinNotificationCenter.main.removeObserver(self)
Notifications.unsubscribe(self)
}
}

Expand Down
3 changes: 1 addition & 2 deletions Shared/ViewModels/ServerDetailViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ class ServerDetailViewModel: ViewModel {
} receiveValue: { newServerState in
self.server = newServerState

let nc = SwiftfinNotificationCenter.main
nc.post(name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI, object: newServerState)
Notifications[.didChangeServerCurrentURI].post(object: newServerState)
}
.store(in: &cancellables)
}
Expand Down
3 changes: 1 addition & 2 deletions Shared/ViewModels/ServerListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ class ServerListViewModel: ObservableObject {
// This is a workaround since Stinsen doesn't have the ability to rebuild a root at the time of writing.
// Feature request issue: https://github.com/rundfunk47/stinsen/issues/33
// Go to each MainCoordinator and implement the rebuild of the root when receiving the notification
let nc = SwiftfinNotificationCenter.main
nc.addObserver(self, selector: #selector(didPurge), name: SwiftfinNotificationCenter.Keys.didPurge, object: nil)
Notifications[.didPurge].subscribe(self, selector: #selector(didPurge))
}

func fetchServers() {
Expand Down
4 changes: 1 addition & 3 deletions Shared/ViewModels/UserListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ class UserListViewModel: ViewModel {

super.init()

let nc = SwiftfinNotificationCenter.main
nc.addObserver(self, selector: #selector(didChangeCurrentLoginURI), name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI,
object: nil)
Notifications[.didChangeServerCurrentURI].subscribe(self, selector: #selector(didChangeCurrentLoginURI(_:)))
}

@objc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,7 @@ extension VideoPlayerViewModel {
self.handleAPIRequestError(completion: completion)
} receiveValue: { _ in
LogManager.shared.log.debug("Stop report sent for item: \(self.item.id ?? "No ID")")
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSendStopReport,
object: self.item.id)
Notifications[.didSendStopReport].post(object: self.item.id)
}
.store(in: &cancellables)
}
Expand Down
63 changes: 63 additions & 0 deletions Shared/Views/BlurHashView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// 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) 2022 Jellyfin & Jellyfin Contributors
//

import SwiftUI
import UIKit

struct BlurHashView: UIViewRepresentable {

let blurHash: String

func makeUIView(context: Context) -> UIBlurHashView {
UIBlurHashView(blurHash)
}

func updateUIView(_ uiView: UIBlurHashView, context: Context) {}
}

class UIBlurHashView: UIView {

private let imageView: UIImageView

init(_ blurHash: String) {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
self.imageView = imageView

super.init(frame: .zero)

computeBlurHashImageAsync(blurHash: blurHash) { [weak self] blurImage in
guard let self = self else { return }
DispatchQueue.main.async {
self.imageView.image = blurImage
self.imageView.setNeedsDisplay()
}
}

addSubview(imageView)

NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: topAnchor),
imageView.bottomAnchor.constraint(equalTo: bottomAnchor),
imageView.leftAnchor.constraint(equalTo: leftAnchor),
imageView.rightAnchor.constraint(equalTo: rightAnchor),
])
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func computeBlurHashImageAsync(blurHash: String, _ completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global(qos: .utility).async {
let image = UIImage(blurHash: blurHash, size: .Circle(radius: 12))
completion(image)
}
}
}
Loading

0 comments on commit 1ab99a6

Please sign in to comment.