Skip to content

Commit

Permalink
Merge branch 'main' into activeSessionsIndicator
Browse files Browse the repository at this point in the history
  • Loading branch information
JPKribs authored Jan 30, 2025
2 parents 45d07bb + 21cf786 commit 420e6bd
Show file tree
Hide file tree
Showing 786 changed files with 10,503 additions and 4,481 deletions.
7 changes: 4 additions & 3 deletions Documentation/players.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ Swiftfin offers two player options: Swiftfin (VLCKit) and Native (AVKit). The Sw
**Notes**

- Unsupported containers will require transcoding or remuxing to play.
- AV1 is disabled by default but can be enabled for Native (AVKit) using Custom Device Profiles.

---

Expand Down Expand Up @@ -86,14 +85,16 @@ Swiftfin offers two player options: Swiftfin (VLCKit) and Native (AVKit). The Sw

| Video Codec | Swiftfin (VLCKit) | Native (AVKit) |
|-------------|-------------------|----------------|
| **AV1** || |
| **AV1** || 🟡 Limited support |
| **H.264** |||
| **H.265** |||
| **MPEG-2** |||
| **MPEG-4** |||
| **VP8** |||
| **VP9** |||

- AV1 is disabled by default but can be enabled for Native (AVKit) using Custom Device Profiles. Enabling AV1 may result in a [poor experience for SOCs prior to A17](https://en.wikipedia.org/wiki/Apple_A17).

---

## Subtitle Support
Expand Down Expand Up @@ -136,4 +137,4 @@ Swiftfin offers two player options: Swiftfin (VLCKit) and Native (AVKit). The Sw
- Dolby Vision Profile 10 requires AV1 to be enabled to work in Native (AVKit).
- Swiftfin (VLCKit) does not support HDR playback natively. HDR content may play back without the intended high dynamic range effect.

---
---
2 changes: 1 addition & 1 deletion PreferencesView/Sources/PreferencesView/Box.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

class Box {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import UIKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwizzleSwift
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
13 changes: 10 additions & 3 deletions RedrawOnNotificationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand All @@ -13,18 +13,25 @@ struct RedrawOnNotificationView<Content: View, P>: View {
@State
private var id = 0

private let filter: (P) -> Bool
private let key: Notifications.Key<P>
private let content: () -> Content

init(_ key: Notifications.Key<P>, @ViewBuilder content: @escaping () -> Content) {
init(
_ key: Notifications.Key<P>,
filter: @escaping (P) -> Bool = { _ in true },
@ViewBuilder content: @escaping () -> Content
) {
self.filter = filter
self.key = key
self.content = content
}

var body: some View {
content()
.id(id)
.onNotification(key) { _ in
.onNotification(key) { p in
guard filter(p) else { return }
id += 1
}
}
Expand Down
54 changes: 54 additions & 0 deletions Scripts/Translations/AlphabetizeStrings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation

// Get the English localization file
let fileURL = URL(fileURLWithPath: "./Translations/en.lproj/Localizable.strings")

// This regular expression pattern matches lines of the format:
// "Key" = "Value";
let regex = #/^\"(?<key>[^\"]+)\"\s*=\s*\"(?<value>[^\"]+)\";/#

// Attempt to read the file content.
guard let content = try? String(contentsOf: fileURL, encoding: .utf8) else {
print("Unable to read file: \(fileURL.path)")
exit(1)
}

// Split file content by newlines to process line by line.
let strings = content.components(separatedBy: .newlines)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty && !$0.hasPrefix("//") }

let entries = strings.reduce(into: [String: String]()) {
if let match = $1.firstMatch(of: regex) {
let key = String(match.output.key)
let value = String(match.output.value)
$0[key] = value
} else {
print("Error: Invalid line format in \(fileURL.path): \($1)")
exit(1)
}
}

// Sort the keys alphabetically for consistent ordering.
let sortedKeys = entries.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == .orderedAscending }
let newContent = sortedKeys.map { "/// \(entries[$0]!)\n\"\($0)\" = \"\(entries[$0]!)\";" }.joined(separator: "\n\n")

// Write the updated, sorted, and commented localizations back to the file.
do {
try newContent.write(to: fileURL, atomically: true, encoding: .utf8)

if let derivedFileDirectory = ProcessInfo.processInfo.environment["DERIVED_FILE_DIR"] {
try? "".write(toFile: derivedFileDirectory + "/alphabetizeStrings.txt", atomically: true, encoding: .utf8)
}
} catch {
print("Error: Failed to write to \(fileURL.path)")
exit(1)
}
111 changes: 111 additions & 0 deletions Scripts/Translations/PurgeUnusedStrings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation

// Path to the English localization file
let localizationFile = "./Translations/en.lproj/Localizable.strings"

// Directories to scan for Swift files
let directoriesToScan = ["./Shared", "./Swiftfin", "./Swiftfin tvOS"]

// File to exclude from scanning
let excludedFile = "./Shared/Strings/Strings.swift"

// Regular expressions to match localization entries and usage in Swift files
// Matches lines like "Key" = "Value";
let localizationRegex = #/^\"(?<key>[^\"]+)\"\s*=\s*\"(?<value>[^\"]+)\";$/#

// Matches usage like L10n.key in Swift files
let usageRegex = #/L10n\.(?<key>[a-zA-Z0-9_]+)/#

// Attempt to load the localization file's content
guard let localizationContent = try? String(contentsOfFile: localizationFile, encoding: .utf8) else {
print("Unable to read localization file at \(localizationFile)")
exit(1)
}

// Split the file into lines and initialize a dictionary for localization entries
let localizationLines = localizationContent.components(separatedBy: .newlines)
var localizationEntries = [String: String]()

// Parse each line to extract key-value pairs
for line in localizationLines {
let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines)

// Skip empty lines or comments
if trimmed.isEmpty || trimmed.hasPrefix("//") { continue }

// Match valid localization entries and add them to the dictionary
if let match = line.firstMatch(of: localizationRegex) {
let key = String(match.output.key)
let value = String(match.output.value)
localizationEntries[key] = value
}
}

// Set to store all keys found in the codebase
var usedKeys = Set<String>()

// Function to scan a directory recursively for Swift files
func scanDirectory(_ path: String) {
let fileManager = FileManager.default
guard let enumerator = fileManager.enumerator(atPath: path) else { return }

for case let file as String in enumerator {
let filePath = "\(path)/\(file)"

// Skip the excluded file
if filePath == excludedFile { continue }

// Process only Swift files
if file.hasSuffix(".swift") {
if let fileContent = try? String(contentsOfFile: filePath, encoding: .utf8) {
for line in fileContent.components(separatedBy: .newlines) {
// Find all matches for L10n.key in each line
let matches = line.matches(of: usageRegex)
for match in matches {
let key = String(match.output.key)
usedKeys.insert(key)
}
}
}
}
}
}

// Scan all specified directories
for directory in directoriesToScan {
scanDirectory(directory)
}

// MARK: - Remove Unused Keys

// Identify keys in the localization file that are not used in the codebase
let unusedKeys = localizationEntries.keys.filter { !usedKeys.contains($0) }

// Remove unused keys from the dictionary
unusedKeys.forEach { localizationEntries.removeValue(forKey: $0) }

// MARK: - Write Updated Localizable.strings

// Sort keys alphabetically for consistent formatting
let sortedKeys = localizationEntries.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == .orderedAscending }

// Reconstruct the localization file with sorted and updated entries
let updatedContent = sortedKeys.map { "/// \(localizationEntries[$0]!)\n\"\($0)\" = \"\(localizationEntries[$0]!)\";" }
.joined(separator: "\n\n")

// Attempt to write the updated content back to the localization file
do {
try updatedContent.write(toFile: localizationFile, atomically: true, encoding: .utf8)
print("Localization file updated. Removed \(unusedKeys.count) unused keys.")
} catch {
print("Error: Failed to write updated localization file.")
exit(1)
}
2 changes: 1 addition & 1 deletion Shared/AppIcons/AppIcons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/AppIcons/DarkAppIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/AppIcons/InvertedDarkAppIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/AppIcons/InvertedLightAppIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/AppIcons/LightAppIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/AppIcons/PrimaryAppIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Shared/Components/AlternateLayoutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
2 changes: 1 addition & 1 deletion Shared/Components/AssertionFailureView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import SwiftUI
Expand Down
Loading

0 comments on commit 420e6bd

Please sign in to comment.