Skip to content

Commit

Permalink
Refactor PosterButton and libraries, good UICollectionViews, prop…
Browse files Browse the repository at this point in the history
…er orientation handling, and more (#905)
  • Loading branch information
LePips authored Mar 11, 2024
1 parent 11cc5f5 commit a645444
Show file tree
Hide file tree
Showing 285 changed files with 6,643 additions and 5,793 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions PreferencesView/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "swizzleswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/MarioIannotta/SwizzleSwift",
"state" : {
"branch" : "master",
"revision" : "e2d31c646182bf94a496b173c6ee5ad191230e9a"
}
}
],
"version" : 2
}
26 changes: 26 additions & 0 deletions PreferencesView/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version: 5.9

import PackageDescription

let package = Package(
name: "PreferencesView",
platforms: [
.iOS(.v15),
.tvOS(.v15),
],
products: [
.library(
name: "PreferencesView",
targets: ["PreferencesView"]
),
],
dependencies: [
.package(url: "https://github.com/MarioIannotta/SwizzleSwift", branch: "master"),
],
targets: [
.target(
name: "PreferencesView",
dependencies: [.product(name: "SwizzleSwift", package: "SwizzleSwift")]
),
]
)
1 change: 1 addition & 0 deletions PreferencesView/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PreferencesView
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
class Box {

enum SelectorType {
case single
case multi
weak var value: UIPreferencesHostingController?

init() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
import UIKit

struct KeyCommandAction {
public struct KeyCommandAction {

let title: String
let subtitle: String?
let input: String
let modifierFlags: UIKeyModifierFlags
let action: () -> Void

init(
public init(
title: String,
subtitle: String? = nil,
input: String,
modifierFlags: UIKeyModifierFlags = [],
action: @escaping () -> Void
) {
self.title = title
self.subtitle = subtitle
self.input = input
self.modifierFlags = modifierFlags
self.action = action
Expand All @@ -31,7 +33,7 @@ struct KeyCommandAction {

extension KeyCommandAction: Equatable {

static func == (lhs: KeyCommandAction, rhs: KeyCommandAction) -> Bool {
public static func == (lhs: KeyCommandAction, rhs: KeyCommandAction) -> Bool {
lhs.input == rhs.input
}
}
37 changes: 37 additions & 0 deletions PreferencesView/Sources/PreferencesView/KeyCommandsBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// 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

@resultBuilder
public enum KeyCommandsBuilder {

public static func buildBlock(_ components: [KeyCommandAction]...) -> [KeyCommandAction] {
components.flatMap { $0 }
}

public static func buildExpression(_ expression: KeyCommandAction) -> [KeyCommandAction] {
[expression]
}

public static func buildOptional(_ component: [KeyCommandAction]?) -> [KeyCommandAction] {
component ?? []
}

public static func buildEither(first component: [KeyCommandAction]) -> [KeyCommandAction] {
component
}

public static func buildEither(second component: [KeyCommandAction]) -> [KeyCommandAction] {
component
}

public static func buildArray(_ components: [[KeyCommandAction]]) -> [KeyCommandAction] {
components.flatMap { $0 }
}
}
43 changes: 43 additions & 0 deletions PreferencesView/Sources/PreferencesView/PreferenceKeys.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// 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 SwiftUI

#if os(iOS)
struct KeyCommandsPreferenceKey: PreferenceKey {

static var defaultValue: [KeyCommandAction] = []

static func reduce(value: inout [KeyCommandAction], nextValue: () -> [KeyCommandAction]) {
value.append(contentsOf: nextValue())
}
}

struct PreferredScreenEdgesDeferringSystemGesturesPreferenceKey: PreferenceKey {

static var defaultValue: UIRectEdge = [.left, .right]

static func reduce(value: inout UIRectEdge, nextValue: () -> UIRectEdge) {}
}

struct PrefersHomeIndicatorAutoHiddenPreferenceKey: PreferenceKey {

static var defaultValue: Bool = false

static func reduce(value: inout Bool, nextValue: () -> Bool) {
value = nextValue() || value
}
}

struct SupportedOrientationsPreferenceKey: PreferenceKey {

static var defaultValue: UIInterfaceOrientationMask = .allButUpsideDown

static func reduce(value: inout UIInterfaceOrientationMask, nextValue: () -> UIInterfaceOrientationMask) {}
}
#endif
26 changes: 26 additions & 0 deletions PreferencesView/Sources/PreferencesView/PreferencesView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// 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 SwiftUI
import SwizzleSwift

public struct PreferencesView<Content: View>: UIViewControllerRepresentable {

private var content: () -> Content

public init(@ViewBuilder content: @escaping () -> Content) {
_ = UIViewController.swizzlePreferences
self.content = content
}

public func makeUIViewController(context: Context) -> UIPreferencesHostingController {
UIPreferencesHostingController(content: content)
}

public func updateUIViewController(_ uiViewController: UIPreferencesHostingController, context: Context) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// 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 SwiftUI

public class UIPreferencesHostingController: UIHostingController<AnyView> {

init<Content: View>(@ViewBuilder content: @escaping () -> Content) {
let box = Box()
let rootView = AnyView(
content()
#if os(iOS)
.onPreferenceChange(KeyCommandsPreferenceKey.self) {
box.value?._keyCommandActions = $0
}
.onPreferenceChange(PrefersHomeIndicatorAutoHiddenPreferenceKey.self) {
box.value?._prefersHomeIndicatorAutoHidden = $0
}
.onPreferenceChange(PreferredScreenEdgesDeferringSystemGesturesPreferenceKey.self) {
box.value?._preferredScreenEdgesDeferringSystemGestures = $0
}
.onPreferenceChange(SupportedOrientationsPreferenceKey.self) {
box.value?._orientations = $0
}
#endif
)

super.init(rootView: rootView)

box.value = self
}

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

#if os(iOS)

// MARK: Key Commands

private var _keyCommandActions: [KeyCommandAction] = [] {
willSet {
_keyCommands = newValue.map { action in
let keyCommand = UIKeyCommand(
title: action.title,
action: #selector(keyCommandHit),
input: String(action.input),
modifierFlags: action.modifierFlags
)

keyCommand.subtitle = action.subtitle
keyCommand.wantsPriorityOverSystemBehavior = true

return keyCommand
}
}
}

private var _keyCommands: [UIKeyCommand] = []

override public var keyCommands: [UIKeyCommand]? {
_keyCommands
}

@objc
private func keyCommandHit(keyCommand: UIKeyCommand) {
guard let action = _keyCommandActions
.first(where: { $0.input == keyCommand.input && $0.modifierFlags == keyCommand.modifierFlags }) else { return }
action.action()
}

// MARK: Orientation

var _orientations: UIInterfaceOrientationMask = .all {
didSet {
if #available(iOS 16, *) {
setNeedsUpdateOfSupportedInterfaceOrientations()
}
}
}

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
_orientations
}

// MARK: Defer Edges

private var _preferredScreenEdgesDeferringSystemGestures: UIRectEdge = [.left, .right] {
didSet { setNeedsUpdateOfScreenEdgesDeferringSystemGestures() }
}

override public var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
_preferredScreenEdgesDeferringSystemGestures
}

// MARK: Home Indicator Auto Hidden

private var _prefersHomeIndicatorAutoHidden = false {
didSet { setNeedsUpdateOfHomeIndicatorAutoHidden() }
}

override public var prefersHomeIndicatorAutoHidden: Bool {
_prefersHomeIndicatorAutoHidden
}

#endif
}
Loading

0 comments on commit a645444

Please sign in to comment.