) {
20 | set.insert(asAnyCancellable())
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Shared/Extensions/Text.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | extension Text {
12 |
13 | init(_ content: some Displayable) {
14 | self.init(verbatim: "\(content.displayTitle)")
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Shared/Extensions/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | var overlayColor: UIColor {
13 | var red: CGFloat = 0
14 | var green: CGFloat = 0
15 | var blue: CGFloat = 0
16 | var alpha: CGFloat = 0
17 |
18 | getRed(&red, green: &green, blue: &blue, alpha: &alpha)
19 |
20 | let brightness = ((red * 299) + (green * 587) + (blue * 114)) / 1000
21 |
22 | return brightness < 0.5 ? .white : .black
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Shared/Extensions/UIGestureRecognizer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | extension UIGestureRecognizer {
12 |
13 | func unitPoint(in view: UIView) -> UnitPoint {
14 | let location = location(in: view)
15 | return .init(x: location.x / view.frame.width, y: location.y / view.frame.height)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Shared/Extensions/UIScreen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIScreen {
12 |
13 | func scale(_ x: Int) -> Int {
14 | Int(nativeScale) * x
15 | }
16 |
17 | func scale(_ x: CGFloat) -> Int {
18 | Int(nativeScale * x)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Shared/Extensions/URLComponents.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | extension URLComponents {
12 |
13 | func addingQueryItem(key: String, value: String?) -> Self {
14 | var copy = self
15 |
16 | if copy.queryItems == nil {
17 | copy.queryItems = []
18 | }
19 |
20 | copy.queryItems?.append(.init(name: key, value: value))
21 | return copy
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Shared/Extensions/URLResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | extension URLResponse {
12 |
13 | var mimeSubtype: String? {
14 | guard let subtype = mimeType?.split(separator: "/")[safe: 1] else { return nil }
15 | return String(subtype)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Shared/Extensions/URLSessionConfiguration.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | extension URLSessionConfiguration {
12 |
13 | /// A session configuration object built upon the default
14 | /// configuration with values for Swiftfin.
15 | static let swiftfin: URLSessionConfiguration = {
16 | .default.mutating(\.timeoutIntervalForRequest, with: 20)
17 | }()
18 | }
19 |
--------------------------------------------------------------------------------
/Shared/Extensions/VerticalAlignment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | extension VerticalAlignment {
12 |
13 | private struct SliderCenterAlignment: AlignmentID {
14 | static func defaultValue(in context: ViewDimensions) -> CGFloat {
15 | context[VerticalAlignment.center]
16 | }
17 | }
18 |
19 | static let sliderCenterAlignmentGuide = VerticalAlignment(
20 | SliderCenterAlignment.self
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/Shared/Extensions/ViewExtensions/Backport/BackPort+ScrollIndicatorVisibility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 | import SwiftUI
11 |
12 | extension Backport {
13 |
14 | enum ScrollIndicatorVisibility {
15 |
16 | case automatic
17 | case visible
18 | case hidden
19 | case never
20 |
21 | @available(iOS 16, tvOS 16, *)
22 | var supportedValue: SwiftUI.ScrollIndicatorVisibility {
23 | switch self {
24 | case .automatic: .automatic
25 | case .visible: .visible
26 | case .hidden: .hidden
27 | case .never: .never
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Shared/Extensions/ViewExtensions/Modifiers/OnFirstAppearModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct OnFirstAppearModifier: ViewModifier {
12 |
13 | @State
14 | private var didAppear = false
15 |
16 | let action: () -> Void
17 |
18 | func body(content: Content) -> some View {
19 | content
20 | .onAppear {
21 | guard !didAppear else { return }
22 | didAppear = true
23 | action()
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Extensions/ViewExtensions/Modifiers/OnReceiveNotificationModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct OnReceiveNotificationModifier>: ViewModifier {
12 |
13 | let key: K
14 | let onReceive: (P) -> Void
15 |
16 | func body(content: Content) -> some View {
17 | content
18 | .onReceive(key.publisher, perform: onReceive)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Shared/Extensions/ViewExtensions/Modifiers/OnScenePhaseChangedModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct OnScenePhaseChangedModifier: ViewModifier {
12 |
13 | @Environment(\.scenePhase)
14 | private var scenePhase
15 |
16 | let phase: ScenePhase
17 | let action: () -> Void
18 |
19 | func body(content: Content) -> some View {
20 | content.onChange(of: scenePhase) { newValue in
21 | if newValue == phase {
22 | action()
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Extensions/ViewExtensions/Modifiers/SinceLastDisappearModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct SinceLastDisappearModifier: ViewModifier {
12 |
13 | @State
14 | private var lastDisappear: Date? = nil
15 |
16 | let action: (TimeInterval) -> Void
17 |
18 | func body(content: Content) -> some View {
19 | content
20 | .onAppear {
21 | guard let lastDisappear else { return }
22 | let interval = Date.now.timeIntervalSince(lastDisappear)
23 | action(interval)
24 | }
25 | .onDisappear {
26 | lastDisappear = Date.now
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Shared/Objects/BindingBox.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Combine
10 | import SwiftUI
11 |
12 | /// Utility for views that are passed a `Binding` that
13 | /// may not be able to respond to view updates from
14 | /// the source
15 | class BindingBox: ObservableObject {
16 |
17 | @Published
18 | var value: Wrapped
19 |
20 | private let source: Binding
21 | private var valueObserver: AnyCancellable!
22 |
23 | init(source: Binding) {
24 | self.source = source
25 | self.value = source.wrappedValue
26 | valueObserver = nil
27 |
28 | valueObserver = $value.sink { [weak self] in
29 | self?.source.wrappedValue = $0
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Shared/Objects/CommaStringBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// Result builder that build a comma-separated string from its components
12 | @resultBuilder
13 | struct CommaStringBuilder where Component: RawRepresentable {
14 |
15 | static func buildBlock(_ components: String...) -> String {
16 | components.joined(separator: ",")
17 | }
18 |
19 | static func buildExpression(_ expression: Component) -> String {
20 | expression.rawValue
21 | }
22 |
23 | static func buildExpression(_ expression: [Component]) -> String {
24 | expression.map(\.rawValue)
25 | .joined(separator: ",")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Shared/Objects/CustomDeviceProfileAction.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum CustomDeviceProfileAction: String, CaseIterable, Displayable, Storable {
13 |
14 | case add
15 | case replace
16 |
17 | var displayTitle: String {
18 | switch self {
19 | case .add:
20 | return L10n.add
21 | case .replace:
22 | return L10n.replace
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Shared/Objects/DisplayOrder/BoxSetDisplayOrder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | enum BoxSetDisplayOrder: String, CaseIterable, Identifiable {
12 | case dateModified = "DateModified"
13 | case sortName = "SortName"
14 | case premiereDate = "PremiereDate"
15 |
16 | var id: String { rawValue }
17 |
18 | var displayTitle: String {
19 | switch self {
20 | case .dateModified:
21 | return L10n.dateModified
22 | case .sortName:
23 | return L10n.sortName
24 | case .premiereDate:
25 | return L10n.premiereDate
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Shared/Objects/Displayable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// A type that is displayed with a title
12 | protocol Displayable {
13 |
14 | var displayTitle: String { get }
15 | }
16 |
--------------------------------------------------------------------------------
/Shared/Objects/Eventful.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Combine
10 | import Foundation
11 |
12 | protocol Eventful {
13 |
14 | associatedtype Event
15 |
16 | var events: AnyPublisher { get }
17 | }
18 |
--------------------------------------------------------------------------------
/Shared/Objects/ImageSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// Represents an image source along with a blur hash and a system image
12 | /// to act as placeholders.
13 | ///
14 | /// If `blurHash` is `nil`, the given system image is used instead.
15 | struct ImageSource: Hashable {
16 |
17 | let url: URL?
18 | let blurHash: String?
19 |
20 | init(
21 | url: URL? = nil,
22 | blurHash: String? = nil
23 | ) {
24 | self.url = url
25 | self.blurHash = blurHash
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Shared/Objects/ItemFilter/AnyItemFilter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// A type-erased instance of an item filter.
12 | struct AnyItemFilter: Displayable, Hashable, ItemFilter {
13 |
14 | let displayTitle: String
15 | let value: String
16 |
17 | init(
18 | displayTitle: String,
19 | value: String
20 | ) {
21 | self.displayTitle = displayTitle
22 | self.value = value
23 | }
24 |
25 | init(from anyFilter: AnyItemFilter) {
26 | self.displayTitle = anyFilter.displayTitle
27 | self.value = anyFilter.value
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Shared/Objects/ItemFilter/ItemGenre.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | struct ItemGenre: Codable, ExpressibleByStringLiteral, Hashable, ItemFilter {
12 |
13 | let value: String
14 |
15 | var displayTitle: String {
16 | value
17 | }
18 |
19 | init(stringLiteral value: String) {
20 | self.value = value
21 | }
22 |
23 | init(from anyFilter: AnyItemFilter) {
24 | self.value = anyFilter.value
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Objects/ItemFilter/ItemTag.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | struct ItemTag: Codable, ExpressibleByStringLiteral, Hashable, ItemFilter {
12 |
13 | let value: String
14 |
15 | var displayTitle: String {
16 | value
17 | }
18 |
19 | init(stringLiteral value: String) {
20 | self.value = value
21 | }
22 |
23 | init(from anyFilter: AnyItemFilter) {
24 | self.value = anyFilter.value
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Objects/ItemFilter/ItemYear.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | struct ItemYear: Codable, ExpressibleByIntegerLiteral, Hashable, ItemFilter {
12 |
13 | let value: String
14 |
15 | var displayTitle: String {
16 | value
17 | }
18 |
19 | var intValue: Int {
20 | Int(value)!
21 | }
22 |
23 | init(integerLiteral value: IntegerLiteralType) {
24 | self.value = "\(value)"
25 | }
26 |
27 | init(from anyFilter: AnyItemFilter) {
28 | self.value = anyFilter.value
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Shared/Objects/ItemViewType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum ItemViewType: String, CaseIterable, Displayable, Defaults.Serializable {
13 |
14 | case compactPoster
15 | case compactLogo
16 | case cinematic
17 |
18 | var displayTitle: String {
19 | switch self {
20 | case .compactPoster:
21 | return L10n.compactPoster
22 | case .compactLogo:
23 | return L10n.compactLogo
24 | case .cinematic:
25 | return L10n.cinematic
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Shared/Objects/LibraryDisplayType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 | import UIKit
12 |
13 | enum LibraryDisplayType: String, CaseIterable, Displayable, Storable, SystemImageable {
14 |
15 | case grid
16 | case list
17 |
18 | // TODO: localize
19 | var displayTitle: String {
20 | switch self {
21 | case .grid:
22 | L10n.grid
23 | case .list:
24 | L10n.list
25 | }
26 | }
27 |
28 | var systemImage: String {
29 | switch self {
30 | case .grid:
31 | "square.grid.2x2.fill"
32 | case .list:
33 | "square.fill.text.grid.1x2"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Shared/Objects/LibraryParent/TitledLibraryParent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 | import JellyfinAPI
11 |
12 | /// A basic structure conforming to `LibraryParent` that is meant to only define its `displayTitle`
13 | struct TitledLibraryParent: LibraryParent {
14 |
15 | let displayTitle: String
16 | let id: String?
17 | let libraryType: BaseItemKind? = nil
18 |
19 | init(displayTitle: String, id: String? = nil) {
20 | self.displayTitle = displayTitle
21 | self.id = id
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Shared/Objects/NotificationSet.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// A container for `Notifications.Key`.
12 | struct NotificationSet {
13 |
14 | private var names: Set = []
15 |
16 | func contains(_ key: Notifications.Key
) -> Bool {
17 | names.contains(key.name.rawValue)
18 | }
19 |
20 | mutating func insert
(_ key: Notifications.Key
) {
21 | names.insert(key.name.rawValue)
22 | }
23 |
24 | mutating func remove
(_ key: Notifications.Key
) {
25 | names.remove(key.name.rawValue)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Shared/Objects/PlaybackCompatibility/PlaybackCompatibility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import JellyfinAPI
11 |
12 | enum PlaybackCompatibility: String, CaseIterable, Defaults.Serializable, Displayable {
13 |
14 | case auto
15 | case mostCompatible
16 | case directPlay
17 | case custom
18 |
19 | var displayTitle: String {
20 | switch self {
21 | case .auto:
22 | return L10n.auto
23 | case .mostCompatible:
24 | return L10n.compatible
25 | case .directPlay:
26 | return L10n.direct
27 | case .custom:
28 | return L10n.custom
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Shared/Objects/PosterDisplayType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | // TODO: think about what to do for square (music)
13 | enum PosterDisplayType: String, CaseIterable, Displayable, Storable, SystemImageable {
14 |
15 | case landscape
16 | case portrait
17 |
18 | var displayTitle: String {
19 | switch self {
20 | case .landscape:
21 | L10n.landscape
22 | case .portrait:
23 | L10n.portrait
24 | }
25 | }
26 |
27 | var systemImage: String {
28 | switch self {
29 | case .landscape:
30 | "rectangle.fill"
31 | case .portrait:
32 | "rectangle.portrait.fill"
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Shared/Objects/RoundedCorner.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct RoundedCorner: Shape {
12 |
13 | let radius: CGFloat
14 | let corners: UIRectCorner
15 |
16 | func path(in rect: CGRect) -> Path {
17 | Path(UIBezierPath(
18 | roundedRect: rect,
19 | byRoundingCorners: corners,
20 | cornerRadii: CGSize(width: radius, height: radius)
21 | ).cgPath)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Shared/Objects/ScalingButtonStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ScalingButtonStyle: ButtonStyle {
12 |
13 | private let animation: Animation
14 | private let scale: CGFloat
15 |
16 | init(scale: CGFloat = 0.8, animation: Animation = .linear(duration: 0.1)) {
17 | self.animation = animation
18 | self.scale = scale
19 | }
20 |
21 | func makeBody(configuration: Configuration) -> some View {
22 | configuration.label
23 | .scaleEffect(configuration.isPressed ? scale : 1)
24 | .animation(animation, value: configuration.isPressed)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Objects/SeriesStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | enum SeriesStatus: String, CaseIterable {
12 | case continuing = "Continuing"
13 | case ended = "Ended"
14 | case unreleased = "Unreleased"
15 |
16 | var displayTitle: String {
17 | switch self {
18 | case .continuing:
19 | return L10n.continuing
20 | case .ended:
21 | return L10n.ended
22 | case .unreleased:
23 | return L10n.unreleased
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Shared/Objects/SliderType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum SliderType: String, CaseIterable, Displayable, Defaults.Serializable {
13 |
14 | case thumb
15 | case capsule
16 |
17 | var displayTitle: String {
18 | switch self {
19 | case .thumb:
20 | return L10n.thumbSlider
21 | case .capsule:
22 | return L10n.capsule
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Shared/Objects/Storable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | /// A type that is able to be stored within:
13 | ///
14 | /// - `Defaults`: UserDefaults
15 | /// - `StoredValue`: AnyData
16 | protocol Storable: Codable, Defaults.Serializable {}
17 |
--------------------------------------------------------------------------------
/Shared/Objects/SupportedCaseIterable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | /// A type that provides a collection of a subset of all of its values.
12 | ///
13 | /// Using types that conform to `CaseIterable` may contain values that
14 | /// aren't supported or valid in certain scenarios.
15 | protocol SupportedCaseIterable: CaseIterable {
16 |
17 | associatedtype SupportedCases: Collection = [Self] where Self == Self.SupportedCases.Element
18 |
19 | static var supportedCases: Self.SupportedCases { get }
20 | }
21 |
22 | extension SupportedCaseIterable where SupportedCases.Element: Equatable {
23 |
24 | var isSupported: Bool {
25 | Self.supportedCases.contains(self)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Shared/Objects/SystemImageable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | protocol SystemImageable {
12 |
13 | var systemImage: String { get }
14 | }
15 |
--------------------------------------------------------------------------------
/Shared/Objects/TextPair.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | struct TextPair: Displayable, Identifiable {
12 |
13 | let title: String
14 | let subtitle: String
15 |
16 | var displayTitle: String {
17 | title
18 | }
19 |
20 | var id: String {
21 | displayTitle.appending(subtitle)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Shared/Objects/TimeStampType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum TimestampType: String, CaseIterable, Defaults.Serializable, Displayable {
13 |
14 | case split
15 | case compact
16 |
17 | var displayTitle: String {
18 | switch self {
19 | case .split:
20 | return L10n.split
21 | case .compact:
22 | return L10n.compact
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Shared/Objects/TrailingTimestampType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum TrailingTimestampType: String, CaseIterable, Displayable, Defaults.Serializable {
13 |
14 | case timeLeft
15 | case totalTime
16 |
17 | var displayTitle: String {
18 | switch self {
19 | case .timeLeft:
20 | return L10n.timeLeft
21 | case .totalTime:
22 | return L10n.totalTime
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Shared/Objects/UserAccessPolicy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | // TODO: require remote sign in every time
12 | // - actually found to be a bit difficult?
13 | // TODO: rename to not confuse with server access/UserDto
14 |
15 | enum UserAccessPolicy: String, CaseIterable, Codable, Displayable {
16 |
17 | case none
18 | case requireDeviceAuthentication
19 | case requirePin
20 |
21 | var displayTitle: String {
22 | switch self {
23 | case .none:
24 | L10n.none
25 | case .requireDeviceAuthentication:
26 | L10n.deviceAuth
27 | case .requirePin:
28 | L10n.pin
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Shared/Objects/UserSignInState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import Foundation
11 |
12 | enum UserSignInState: RawRepresentable, Codable, Defaults.Serializable, Equatable, Hashable {
13 |
14 | case signedOut
15 | case signedIn(userID: String)
16 |
17 | var rawValue: String {
18 | switch self {
19 | case .signedOut:
20 | ""
21 | case let .signedIn(userID):
22 | userID
23 | }
24 | }
25 |
26 | init?(rawValue: String) {
27 | if rawValue.isEmpty {
28 | self = .signedOut
29 | } else {
30 | self = .signedIn(userID: rawValue)
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Shared/Objects/Utilities.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | @inlinable
12 | func clamp(_ x: T, min y: T, max z: T) -> T {
13 | min(max(x, y), z)
14 | }
15 |
16 | @inlinable
17 | func round(_ value: T, toNearest: T) -> T {
18 | round(value / toNearest) * toNearest
19 | }
20 |
21 | @inlinable
22 | func round(_ value: T, toNearest: T) -> T {
23 | T(round(Double(value), toNearest: Double(toNearest)))
24 | }
25 |
--------------------------------------------------------------------------------
/Shared/Services/Keychain.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Factory
10 | import Foundation
11 | import KeychainSwift
12 |
13 | extension Container {
14 |
15 | // TODO: take a look at all security options
16 | var keychainService: Factory { self { KeychainSwift() }.singleton }
17 | }
18 |
--------------------------------------------------------------------------------
/Shared/ViewModels/DownloadListViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Factory
10 | import SwiftUI
11 |
12 | class DownloadListViewModel: ViewModel {
13 |
14 | @Injected(\.downloadManager)
15 | private var downloadManager
16 |
17 | @Published
18 | var items: [DownloadTask] = []
19 |
20 | override init() {
21 | super.init()
22 |
23 | items = downloadManager.downloadedItems()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Shared/ViewModels/ItemViewModel/MovieItemViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Combine
10 | import Foundation
11 | import JellyfinAPI
12 |
13 | final class MovieItemViewModel: ItemViewModel {}
14 |
--------------------------------------------------------------------------------
/Shared/ViewModels/VideoPlayerManager/OnlineVideoPlayerManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 | import JellyfinAPI
11 |
12 | final class OnlineVideoPlayerManager: VideoPlayerManager {
13 |
14 | init(item: BaseItemDto, mediaSource: MediaSourceInfo) {
15 | super.init()
16 |
17 | Task {
18 | let viewModel = try await item.videoPlayerViewModel(with: mediaSource)
19 |
20 | await MainActor.run {
21 | self.currentViewModel = viewModel
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Components/DotHStack.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct DotHStack: View {
12 |
13 | @ViewBuilder
14 | var content: () -> Content
15 |
16 | var body: some View {
17 | SeparatorHStack(content)
18 | .separator {
19 | Circle()
20 | .frame(width: 5, height: 5)
21 | .padding(.horizontal, 10)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Extensions/View/View-tvOS.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 | import SwiftUIIntrospect
12 |
13 | extension View {
14 |
15 | @ViewBuilder
16 | func navigationBarBranding(
17 | isLoading: Bool = false
18 | ) -> some View {
19 | modifier(
20 | NavigationBarBrandingModifier(
21 | isLoading: isLoading
22 | )
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/ImageButtonStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | struct ImageButtonStyle: ButtonStyle {
10 |
11 | let focused: Bool
12 | func makeBody(configuration: Configuration) -> some View {
13 | configuration
14 | .label
15 | .padding(6)
16 | .foregroundColor(Color.white)
17 | .background(Color.blue)
18 | .cornerRadius(100)
19 | .shadow(color: .black, radius: self.focused ? 20 : 0, x: 0, y: 0) // 0
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/1280x768-back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/1280x768-back.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "1280x768-back.png",
5 | "idiom" : "tv"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.imagestacklayer"
9 | },
10 | {
11 | "filename" : "Back.imagestacklayer"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/512.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "512.png",
5 | "idiom" : "tv"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/400x240-back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/400x240-back.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "400x240-back.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "Webp.net-resizeimage.png",
10 | "idiom" : "tv",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "author" : "xcode",
16 | "version" : 1
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Webp.net-resizeimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Webp.net-resizeimage.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "layers" : [
7 | {
8 | "filename" : "Front.imagestacklayer"
9 | },
10 | {
11 | "filename" : "Back.imagestacklayer"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/216.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/216.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "216.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "Webp.net-resizeimage-2.png",
10 | "idiom" : "tv",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "author" : "xcode",
16 | "version" : 1
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Webp.net-resizeimage-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Webp.net-resizeimage-2.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets" : [
3 | {
4 | "filename" : "App Icon - App Store.imagestack",
5 | "idiom" : "tv",
6 | "role" : "primary-app-icon",
7 | "size" : "1280x768"
8 | },
9 | {
10 | "filename" : "App Icon.imagestack",
11 | "idiom" : "tv",
12 | "role" : "primary-app-icon",
13 | "size" : "400x240"
14 | },
15 | {
16 | "filename" : "Top Shelf Image Wide.imageset",
17 | "idiom" : "tv",
18 | "role" : "top-shelf-image-wide",
19 | "size" : "2320x720"
20 | },
21 | {
22 | "filename" : "Top Shelf Image.imageset",
23 | "idiom" : "tv",
24 | "role" : "top-shelf-image",
25 | "size" : "1920x720"
26 | }
27 | ],
28 | "info" : {
29 | "author" : "xcode",
30 | "version" : 1
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "top shelf.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "Untitled-1.png",
10 | "idiom" : "tv",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "top shelf-1.png",
15 | "idiom" : "tv-marketing",
16 | "scale" : "1x"
17 | },
18 | {
19 | "filename" : "Untitled-2.png",
20 | "idiom" : "tv-marketing",
21 | "scale" : "2x"
22 | }
23 | ],
24 | "info" : {
25 | "author" : "xcode",
26 | "version" : 1
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Untitled-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Untitled-1.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Untitled-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Untitled-2.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top shelf-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top shelf-1.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top shelf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/top shelf.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "top shelf.png",
5 | "idiom" : "tv",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "Untitled-2.png",
10 | "idiom" : "tv",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "top shelf-1.png",
15 | "idiom" : "tv-marketing",
16 | "scale" : "1x"
17 | },
18 | {
19 | "filename" : "Untitled-1.png",
20 | "idiom" : "tv-marketing",
21 | "scale" : "2x"
22 | }
23 | ],
24 | "info" : {
25 | "author" : "xcode",
26 | "version" : 1
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Untitled-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Untitled-1.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Untitled-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Untitled-2.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/top shelf-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/top shelf-1.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/top shelf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin tvOS/Resources/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/top shelf.png
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/jellyfin-blob-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "jellyfin-blob.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/tomato.fresh.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "tomato.fresh.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Resources/Assets.xcassets/tomato.rotten.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "tomato.rotten.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/ItemView/CollectionItemView/CollectionItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct CollectionItemView: View {
12 |
13 | @ObservedObject
14 | var viewModel: CollectionItemViewModel
15 |
16 | var body: some View {
17 | ItemView.CinematicScrollView(viewModel: viewModel) {
18 | ContentView(viewModel: viewModel)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/ItemView/EpisodeItemView/EpisodeItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EpisodeItemView: View {
12 |
13 | @ObservedObject
14 | var viewModel: EpisodeItemViewModel
15 |
16 | var body: some View {
17 | ItemView.CinematicScrollView(viewModel: viewModel) {
18 | ContentView(viewModel: viewModel)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/ItemView/MovieItemView/MovieItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct MovieItemView: View {
12 |
13 | @ObservedObject
14 | var viewModel: MovieItemViewModel
15 |
16 | var body: some View {
17 | ItemView.CinematicScrollView(viewModel: viewModel) {
18 | ContentView(viewModel: viewModel)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/ItemView/SeriesItemView/SeriesItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct SeriesItemView: View {
12 |
13 | @ObservedObject
14 | var viewModel: SeriesItemViewModel
15 |
16 | var body: some View {
17 | ItemView.CinematicScrollView(viewModel: viewModel) {
18 | ContentView(viewModel: viewModel)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/ListColumnsPickerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | struct ListColumnsPickerView: View {
13 |
14 | @Binding
15 | var selection: Int
16 |
17 | var body: some View {
18 | StepperView(
19 | title: L10n.columns,
20 | value: $selection,
21 | range: 1 ... 3,
22 | step: 1
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/SettingsView/ExperimentalSettingsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | // Note: Used for experimental settings that may be removed or implemented
13 | // officially. Keep for future settings.
14 |
15 | struct ExperimentalSettingsView: View {
16 |
17 | var body: some View {
18 | SplitFormWindowView()
19 | .descriptionView {
20 | Image(systemName: "gearshape")
21 | .resizable()
22 | .aspectRatio(contentMode: .fit)
23 | .frame(maxWidth: 400)
24 | }
25 | .contentView {}
26 | .navigationTitle(L10n.experimental)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/VideoPlayer/Overlays/Components/ActionButtons/ActionButtons.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | extension VideoPlayer.Overlay {
12 |
13 | enum ActionButtons {}
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin tvOS/Views/VideoPlayer/Overlays/ConfirmCloseOverlay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ConfirmCloseOverlay: View {
12 | var body: some View {
13 | VStack {
14 | HStack {
15 | Image(systemName: "xmark.circle.fill")
16 | .font(.system(size: 96))
17 | .padding(3)
18 | .background(Color.black.opacity(0.4).mask(Circle()))
19 |
20 | Spacer()
21 | }
22 | .padding()
23 |
24 | Spacer()
25 | }
26 | .padding()
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Swiftfin.xcodeproj/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | // Swiftfin is subject to the terms of the Mozilla Public
8 | // License, v2.0. If a copy of the MPL was not distributed with this
9 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
10 | //
11 | // Copyright (c) ___YEAR___ Jellyfin & Jellyfin Contributors
12 | //
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Swiftfin/Components/DotHStack.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct DotHStack: View {
12 |
13 | @ViewBuilder
14 | var content: () -> Content
15 |
16 | var body: some View {
17 | SeparatorHStack(content)
18 | .separator {
19 | Circle()
20 | .frame(width: 2, height: 2)
21 | .padding(.horizontal, 5)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Swiftfin/Components/Video3DFormatPicker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | struct Video3DFormatPicker: View {
13 | let title: String
14 | @Binding
15 | var selectedFormat: Video3DFormat?
16 |
17 | var body: some View {
18 | Picker(title, selection: $selectedFormat) {
19 | Text(L10n.none).tag(nil as Video3DFormat?)
20 | ForEach(Video3DFormat.allCases, id: \.self) { format in
21 | Text(format.displayTitle).tag(format as Video3DFormat?)
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Swiftfin/Components/iOS15View.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | // TODO: remove when iOS 15 support removed
12 | struct iOS15View: View {
13 |
14 | let iOS15: () -> iOS15Content
15 | let content: () -> Content
16 |
17 | var body: some View {
18 | if #available(iOS 16, *) {
19 | content()
20 | } else {
21 | iOS15()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Swiftfin/Extensions/View/Modifiers/DetectOrientationModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct DetectOrientation: ViewModifier {
12 |
13 | @Binding
14 | var orientation: UIDeviceOrientation
15 |
16 | func body(content: Content) -> some View {
17 | content
18 | .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
19 | orientation = UIDevice.current.orientation
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Swiftfin/Extensions/View/Modifiers/NavigationBarDrawerButtons/NavigationBarDrawerModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct NavigationBarDrawerModifier: ViewModifier {
12 |
13 | private let drawer: () -> Drawer
14 |
15 | init(@ViewBuilder drawer: @escaping () -> Drawer) {
16 | self.drawer = drawer
17 | }
18 |
19 | func body(content: Content) -> some View {
20 | NavigationBarDrawerView {
21 | drawer()
22 | .ignoresSafeArea()
23 | } content: {
24 | content
25 | }
26 | .ignoresSafeArea()
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin/Extensions/View/Modifiers/NavigationBarOffset/NavigationBarOffsetModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct NavigationBarOffsetModifier: ViewModifier {
12 |
13 | @Binding
14 | var scrollViewOffset: CGFloat
15 |
16 | let start: CGFloat
17 | let end: CGFloat
18 |
19 | func body(content: Content) -> some View {
20 | NavigationBarOffsetView(
21 | scrollViewOffset: $scrollViewOffset,
22 | start: start,
23 | end: end
24 | ) {
25 | content
26 | }
27 | .ignoresSafeArea()
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Swiftfin/Objects/DeepLink.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 | import JellyfinAPI
11 |
12 | enum DeepLink {
13 | case item(BaseItemDto)
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-blue.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-green.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-green.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-jellyfin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-jellyfin.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-orange.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-orange.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-red.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-red.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-dark-yellow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-yellow.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-blue.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-green.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-green.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-jellyfin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-jellyfin.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-orange.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-orange.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-red.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-red.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedDark-yellow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedDark-yellow.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-blue.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-green.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-green.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-jellyfin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-jellyfin.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-orange.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-orange.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-red.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-red.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-invertedLight-yellow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-invertedLight-yellow.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-blue.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-green.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-green.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-jellyfin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-jellyfin.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-orange.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-orange.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-red.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-red.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-light-yellow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-yellow.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcon-primary-primary.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-primary-primary.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-blue.appiconset/AppIcon-dark-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-blue.appiconset/AppIcon-dark-blue.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-blue.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-blue.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-green.appiconset/AppIcon-dark-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-green.appiconset/AppIcon-dark-green.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-green.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-green.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-jellyfin.appiconset/AppIcon-dark-jellyfin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-jellyfin.appiconset/AppIcon-dark-jellyfin.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-jellyfin.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-jellyfin.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-orange.appiconset/AppIcon-dark-orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-orange.appiconset/AppIcon-dark-orange.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-orange.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-orange.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-red.appiconset/AppIcon-dark-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-red.appiconset/AppIcon-dark-red.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-red.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-red.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-yellow.appiconset/AppIcon-dark-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-yellow.appiconset/AppIcon-dark-yellow.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/AppIcon-dark-yellow.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-dark-yellow.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Dark/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-blue.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "blue.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-blue.appiconset/blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-blue.appiconset/blue.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-green.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "green.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-green.appiconset/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-green.appiconset/green.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-jellyfin.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "jellyfin.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-jellyfin.appiconset/jellyfin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-jellyfin.appiconset/jellyfin.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-orange.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "orange.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-orange.appiconset/orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-orange.appiconset/orange.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-red.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "red.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-red.appiconset/red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-red.appiconset/red.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-yellow.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "yellow.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-yellow.appiconset/yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/AppIcon-invertedDark-yellow.appiconset/yellow.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Dark/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-blue.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "blue.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-blue.appiconset/blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-blue.appiconset/blue.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-green.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "green.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-green.appiconset/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-green.appiconset/green.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-jellyfin.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "jellyfin.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-jellyfin.appiconset/jellyfin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-jellyfin.appiconset/jellyfin.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-orange.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "orange.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-orange.appiconset/orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-orange.appiconset/orange.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-red.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "red.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-red.appiconset/red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-red.appiconset/red.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-yellow.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "yellow.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-yellow.appiconset/yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/AppIcon-invertedLight-yellow.appiconset/yellow.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Inverted-Light/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-blue.appiconset/AppIcon-light-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-blue.appiconset/AppIcon-light-blue.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-blue.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-blue.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-green.appiconset/AppIcon-light-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-green.appiconset/AppIcon-light-green.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-green.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-green.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-jellyfin.appiconset/AppIcon-light-jellyfin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-jellyfin.appiconset/AppIcon-light-jellyfin.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-jellyfin.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-jellyfin.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-orange.appiconset/AppIcon-light-orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-orange.appiconset/AppIcon-light-orange.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-orange.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-orange.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-red.appiconset/AppIcon-light-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-red.appiconset/AppIcon-light-red.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-red.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-red.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-yellow.appiconset/AppIcon-light-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-yellow.appiconset/AppIcon-light-yellow.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/AppIcon-light-yellow.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-light-yellow.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Light/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Primary/AppIcon-primary-primary.appiconset/AppIcon-primary-primary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Swiftfin/Resources/Assets.xcassets/AppIcons/Primary/AppIcon-primary-primary.appiconset/AppIcon-primary-primary.png
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Primary/AppIcon-primary-primary.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-primary-primary.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/AppIcons/Primary/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-chrome.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "chrome.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-chrome.imageset/chrome.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-edge.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "edge.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-edgechromium.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "edgechromium.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-firefox.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "firefox.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-html5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "html5.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-html5.imageset/html5.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-msie.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "msie.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-opera.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "opera.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-opera.imageset/opera.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Browsers/Device-browser-safari.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "safari.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-android.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "android.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-android.imageset/android.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-apple.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "apple.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-apple.imageset/apple.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-finamp.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "finamp.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-kodi.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "kodi.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-playstation.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "playstation.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-playstation.imageset/playstation.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-roku.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "roku.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-samsungtv.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "samsungtv.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-webos.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "webOS.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-windows.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "windows.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-windows.imageset/windows.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-xbox.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "xbox.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Clients/Device-client-xbox.imageset/xbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Other/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Other/Device-other-homeassistant.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "home-assistant.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Other/Device-other-other.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "other.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/DeviceIcons/Other/Device-other-other.imageset/other.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/git.commit.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "git.commit.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/jellyfin-blob-blue.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "jellyfin-blob.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/logo.github.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "logo.github.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/tomato.fresh.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "tomato.fresh.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Assets.xcassets/tomato.rotten.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "tomato.rotten.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Swiftfin/Resources/Swiftfin.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Swiftfin/Views/AdminDashboardView/ServerDevices/DeviceDetailsView/Components/Sections/CustomDeviceNameSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | extension DeviceDetailsView {
13 | struct CustomDeviceNameSection: View {
14 | @Binding
15 | var customName: String
16 |
17 | // MARK: - Body
18 |
19 | var body: some View {
20 | Section(L10n.name) {
21 | TextField(
22 | L10n.name,
23 | text: $customName
24 | )
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin/Views/AdminDashboardView/ServerTasks/EditServerTaskView/Components/Sections/DetailsSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | extension EditServerTaskView {
12 |
13 | struct DetailsSection: View {
14 |
15 | let category: String
16 |
17 | var body: some View {
18 | Section(L10n.details) {
19 | TextPairView(leading: L10n.category, trailing: category)
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Swiftfin/Views/AdminDashboardView/ServerTasks/EditServerTaskView/Components/Sections/LastErrorSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | extension EditServerTaskView {
13 |
14 | struct LastErrorSection: View {
15 |
16 | let message: String
17 |
18 | var body: some View {
19 | Section(L10n.errorDetails) {
20 | Text(message)
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/StatusSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | extension ServerUserPermissionsView {
13 |
14 | struct StatusSection: View {
15 |
16 | @Binding
17 | var policy: UserPolicy
18 |
19 | var body: some View {
20 | Section(L10n.status) {
21 |
22 | Toggle(L10n.active, isOn: Binding(
23 | get: { !(policy.isDisabled ?? false) },
24 | set: { policy.isDisabled = !$0 }
25 | ))
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/SyncPlaySection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | extension ServerUserPermissionsView {
13 |
14 | struct SyncPlaySection: View {
15 |
16 | @Binding
17 | var policy: UserPolicy
18 |
19 | var body: some View {
20 | Section(L10n.syncPlay) {
21 |
22 | CaseIterablePicker(
23 | L10n.permissions,
24 | selection: $policy.syncPlayAccess.coalesce(.none)
25 | )
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Swiftfin/Views/DownloadTaskView/DownloadTaskView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | struct DownloadTaskView: View {
13 |
14 | @EnvironmentObject
15 | private var router: DownloadTaskCoordinator.Router
16 |
17 | @ObservedObject
18 | var downloadTask: DownloadTask
19 |
20 | var body: some View {
21 | ScrollView(showsIndicators: false) {
22 | ContentView(downloadTask: downloadTask)
23 | }
24 | .navigationBarCloseButton {
25 | router.dismissCoordinator()
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Swiftfin/Views/FontPickerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 | import UIKit
11 |
12 | struct FontPickerView: View {
13 |
14 | @Binding
15 | var selection: String
16 |
17 | var body: some View {
18 | SelectorView(
19 | selection: $selection,
20 | sources: UIFont.familyNames
21 | )
22 | .label { fontFamily in
23 | Text(fontFamily)
24 | .foregroundColor(.primary)
25 | .font(.custom(fontFamily, size: 18))
26 | }
27 | .navigationTitle(L10n.subtitleFont)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Swiftfin/Views/ItemEditorView/ItemImages/ItemPhotoPickerView/ItemPhotoPickerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ItemImagePicker: View {
12 |
13 | // MARK: - Observed, & Environment Objects
14 |
15 | @EnvironmentObject
16 | private var router: ItemImagePickerCoordinator.Router
17 |
18 | // MARK: - Body
19 |
20 | var body: some View {
21 | PhotoPickerView {
22 | router.route(to: \.cropImage, $0)
23 | } onCancel: {
24 | router.dismissCoordinator()
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Swiftfin/Views/ItemView/Components/StudiosHStack.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import JellyfinAPI
10 | import SwiftUI
11 |
12 | extension ItemView {
13 |
14 | struct StudiosHStack: View {
15 |
16 | @EnvironmentObject
17 | private var router: ItemCoordinator.Router
18 |
19 | let studios: [NameGuidPair]
20 |
21 | var body: some View {
22 | PillHStack(
23 | title: L10n.studios,
24 | items: studios
25 | ).onSelect { studio in
26 | let viewModel = ItemLibraryViewModel(parent: studio)
27 | router.route(to: \.library, viewModel)
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Swiftfin/Views/SettingsView/DebugSettingsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | // NOTE: All settings *MUST* be surrounded by DEBUG compiler conditional as usage site
13 |
14 | #if DEBUG
15 | struct DebugSettingsView: View {
16 |
17 | @Default(.sendProgressReports)
18 | private var sendProgressReports
19 |
20 | var body: some View {
21 | Form {
22 |
23 | Toggle("Send Progress Reports", isOn: $sendProgressReports)
24 | }
25 | .navigationTitle("Debug")
26 | }
27 | }
28 | #endif
29 |
--------------------------------------------------------------------------------
/Swiftfin/Views/SettingsView/ExperimentalSettingsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | // Note: Used for experimental settings that may be removed or implemented
13 | // officially. Keep for future settings.
14 |
15 | struct ExperimentalSettingsView: View {
16 |
17 | var body: some View {
18 | Form {}
19 | .navigationTitle(L10n.experimental)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/ActionButtonSelectorView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | struct ActionButtonSelectorView: View {
13 |
14 | @Binding
15 | var selection: [VideoPlayerActionButton]
16 |
17 | var body: some View {
18 | OrderedSectionSelectorView(
19 | selection: $selection,
20 | sources: VideoPlayerActionButton.allCases
21 | )
22 | .label { button in
23 | HStack {
24 | Image(systemName: button.settingsSystemImage)
25 |
26 | Text(button.displayTitle)
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/TransitionSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Defaults
10 | import SwiftUI
11 |
12 | extension VideoPlayerSettingsView {
13 | struct TransitionSection: View {
14 | @Default(.VideoPlayer.Transition.pauseOnBackground)
15 | private var pauseOnBackground
16 | @Default(.VideoPlayer.Transition.playOnActive)
17 | private var playOnActive
18 |
19 | var body: some View {
20 | Section(L10n.transition) {
21 |
22 | Toggle(L10n.pauseOnBackground, isOn: $pauseOnBackground)
23 | Toggle(L10n.playOnActive, isOn: $playOnActive)
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Swiftfin/Views/UserProfileImagePicker/UserProfileImagePickerView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct UserProfileImagePickerView: View {
12 |
13 | // MARK: - Observed, & Environment Objects
14 |
15 | @EnvironmentObject
16 | private var router: UserProfileImageCoordinator.Router
17 |
18 | // MARK: - Body
19 |
20 | var body: some View {
21 | PhotoPickerView {
22 | router.route(to: \.cropImage, $0)
23 | } onCancel: {
24 | router.dismissCoordinator()
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Swiftfin/Views/VideoPlayer/Overlays/Components/ActionButtons/ActionButtons.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import Foundation
10 |
11 | extension VideoPlayer.Overlay {
12 |
13 | enum ActionButtons {}
14 | }
15 |
--------------------------------------------------------------------------------
/Swiftfin/Views/VideoPlayer/VideoPlayer+Actions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Swiftfin is subject to the terms of the Mozilla Public
3 | // License, v2.0. If a copy of the MPL was not distributed with this
4 | // file, you can obtain one at https://mozilla.org/MPL/2.0/.
5 | //
6 | // Copyright (c) 2025 Jellyfin & Jellyfin Contributors
7 | //
8 |
9 | import SwiftUI
10 |
11 | extension VideoPlayer {
12 |
13 | enum Action {
14 |
15 | // MARK: Aspect Fill
16 |
17 | func aspectFill(
18 | state: UIGestureRecognizer.State,
19 | unitPoint: UnitPoint,
20 | scale: CGFloat
21 | ) {}
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Translations/ar.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ar.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/bg.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/bg.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ca.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ca.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/cs.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/cs.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/da.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/da.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/de.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/de.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/el.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/el.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/en.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/eo.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/eo.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/es.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/eu.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/eu.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/fi.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/fi.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/fr.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/he.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/he.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/hi.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/hi.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/hr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/hr.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/hu.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/hu.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/id.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/id.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/it.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/it.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ja.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ja.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/kk.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/kk.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ko.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ko.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/lb.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/lb.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/lt.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/lt.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/mk.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/mk.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/nb-NO.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/nb-NO.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/nl.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/nl.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/nn.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/nn.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/pl.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/pl.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ps.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ps.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/pt-BR.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/pt-BR.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/pt.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/pt.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ro.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ro.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ru.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ru.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/sk.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/sk.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/sl.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/sl.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/sq.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/sq.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/sv.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/sv.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/ta.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/ta.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/th.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/th.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/tr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/tr.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/uk.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/uk.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/vi.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/vi.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/zh-Hans.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/zh-Hans.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Translations/zh-Hant.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/Translations/zh-Hant.lproj/Localizable.strings
--------------------------------------------------------------------------------
/fastlane/Appfile.swift:
--------------------------------------------------------------------------------
1 | var appIdentifier: String { return "[[APP_IDENTIFIER]]" } // The bundle identifier of your app
2 | var appleID: String { return "[[APPLE_ID]]" } // Your Apple Developer Portal username
3 |
4 |
5 |
6 | // For more information about the Appfile, see:
7 | // https://docs.fastlane.tools/advanced/#appfile
8 |
--------------------------------------------------------------------------------
/fastlane/FastlaneRunner:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jellyfin/Swiftfin/11824cf828fd1cf660db16151eadad86d387e7da/fastlane/FastlaneRunner
--------------------------------------------------------------------------------
/fastlane/swift/Actions.swift:
--------------------------------------------------------------------------------
1 | // Actions.swift
2 | // Copyright (c) 2025 FastlaneTools
3 |
4 | // This autogenerated file will be overwritten or replaced when running "fastlane generate_swift"
5 | //
6 | // ** NOTE **
7 | // This file is provided by fastlane and WILL be overwritten in future updates
8 | // If you want to add extra functionality to this project, create a new file in a
9 | // new group so that it won't be marked for upgrade
10 | //
11 |
12 | import Foundation
13 |
14 | // Please don't remove the lines below
15 | // They are used to detect outdated files
16 | // FastlaneRunnerAPIVersion [0.9.56]
17 |
--------------------------------------------------------------------------------
/fastlane/swift/Appfile.swift:
--------------------------------------------------------------------------------
1 | // Appfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | var appIdentifier: String { return "" } // The bundle identifier of your app
5 | var appleID: String { return "" } // Your Apple Developer Portal username
6 |
7 | var teamID: String { return "" } // Developer Portal Team ID
8 | var itcTeam: String? { return nil } // App Store Connect Team ID (may be nil if no team)
9 |
10 | // you can even provide different app identifiers, Apple IDs and team names per lane:
11 | // More information: https://docs.fastlane.tools/advanced/#appfile
12 |
13 | // Please don't remove the lines below
14 | // They are used to detect outdated files
15 | // FastlaneRunnerAPIVersion [0.9.1]
16 |
--------------------------------------------------------------------------------
/fastlane/swift/Deliverfile.swift:
--------------------------------------------------------------------------------
1 | // Deliverfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `deliver`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Deliverfile: DeliverfileProtocol {
15 | // If you want to enable `deliver`, run `fastlane deliver init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Fastfile.swift:
--------------------------------------------------------------------------------
1 | // This class is automatically included in FastlaneRunner during build
2 | // If you have a custom Fastfile.swift, this file will be replaced by it
3 | // Don't modify this file unless you are familiar with how fastlane's swift code generation works
4 | // *** This file will be overwritten or replaced during build time ***
5 |
6 | import Foundation
7 |
8 | open class Fastfile: LaneFile {
9 | override public init() {
10 | super.init()
11 | }
12 | }
13 |
14 | // Please don't remove the lines below
15 | // They are used to detect outdated files
16 | // FastlaneRunnerAPIVersion [0.9.1]
17 |
--------------------------------------------------------------------------------
/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fastlane/swift/FastlaneSwiftRunner/README.txt:
--------------------------------------------------------------------------------
1 | Don't modify the structure of this group including but not limited to:
2 | - renaming this group
3 | - adding sub groups
4 | - removing sub groups
5 | - adding new files
6 | - removing files
7 |
8 | If you modify anything in this folder, future fastlane upgrades may not be able to be applied automatically.
9 |
10 | If you need to add new groups, please add them at the root of the "Fastlane Runner" group.
11 |
--------------------------------------------------------------------------------
/fastlane/swift/Gymfile.swift:
--------------------------------------------------------------------------------
1 | // Gymfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `gym`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Gymfile: GymfileProtocol {
15 | // If you want to enable `gym`, run `fastlane gym init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Matchfile.swift:
--------------------------------------------------------------------------------
1 | // Matchfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `match`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Matchfile: MatchfileProtocol {
15 | // If you want to enable `match`, run `fastlane match init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Plugins.swift:
--------------------------------------------------------------------------------
1 | // Plugins.swift
2 | // Copyright (c) 2025 FastlaneTools
3 |
4 | // This autogenerated file will be overwritten or replaced when installing/updating plugins or running "fastlane generate_swift"
5 | //
6 | // ** NOTE **
7 | // This file is provided by fastlane and WILL be overwritten in future updates
8 | // If you want to add extra functionality to this project, create a new file in a
9 | // new group so that it won't be marked for upgrade
10 | //
11 |
12 | import Foundation
13 |
14 | // Please don't remove the lines below
15 | // They are used to detect outdated files
16 | // FastlaneRunnerAPIVersion [0.9.56]
17 |
--------------------------------------------------------------------------------
/fastlane/swift/Precheckfile.swift:
--------------------------------------------------------------------------------
1 | // Precheckfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `precheck`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Precheckfile: PrecheckfileProtocol {
15 | // If you want to enable `precheck`, run `fastlane precheck init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/RunnerArgument.swift:
--------------------------------------------------------------------------------
1 | // RunnerArgument.swift
2 | // Copyright (c) 2025 FastlaneTools
3 |
4 | //
5 | // ** NOTE **
6 | // This file is provided by fastlane and WILL be overwritten in future updates
7 | // If you want to add extra functionality to this project, create a new file in a
8 | // new group so that it won't be marked for upgrade
9 | //
10 |
11 | import Foundation
12 |
13 | struct RunnerArgument {
14 | let name: String
15 | let value: String
16 | }
17 |
18 | // Please don't remove the lines below
19 | // They are used to detect outdated files
20 | // FastlaneRunnerAPIVersion [0.9.2]
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Scanfile.swift:
--------------------------------------------------------------------------------
1 | // Scanfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `scan`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Scanfile: ScanfileProtocol {
15 | // If you want to enable `scan`, run `fastlane scan init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Screengrabfile.swift:
--------------------------------------------------------------------------------
1 | // Screengrabfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `screengrab`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Screengrabfile: ScreengrabfileProtocol {
15 | // If you want to enable `screengrab`, run `fastlane screengrab init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/Snapshotfile.swift:
--------------------------------------------------------------------------------
1 | // Snapshotfile.swift
2 | // Copyright (c) 2024 FastlaneTools
3 |
4 | // This class is automatically included in FastlaneRunner during build
5 |
6 | // This autogenerated file will be overwritten or replaced during build time, or when you initialize `snapshot`
7 | //
8 | // ** NOTE **
9 | // This file is provided by fastlane and WILL be overwritten in future updates
10 | // If you want to add extra functionality to this project, create a new file in a
11 | // new group so that it won't be marked for upgrade
12 | //
13 |
14 | public class Snapshotfile: SnapshotfileProtocol {
15 | // If you want to enable `snapshot`, run `fastlane snapshot init`
16 | // After, this file will be replaced with a custom implementation that contains values you supplied
17 | // during the `init` process, and you won't see this message
18 | }
19 |
20 | // Generated with fastlane 2.220.0
21 |
--------------------------------------------------------------------------------
/fastlane/swift/SocketClientDelegateProtocol.swift:
--------------------------------------------------------------------------------
1 | // SocketClientDelegateProtocol.swift
2 | // Copyright (c) 2025 FastlaneTools
3 |
4 | //
5 | // ** NOTE **
6 | // This file is provided by fastlane and WILL be overwritten in future updates
7 | // If you want to add extra functionality to this project, create a new file in a
8 | // new group so that it won't be marked for upgrade
9 | //
10 |
11 | import Foundation
12 |
13 | protocol SocketClientDelegateProtocol: AnyObject {
14 | func connectionsOpened()
15 | func connectionsClosed()
16 | func commandExecuted(serverResponse: SocketClientResponse, completion: (SocketClient) -> Void)
17 | }
18 |
19 | // Please don't remove the lines below
20 | // They are used to detect outdated files
21 | // FastlaneRunnerAPIVersion [0.9.2]
22 |
--------------------------------------------------------------------------------
/fastlane/swift/formatting/Brewfile:
--------------------------------------------------------------------------------
1 | brew("swiftformat")
2 |
--------------------------------------------------------------------------------
/fastlane/swift/formatting/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | task(default: %w[setup])
4 |
5 | task(setup: [:brew, :lint])
6 |
7 | task(:brew) do
8 | raise '`brew` is required. Please install brew. https://brew.sh/' unless system('which brew')
9 |
10 | puts('➡️ Brew')
11 | sh('brew bundle')
12 | end
13 |
14 | task(:lint) do
15 | Dir.chdir('..') do
16 | sh("swiftformat . --config formatting/.swiftformat --verbose --selfrequired waitWithPolling --exclude Fastfile.swift --swiftversion 4.0")
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/fastlane/swift/upgrade_manifest.json:
--------------------------------------------------------------------------------
1 | {"Actions.swift":"Autogenerated API","Fastlane.swift":"Autogenerated API","DeliverfileProtocol.swift":"Autogenerated API","GymfileProtocol.swift":"Autogenerated API","MatchfileProtocol.swift":"Autogenerated API","Plugins.swift":"Autogenerated API","PrecheckfileProtocol.swift":"Autogenerated API","ScanfileProtocol.swift":"Autogenerated API","ScreengrabfileProtocol.swift":"Autogenerated API","SnapshotfileProtocol.swift":"Autogenerated API","LaneFileProtocol.swift":"Fastfile Components","OptionalConfigValue.swift":"Fastfile Components","Atomic.swift":"Networking","ControlCommand.swift":"Networking","RubyCommand.swift":"Networking","RubyCommandable.swift":"Networking","Runner.swift":"Networking","SocketClient.swift":"Networking","SocketClientDelegateProtocol.swift":"Networking","SocketResponse.swift":"Networking","main.swift":"Runner Code","ArgumentProcessor.swift":"Runner Code","RunnerArgument.swift":"Runner Code"}
--------------------------------------------------------------------------------
/swiftgen.yml:
--------------------------------------------------------------------------------
1 | strings:
2 | inputs: Translations/en.lproj
3 | outputs:
4 | - templateName: structured-swift5
5 | output: Shared/Strings/Strings.swift
6 |
--------------------------------------------------------------------------------