172 lines
6 KiB
Swift
172 lines
6 KiB
Swift
import SwiftUI
|
|
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
// LicensesView.swift
|
|
// Displays all open-source licenses for dependencies used in the app
|
|
// and the Companion API server.
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
|
|
struct LicenseItem: Identifiable {
|
|
let id = UUID()
|
|
let name: String
|
|
let description: String
|
|
let license: String
|
|
let url: String
|
|
let category: String // "App" or "Companion API"
|
|
}
|
|
|
|
struct LicensesView: View {
|
|
private let accentPink = Color(red: 1.0, green: 0.176, blue: 0.333)
|
|
|
|
private let licenses: [LicenseItem] = [
|
|
// ── iOS App ──
|
|
LicenseItem(
|
|
name: "ZIPFoundation",
|
|
description: "Effortless ZIP handling in Swift",
|
|
license: "MIT License",
|
|
url: "https://github.com/weichsel/ZIPFoundation",
|
|
category: "App"
|
|
),
|
|
|
|
// ── Companion API (Python) ──
|
|
LicenseItem(
|
|
name: "FastAPI",
|
|
description: "Modern, fast web framework for building APIs with Python",
|
|
license: "MIT License",
|
|
url: "https://github.com/tiangolo/fastapi",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "Uvicorn",
|
|
description: "Lightning-fast ASGI server for Python",
|
|
license: "BSD License",
|
|
url: "https://github.com/encode/uvicorn",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "Mutagen",
|
|
description: "Python module to handle audio metadata",
|
|
license: "GPL-2.0 License",
|
|
url: "https://github.com/quodlibet/mutagen",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "httpx",
|
|
description: "Fully featured HTTP client for Python 3",
|
|
license: "BSD License",
|
|
url: "https://github.com/encode/httpx",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "NumPy",
|
|
description: "Fundamental package for scientific computing with Python",
|
|
license: "BSD License",
|
|
url: "https://github.com/numpy/numpy",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "Pydantic",
|
|
description: "Data validation using Python type annotations",
|
|
license: "MIT License",
|
|
url: "https://github.com/pydantic/pydantic",
|
|
category: "Companion API"
|
|
),
|
|
LicenseItem(
|
|
name: "librosa",
|
|
description: "Python library for audio and music analysis",
|
|
license: "ISC License",
|
|
url: "https://github.com/librosa/librosa",
|
|
category: "Companion API"
|
|
),
|
|
]
|
|
|
|
private var appLicenses: [LicenseItem] {
|
|
licenses.filter { $0.category == "App" }
|
|
}
|
|
|
|
private var companionLicenses: [LicenseItem] {
|
|
licenses.filter { $0.category == "Companion API" }
|
|
}
|
|
|
|
var body: some View {
|
|
List {
|
|
Section {
|
|
VStack(alignment: .leading, spacing: 6) {
|
|
Text("NavidromePlayer uses the following open-source libraries. We're grateful to the developers and communities behind these projects.")
|
|
.font(.system(size: 13))
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
.padding(.vertical, 4)
|
|
}
|
|
|
|
Section("App") {
|
|
ForEach(appLicenses) { item in
|
|
licenseRow(item)
|
|
}
|
|
}
|
|
|
|
Section("Companion API") {
|
|
ForEach(companionLicenses) { item in
|
|
licenseRow(item)
|
|
}
|
|
}
|
|
|
|
Section {
|
|
VStack(alignment: .leading, spacing: 6) {
|
|
Text("Visualizer")
|
|
.font(.system(size: 15, weight: .semibold))
|
|
Text("The audio visualizer is inspired by Mitsuha, originally created by c0ldra1n for jailbroken iOS. This is an independent reimplementation using Apple frameworks.")
|
|
.font(.system(size: 13))
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
.padding(.vertical, 4)
|
|
} header: {
|
|
Text("Acknowledgments")
|
|
}
|
|
}
|
|
.navigationTitle("Licenses")
|
|
}
|
|
|
|
private func licenseRow(_ item: LicenseItem) -> some View {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
HStack {
|
|
Text(item.name)
|
|
.font(.system(size: 15, weight: .semibold))
|
|
Spacer()
|
|
Text(item.license)
|
|
.font(.system(size: 11, weight: .medium))
|
|
.foregroundStyle(accentPink)
|
|
.padding(.horizontal, 8)
|
|
.padding(.vertical, 3)
|
|
.background(
|
|
Capsule()
|
|
.fill(accentPink.opacity(0.12))
|
|
)
|
|
}
|
|
|
|
Text(item.description)
|
|
.font(.system(size: 13))
|
|
.foregroundStyle(.secondary)
|
|
.lineLimit(2)
|
|
|
|
if let url = URL(string: item.url) {
|
|
Link(destination: url) {
|
|
Text(item.url.replacingOccurrences(of: "https://", with: ""))
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(.blue.opacity(0.8))
|
|
.lineLimit(1)
|
|
.truncationMode(.middle)
|
|
}
|
|
}
|
|
}
|
|
.padding(.vertical, 4)
|
|
}
|
|
}
|
|
|
|
#if DEBUG
|
|
#Preview {
|
|
NavigationStack {
|
|
LicensesView()
|
|
}
|
|
}
|
|
#endif
|