Cleanup and `ItemView.AboutView` Cards (#788)

This commit is contained in:
Ethan Pippin 2023-06-12 22:24:58 -06:00 committed by GitHub
parent cc80be2ee4
commit ddbe77e348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
167 changed files with 1613 additions and 597 deletions

View File

@ -17,7 +17,8 @@ struct SeparatorHStack: View {
var body: some View {
_VariadicView.Tree(SeparatorHStackLayout(separator: separator)) {
AnyView(content())
content()
.eraseToAnyView()
}
}
}

View File

@ -9,61 +9,55 @@
import Defaults
import SwiftUI
struct TruncatedTextView: View {
struct TruncatedText: View {
@Default(.accentColor)
private var accentColor
@State
private var truncated: Bool = false
private var isTruncated: Bool = false
@State
private var fullSize: CGFloat = 0
private var font: Font
private var lineLimit: Int
private let text: String
private var seeMoreAction: () -> Void
private let seeMoreText = "... \(L10n.seeMore)"
private let seeMoreText = "... See More"
var body: some View {
ZStack(alignment: .bottomTrailing) {
Text(text)
.font(font)
.lineLimit(lineLimit)
.if(truncated) { text in
text.mask {
VStack(spacing: 0) {
Color.black
.inverseMask(alignment: .bottomTrailing) {
VStack {
Spacer()
HStack(spacing: 0) {
Color.black
HStack {
Spacer()
LinearGradient(
stops: [
.init(color: .black, location: 0),
.init(color: .clear, location: 0.1),
],
startPoint: .leading,
endPoint: .trailing
)
.frame(width: seeMoreText.widthOfString(usingFont: font.uiFont) + 15)
}
.frame(height: seeMoreText.heightOfString(usingFont: font.uiFont))
Text(" " + seeMoreText)
.background {
LinearGradient(
stops: [
.init(color: .clear, location: 0),
.init(color: .black, location: 0.1),
],
startPoint: .leading,
endPoint: .trailing
)
}
}
}
.visible(isTruncated)
}
if truncated {
if isTruncated {
#if os(tvOS)
Text(seeMoreText)
.font(font)
.foregroundColor(accentColor)
#else
Button {
seeMoreAction()
} label: {
Text(seeMoreText)
.font(font)
.foregroundColor(accentColor)
}
#endif
@ -71,17 +65,15 @@ struct TruncatedTextView: View {
}
.background {
ZStack {
if !truncated {
if !isTruncated {
if fullSize != 0 {
Text(text)
.font(font)
.lineLimit(lineLimit)
.background {
GeometryReader { geo in
GeometryReader { proxy in
Color.clear
.onAppear {
if fullSize > geo.size.height {
self.truncated = true
if fullSize > proxy.size.height {
self.isTruncated = true
}
}
}
@ -89,14 +81,13 @@ struct TruncatedTextView: View {
}
Text(text)
.font(font)
.lineLimit(10)
.fixedSize(horizontal: false, vertical: true)
.background {
GeometryReader { geo in
GeometryReader { proxy in
Color.clear
.onAppear {
self.fullSize = geo.size.height
self.fullSize = proxy.size.height
}
}
}
@ -107,25 +98,15 @@ struct TruncatedTextView: View {
}
}
extension TruncatedTextView {
extension TruncatedText {
init(text: String) {
init(_ text: String) {
self.init(
font: .body,
lineLimit: 1000,
text: text,
seeMoreAction: {}
)
}
func font(_ font: Font) -> Self {
copy(modifying: \.font, with: font)
}
func lineLimit(_ limit: Int) -> Self {
copy(modifying: \.lineLimit, with: limit)
}
func seeMoreAction(_ action: @escaping () -> Void) -> Self {
copy(modifying: \.seeMoreAction, with: action)
}

View File

@ -9,6 +9,8 @@
import Stinsen
import SwiftUI
// TODO: just have this coordinator wrap the content itself in a NavigationViewCoordinator instead
/// Basic coordinator to wrap a view for the purpose of being wrapped in a NavigationViewCoordinator
final class BasicNavigationViewCoordinator: NavigationCoordinatable {

View File

@ -25,11 +25,11 @@ final class ItemCoordinator: NavigationCoordinatable {
var library = makeLibrary
@Route(.push)
var castAndCrew = makeCastAndCrew
@Route(.modal)
var itemOverview = makeItemOverview
#if os(iOS)
@Route(.modal)
var itemOverview = makeItemOverview
@Route(.modal)
var mediaSourceInfo = makeMediaSourceInfo
@Route(.modal)
var downloadTask = makeDownloadTask
@ -37,10 +37,14 @@ final class ItemCoordinator: NavigationCoordinatable {
#if os(tvOS)
@Route(.fullScreen)
var itemOverview = makeItemOverview
@Route(.fullScreen)
var mediaSourceInfo = makeMediaSourceInfo
@Route(.fullScreen)
var videoPlayer = makeVideoPlayer
#endif
let itemDto: BaseItemDto
private let itemDto: BaseItemDto
init(item: BaseItemDto) {
self.itemDto = item
@ -62,15 +66,17 @@ final class ItemCoordinator: NavigationCoordinatable {
CastAndCrewLibraryCoordinator(people: people)
}
func makeItemOverview(item: BaseItemDto) -> NavigationViewCoordinator<ItemOverviewCoordinator> {
NavigationViewCoordinator(ItemOverviewCoordinator(item: itemDto))
func makeItemOverview(item: BaseItemDto) -> NavigationViewCoordinator<BasicNavigationViewCoordinator> {
NavigationViewCoordinator(BasicNavigationViewCoordinator {
ItemOverviewView(item: item)
})
}
func makeMediaSourceInfo(source: MediaSourceInfo) -> NavigationViewCoordinator<MediaSourceInfoCoordinator> {
NavigationViewCoordinator(MediaSourceInfoCoordinator(mediaSourceInfo: source))
}
#if os(iOS)
func makeMediaSourceInfo(mediaSourceInfo: MediaSourceInfo) -> NavigationViewCoordinator<MediaSourceInfoCoordinator> {
NavigationViewCoordinator(MediaSourceInfoCoordinator(mediaSourceInfo: mediaSourceInfo))
}
func makeDownloadTask(downloadTask: DownloadTask) -> NavigationViewCoordinator<DownloadTaskCoordinator> {
NavigationViewCoordinator(DownloadTaskCoordinator(downloadTask: downloadTask))
}

View File

@ -1,34 +0,0 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import Stinsen
import SwiftUI
final class ItemOverviewCoordinator: NavigationCoordinatable {
let stack = NavigationStack(initial: \ItemOverviewCoordinator.start)
@Root
var start = makeStart
let item: BaseItemDto
init(item: BaseItemDto) {
self.item = item
}
@ViewBuilder
func makeStart() -> some View {
#if os(tvOS)
EmptyView()
#else
ItemOverviewView(item: item)
#endif
}
}

View File

@ -16,8 +16,11 @@ final class MediaSourceInfoCoordinator: NavigationCoordinatable {
@Root
var start = makeStart
#if os(iOS)
@Route(.push)
var mediaStreamInfo = makeMediaStreamInfo
#endif
private let mediaSourceInfo: MediaSourceInfo
@ -25,13 +28,15 @@ final class MediaSourceInfoCoordinator: NavigationCoordinatable {
self.mediaSourceInfo = mediaSourceInfo
}
#if os(iOS)
@ViewBuilder
func makeMediaStreamInfo(mediaStream: MediaStream) -> some View {
MediaStreamInfoView(mediaStream: mediaStream)
}
#endif
@ViewBuilder
func makeStart() -> some View {
ItemView.MediaSourceInfoView(mediaSource: mediaSourceInfo)
MediaSourceInfoView(source: mediaSourceInfo)
}
}

View File

@ -26,6 +26,14 @@ extension Array {
self + contents
}
func count(where predicate: (Element) throws -> Bool) rethrows -> Int {
try filter(predicate).count
}
func oneSatisfies(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
try first(where: predicate) != nil
}
func prepending(_ element: Element) -> [Element] {
[element] + self
}

View File

@ -0,0 +1,35 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
extension ForEach where Content: View {
@ViewBuilder
static func `let`(
_ data: Data?,
id: KeyPath<Data.Element, ID>,
@ViewBuilder content: @escaping (Data.Element) -> Content
) -> some View {
if let data {
ForEach(data, id: id, content: content)
} else {
EmptyView()
}
}
@ViewBuilder
static func `let`(_ data: Data?, @ViewBuilder content: @escaping (Data.Element) -> Content) -> some View where ID == Data.Element.ID,
Data.Element: Identifiable {
if let data {
ForEach(data, content: content)
} else {
EmptyView()
}
}
}

View File

@ -151,6 +151,15 @@ extension BaseItemDto {
return dateFormatter.string(from: premiereDate)
}
var hasExternalLinks: Bool {
guard let externalURLs else { return false }
return !externalURLs.isEmpty
}
var hasRatings: Bool {
[criticRating, communityRating].oneSatisfies { $0 != nil }
}
// MARK: Chapter Images
var fullChapterInfo: [ChapterInfo.FullInfo] {

View File

@ -26,11 +26,11 @@ struct AttributeViewModifier: ViewModifier {
.background {
Color(UIColor.lightGray)
.cornerRadius(2)
.inverseMask(
.inverseMask {
content
.font(.caption.weight(.semibold))
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
)
}
}
} else {
content

View File

@ -1,21 +0,0 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
struct BlurViewModifier: ViewModifier {
let style: UIBlurEffect.Style
func body(content: Content) -> some View {
content
.overlay {
BlurView(style: style)
}
}
}

View File

@ -1,25 +0,0 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
public struct VisibilityModifier: ViewModifier {
@usableFromInline
let isVisible: Bool
@usableFromInline
init(isVisible: Bool) {
self.isVisible = isVisible
}
@inlinable
public func body(content: Content) -> some View {
content.opacity(isVisible ? 1 : 0)
}
}

View File

@ -19,14 +19,14 @@ extension View {
AnyView(self)
}
func inverseMask<M: View>(_ mask: M) -> some View {
// exchange foreground and background
let inversed = mask
.foregroundColor(.black) // hide foreground
.background(Color.white) // let the background stand out
.compositingGroup()
.luminanceToAlpha()
return self.mask(inversed)
func inverseMask(alignment: Alignment = .center, _ content: @escaping () -> some View) -> some View {
mask(alignment: alignment) {
content()
.foregroundColor(.black)
.background(.white)
.compositingGroup()
.luminanceToAlpha()
}
}
// From: https://www.avanderlee.com/swiftui/conditional-view-modifier/
@ -177,11 +177,12 @@ extension View {
@inlinable
func visible(_ isVisible: Bool) -> some View {
opacity(isVisible ? 1 : 0)
// modifier(VisibilityModifier(isVisible: isVisible))
}
func blurred(style: UIBlurEffect.Style = .regular) -> some View {
modifier(BlurViewModifier(style: style))
overlay {
BlurView(style: style)
}
}
func accentSymbolRendering(accentColor: Color = Defaults[.accentColor]) -> some View {
@ -217,10 +218,4 @@ extension View {
.ignoresSafeArea()
}
}
func inBasicNavigationCoordinatable() -> BasicNavigationViewCoordinator {
BasicNavigationViewCoordinator {
self
}
}
}

View File

@ -264,6 +264,8 @@ internal enum L10n {
internal static let operatingSystem = L10n.tr("Localizable", "operatingSystem", fallback: "Operating System")
/// Orange
internal static let orange = L10n.tr("Localizable", "orange", fallback: "Orange")
/// Order
internal static let order = L10n.tr("Localizable", "order", fallback: "Order")
/// Other
internal static let other = L10n.tr("Localizable", "other", fallback: "Other")
/// Other User
@ -338,6 +340,8 @@ internal enum L10n {
internal static let randomImage = L10n.tr("Localizable", "randomImage", fallback: "Random Image")
/// Rated
internal static let rated = L10n.tr("Localizable", "rated", fallback: "Rated")
/// Ratings
internal static let ratings = L10n.tr("Localizable", "ratings", fallback: "Ratings")
/// Recently Added
internal static let recentlyAdded = L10n.tr("Localizable", "recentlyAdded", fallback: "Recently Added")
/// Recommended
@ -448,6 +452,8 @@ internal enum L10n {
internal static let smaller = L10n.tr("Localizable", "smaller", fallback: "Smaller")
/// Smallest
internal static let smallest = L10n.tr("Localizable", "smallest", fallback: "Smallest")
/// Sort
internal static let sort = L10n.tr("Localizable", "sort", fallback: "Sort")
/// Sort by
internal static let sortBy = L10n.tr("Localizable", "sortBy", fallback: "Sort by")
/// Source Code

View File

@ -10,6 +10,8 @@ import Defaults
import JellyfinAPI
import SwiftUI
// TODO: if no context menu defined, don't add context menu
struct PosterButton<Item: Poster>: View {
@FocusState

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"symbols" : [
{
"filename" : "tomato.fresh.svg",
"idiom" : "universal"
}
]
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3300" height="2200">
<!--glyph: "", point size: 100.0, font version: "18.0d12e2", template writer version: "101"-->
<style>.monochrome-0 {fill:#000000}
.monochrome-1 {fill:#000000}
.multicolor-0:systemRedColor {fill:#FF3B30}
.multicolor-1:systemGreenColor {fill:#28CD41}
.hierarchical-0:secondary {fill:#4D4D4D}
.hierarchical-1:primary {fill:#212121}
.SFSymbolsPreview28CD41 {fill:#28CD41;opacity:1.0}
.SFSymbolsPreviewFF3B30 {fill:#FF3B30;opacity:1.0}
</style>
<g id="Notes">
<rect height="2200" id="artboard" style="fill:white;opacity:1" width="3300" x="0" y="0"/>
<line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="292" y2="292"/>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 322)">Weight/Scale Variations</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 559.711 322)">Ultralight</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 856.422 322)">Thin</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1153.13 322)">Light</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1449.84 322)">Regular</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1746.56 322)">Medium</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2043.27 322)">Semibold</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2339.98 322)">Bold</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2636.69 322)">Heavy</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2933.4 322)">Black</text>
<line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1903" y2="1903"/>
<g transform="matrix(1 0 0 1 263 1933)">
<path d="M9.24805 0.830078C13.5547 0.830078 17.1387-2.74414 17.1387-7.05078C17.1387-11.3574 13.5449-14.9316 9.23828-14.9316C4.94141-14.9316 1.36719-11.3574 1.36719-7.05078C1.36719-2.74414 4.95117 0.830078 9.24805 0.830078ZM9.24805-0.654297C5.70312-0.654297 2.87109-3.49609 2.87109-7.05078C2.87109-10.6055 5.69336-13.4473 9.23828-13.4473C12.793-13.4473 15.6445-10.6055 15.6445-7.05078C15.6445-3.49609 12.8027-0.654297 9.24805-0.654297ZM5.6543-7.05078C5.6543-6.62109 5.95703-6.32812 6.40625-6.32812L8.50586-6.32812L8.50586-4.20898C8.50586-3.76953 8.79883-3.4668 9.22852-3.4668C9.67773-3.4668 9.9707-3.76953 9.9707-4.20898L9.9707-6.32812L12.0898-6.32812C12.5293-6.32812 12.832-6.62109 12.832-7.05078C12.832-7.49023 12.5293-7.79297 12.0898-7.79297L9.9707-7.79297L9.9707-9.90234C9.9707-10.3516 9.67773-10.6543 9.22852-10.6543C8.79883-10.6543 8.50586-10.3516 8.50586-9.90234L8.50586-7.79297L6.40625-7.79297C5.95703-7.79297 5.6543-7.49023 5.6543-7.05078Z"/>
</g>
<g transform="matrix(1 0 0 1 281.867 1933)">
<path d="M11.709 2.91016C17.1582 2.91016 21.6699-1.61133 21.6699-7.05078C21.6699-12.5 17.1484-17.0117 11.6992-17.0117C6.25977-17.0117 1.74805-12.5 1.74805-7.05078C1.74805-1.61133 6.26953 2.91016 11.709 2.91016ZM11.709 1.25C7.09961 1.25 3.41797-2.44141 3.41797-7.05078C3.41797-11.6602 7.08984-15.3516 11.6992-15.3516C16.3086-15.3516 20.0098-11.6602 20.0098-7.05078C20.0098-2.44141 16.3184 1.25 11.709 1.25ZM7.17773-7.05078C7.17773-6.57227 7.50977-6.25 8.00781-6.25L10.8789-6.25L10.8789-3.36914C10.8789-2.88086 11.2109-2.53906 11.6895-2.53906C12.1777-2.53906 12.5195-2.87109 12.5195-3.36914L12.5195-6.25L15.4004-6.25C15.8887-6.25 16.2305-6.57227 16.2305-7.05078C16.2305-7.53906 15.8887-7.88086 15.4004-7.88086L12.5195-7.88086L12.5195-10.752C12.5195-11.25 12.1777-11.5918 11.6895-11.5918C11.2109-11.5918 10.8789-11.25 10.8789-10.752L10.8789-7.88086L8.00781-7.88086C7.50977-7.88086 7.17773-7.53906 7.17773-7.05078Z"/>
</g>
<g transform="matrix(1 0 0 1 305.646 1933)">
<path d="M14.9707 5.66406C21.9336 5.66406 27.6953-0.0976562 27.6953-7.05078C27.6953-14.0137 21.9238-19.7754 14.9609-19.7754C8.00781-19.7754 2.25586-14.0137 2.25586-7.05078C2.25586-0.0976562 8.01758 5.66406 14.9707 5.66406ZM14.9707 3.84766C8.93555 3.84766 4.08203-1.01562 4.08203-7.05078C4.08203-13.0957 8.92578-17.9492 14.9609-17.9492C21.0059-17.9492 25.8691-13.0957 25.8691-7.05078C25.8691-1.01562 21.0156 3.84766 14.9707 3.84766ZM9.19922-7.05078C9.19922-6.5332 9.57031-6.17188 10.1172-6.17188L14.0625-6.17188L14.0625-2.2168C14.0625-1.67969 14.4336-1.29883 14.9512-1.29883C15.4883-1.29883 15.8594-1.66992 15.8594-2.2168L15.8594-6.17188L19.8145-6.17188C20.3516-6.17188 20.7324-6.5332 20.7324-7.05078C20.7324-7.59766 20.3613-7.96875 19.8145-7.96875L15.8594-7.96875L15.8594-11.9141C15.8594-12.4609 15.4883-12.8418 14.9512-12.8418C14.4336-12.8418 14.0625-12.4609 14.0625-11.9141L14.0625-7.96875L10.1172-7.96875C9.57031-7.96875 9.19922-7.59766 9.19922-7.05078Z"/>
</g>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 1953)">Design Variations</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1971)">Symbols are supported in up to nine weights and three scales.</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1989)">For optimal layout with text and other symbols, vertically align</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 2007)">symbols with the adjacent text.</text>
<line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="776" x2="776" y1="1919" y2="1933"/>
<g transform="matrix(1 0 0 1 776 1933)">
<path d="M3.31055 0.15625C3.82812 0.15625 4.08203-0.0390625 4.26758-0.585938L5.52734-4.0332L11.2891-4.0332L12.5488-0.585938C12.7344-0.0390625 12.9883 0.15625 13.4961 0.15625C14.0137 0.15625 14.3457-0.15625 14.3457-0.644531C14.3457-0.810547 14.3164-0.966797 14.2383-1.17188L9.6582-13.3691C9.43359-13.9648 9.0332-14.2676 8.4082-14.2676C7.80273-14.2676 7.39258-13.9746 7.17773-13.3789L2.59766-1.16211C2.51953-0.957031 2.49023-0.800781 2.49023-0.634766C2.49023-0.146484 2.80273 0.15625 3.31055 0.15625ZM6.00586-5.51758L8.37891-12.0898L8.42773-12.0898L10.8008-5.51758Z"/>
</g>
<line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="793.197" x2="793.197" y1="1919" y2="1933"/>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 776 1953)">Margins</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1971)">Leading and trailing margins on the left and right side of each symbol</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1989)">can be adjusted by modifying the x-location of the margin guidelines.</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2007)">Modifications are automatically applied proportionally to all</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2025)">scales and weights.</text>
<g transform="matrix(1 0 0 1 1289 1933)">
<path d="M2.8418 1.86523L4.54102 3.57422C5.40039 4.44336 6.38672 4.38477 7.31445 3.35938L18.0078-8.42773L17.041-9.4043L6.42578 2.27539C6.07422 2.67578 5.74219 2.77344 5.27344 2.30469L4.10156 1.14258C3.63281 0.683594 3.74023 0.341797 4.14062-0.0195312L15.6152-10.8203L14.6387-11.7871L3.04688-0.898438C2.06055 0.0195312 1.98242 0.996094 2.8418 1.86523ZM9.25781-16.3281C8.83789-15.918 8.80859-15.3418 9.04297-14.9512C9.27734-14.5898 9.73633-14.3555 10.3809-14.5215C11.8457-14.8633 13.3691-14.9219 14.7949-13.9844L14.209-12.5293C13.8672-11.6992 14.043-11.1133 14.5801-10.5664L16.875-8.25195C17.3633-7.76367 17.7734-7.74414 18.3398-7.8418L19.4043-8.03711L20.0684-7.36328L20.0293-6.80664C19.9902-6.30859 20.1172-5.92773 20.6055-5.44922L21.3672-4.70703C21.8457-4.22852 22.4609-4.19922 22.9297-4.66797L25.8398-7.58789C26.3086-8.05664 26.2891-8.65234 25.8105-9.13086L25.0391-9.89258C24.5605-10.3711 24.1895-10.5273 23.7109-10.4883L23.1348-10.4395L22.4902-11.0742L22.7344-12.1973C22.8613-12.7637 22.7051-13.2031 22.1191-13.7891L19.9219-15.9766C16.582-19.2969 12.1484-19.2188 9.25781-16.3281ZM10.752-15.957C13.1836-17.7344 16.4746-17.4316 18.7012-15.2051L21.1328-12.793C21.3672-12.5586 21.4062-12.373 21.3379-12.0312L21.0156-10.5469L22.5195-9.0625L23.5059-9.12109C23.7598-9.13086 23.8379-9.11133 24.0332-8.91602L24.6094-8.33984L22.168-5.89844L21.5918-6.47461C21.3965-6.66992 21.3672-6.74805 21.377-7.01172L21.4453-7.98828L19.9512-9.47266L18.4277-9.21875C18.1055-9.15039 17.959-9.17969 17.7148-9.41406L15.7129-11.416C15.459-11.6504 15.4297-11.8164 15.5859-12.1875L16.4648-14.2773C14.9023-15.7324 12.8711-16.3574 10.8398-15.7617C10.6836-15.7227 10.625-15.8496 10.752-15.957Z"/>
</g>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 1289 1953)">Exporting</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1971)">Symbols should be outlined when exporting to ensure the</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1989)">design is preserved when submitting to Xcode.</text>
<text id="template-version" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1933)">Template v.4.0</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1951)">Requires Xcode 14 or greater</text>
<text id="descriptive-name" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1969)">Generated from tomato.fresh</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1987)">Typeset at 100 points</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 726)">Small</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1156)">Medium</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1586)">Large</text>
</g>
<g id="Guides">
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 696)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="696" y2="696"/>
<line id="Capline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="625.541" y2="625.541"/>
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1126)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1126" y2="1126"/>
<line id="Capline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1055.54" y2="1055.54"/>
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1556)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1556" y2="1556"/>
<line id="Capline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1485.54" y2="1485.54"/>
<line id="left-margin-Ultralight-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="515.649" x2="515.649" y1="600.785" y2="720.121"/>
<line id="right-margin-Ultralight-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="603.773" x2="603.773" y1="600.785" y2="720.121"/>
<line id="left-margin-Regular-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1403.58" x2="1403.58" y1="600.785" y2="720.121"/>
<line id="right-margin-Regular-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1496.11" x2="1496.11" y1="600.785" y2="720.121"/>
<line id="left-margin-Black-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="2884.57" x2="2884.57" y1="600.785" y2="720.121"/>
<line id="right-margin-Black-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="2982.23" x2="2982.23" y1="600.785" y2="720.121"/>
</g>
<g id="Symbols">
<g id="Black-S" transform="matrix(1 0 0 1 2884.57 696)">
<path class="monochrome-0 multicolor-0:systemRedColor hierarchical-0:secondary SFSymbolsPreviewFF3B30" d="M49.4127 2C70.9422 2 88.43-15.2738 88.43-34.659C88.43-49.9606 77.5347-62.1033 62.3552-66.54C58.3042-67.724 55.266-65.7527 50.7305-65.7527C47.7164-65.7527 43.4645-68.0482 40.6469-67.4599C23.3378-63.846 10.43-49.7715 10.43-33.1C10.43-13.7148 27.8831 2 49.4127 2Z"/>
<path class="monochrome-1 multicolor-1:systemGreenColor hierarchical-1:primary SFSymbolsPreview28CD41" d="M31.9398-75.8304L37.3183-79L41.3706-69.7126C43.6407-73.4144 46.4001-75.4173 49.6489-75.7211C51.8078-75.9231 54.0339-74.8539 56.3274-72.5136C54.8261-71.9822 53.7355-71.4086 53.0555-70.7926C52.3755-70.1766 51.9189-69.0549 51.6856-67.4276C55.2246-68.3855 58.9859-68.3855 62.9696-67.4276C67.6129-66.311 70.5565-64.4927 71.8005-61.9729C70.9417-62.3004 70.0301-62.4642 69.0657-62.4642C68.6354-62.4642 66.4899-62.1242 62.9696-61.2767C60.2365-60.6187 56.6382-59.2711 52.9705-59.0969C50.8635-58.9969 48.7896-59.4887 46.7486-60.5725C46.7486-57.2584 45.7664-54.7676 43.8018-53.1001C41.8373-51.4325 38.8409-50.5081 34.8127-50.3269C36.0341-52.8562 36.7024-54.7064 36.8177-55.8773C36.933-57.0482 36.5593-58.1905 35.6966-59.3042C33.3224-56.6185 30.7636-55.0668 28.0201-54.6489C25.2767-54.2311 21.2045-54.8542 15.8036-56.5183C16.3082-56.7038 16.7834-56.934 17.229-57.2087C20.9102-59.4785 23.2579-61.1589 25.4449-62.1321C29.3279-63.8601 30.8857-63.2157 30.4659-63.3733C27.331-64.5501 23.7698-64.8451 19.7822-64.2583C22.4889-67.6436 25.2349-69.6532 28.0201-70.2871C30.8054-70.9209 33.7819-70.6065 36.9496-69.3439L31.9398-75.8304Z"/>
</g>
<g id="Regular-S" transform="matrix(1 0 0 1 1403.58 696)">
<path class="monochrome-0 multicolor-0:systemRedColor hierarchical-0:secondary SFSymbolsPreviewFF3B30" d="M47.4027 2C68.9322 2 86.42-15.2738 86.42-34.659C86.42-49.9606 75.5247-62.1033 60.3452-66.54C56.2942-67.724 53.256-65.7527 48.7205-65.7527C45.7064-65.7527 41.4545-68.0482 38.6369-67.4599C21.3278-63.846 8.42-49.7715 8.42-33.1C8.42-13.7148 25.8731 2 47.4027 2Z"/>
<path class="monochrome-1 multicolor-1:systemGreenColor hierarchical-1:primary SFSymbolsPreview28CD41" d="M29.9298-75.8304L35.3083-79L39.3606-69.7126C41.6307-73.4144 44.3901-75.4173 47.6389-75.7211C49.7978-75.9231 52.0239-74.8539 54.3174-72.5136C52.8161-71.9822 51.7255-71.4086 51.0455-70.7926C50.3655-70.1766 49.9089-69.0549 49.6756-67.4276C53.2146-68.3855 56.9759-68.3855 60.9596-67.4276C65.6029-66.311 68.5465-64.4927 69.7905-61.9729C68.9317-62.3004 68.0201-62.4642 67.0557-62.4642C66.6254-62.4642 64.4799-62.1242 60.9596-61.2767C58.2265-60.6187 54.6282-59.2711 50.9605-59.0969C48.8535-58.9969 46.7796-59.4887 44.7386-60.5725C44.7386-57.2584 43.7564-54.7676 41.7918-53.1001C39.8273-51.4325 36.8309-50.5081 32.8027-50.3269C34.0241-52.8562 34.6924-54.7064 34.8077-55.8773C34.923-57.0482 34.5493-58.1905 33.6866-59.3042C31.3124-56.6185 28.7536-55.0668 26.0101-54.6489C23.2667-54.2311 19.1945-54.8542 13.7936-56.5183C14.2982-56.7038 14.7734-56.934 15.219-57.2087C18.9002-59.4785 21.2479-61.1589 23.4349-62.1321C27.3179-63.8601 28.8757-63.2157 28.4559-63.3733C25.321-64.5501 21.7598-64.8451 17.7722-64.2583C20.4789-67.6436 23.2249-69.6532 26.0101-70.2871C28.7954-70.9209 31.7719-70.6065 34.9396-69.3439L29.9298-75.8304Z"/>
</g>
<g id="Ultralight-S" transform="matrix(1 0 0 1 515.649 696)">
<path class="monochrome-0 multicolor-0:systemRedColor hierarchical-0:secondary SFSymbolsPreviewFF3B30" d="M44.3337 2C65.8632 2 83.351-15.2738 83.351-34.659C83.351-49.9606 72.4557-62.1033 57.2762-66.54C53.2252-67.724 50.187-65.7527 45.6515-65.7527C42.6374-65.7527 38.3855-68.0482 35.5679-67.4599C18.2588-63.846 5.351-49.7715 5.351-33.1C5.351-13.7148 22.8041 2 44.3337 2Z"/>
<path class="monochrome-1 multicolor-1:systemGreenColor hierarchical-1:primary SFSymbolsPreview28CD41" d="M26.8608-75.8304L32.2393-79L36.2916-69.7126C38.5617-73.4144 41.3211-75.4173 44.5699-75.7211C46.7288-75.9231 48.9549-74.8539 51.2484-72.5136C49.7471-71.9822 48.6565-71.4086 47.9765-70.7926C47.2965-70.1766 46.8399-69.0549 46.6066-67.4276C50.1456-68.3855 53.9069-68.3855 57.8906-67.4276C62.5339-66.311 65.4775-64.4927 66.7215-61.9729C65.8627-62.3004 64.9511-62.4642 63.9867-62.4642C63.5564-62.4642 61.4109-62.1242 57.8906-61.2767C55.1575-60.6187 51.5592-59.2711 47.8915-59.0969C45.7845-58.9969 43.7106-59.4887 41.6696-60.5725C41.6696-57.2584 40.6874-54.7676 38.7228-53.1001C36.7583-51.4325 33.7619-50.5081 29.7337-50.3269C30.9551-52.8562 31.6234-54.7064 31.7387-55.8773C31.854-57.0482 31.4803-58.1905 30.6176-59.3042C28.2434-56.6185 25.6846-55.0668 22.9411-54.6489C20.1977-54.2311 16.1255-54.8542 10.7246-56.5183C11.2292-56.7038 11.7044-56.934 12.15-57.2087C15.8312-59.4785 18.1789-61.1589 20.3659-62.1321C24.2489-63.8601 25.8067-63.2157 25.3869-63.3733C22.252-64.5501 18.6908-64.8451 14.7032-64.2583C17.4099-67.6436 20.1559-69.6532 22.9411-70.2871C25.7264-70.9209 28.7029-70.6065 31.8706-69.3439L26.8608-75.8304Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"symbols" : [
{
"filename" : "tomato.rotten.svg",
"idiom" : "universal"
}
]
}

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3300" height="2200">
<!--glyph: "", point size: 100.0, font version: "18.0d12e2", template writer version: "101"-->
<style>.monochrome-0 {fill:#000000}
.SFSymbolsPreview000000 {fill:#000000;opacity:1.0}
</style>
<g id="Notes">
<rect height="2200" id="artboard" style="fill:white;opacity:1" width="3300" x="0" y="0"/>
<line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="292" y2="292"/>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 322)">Weight/Scale Variations</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 559.711 322)">Ultralight</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 856.422 322)">Thin</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1153.13 322)">Light</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1449.84 322)">Regular</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1746.56 322)">Medium</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2043.27 322)">Semibold</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2339.98 322)">Bold</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2636.69 322)">Heavy</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2933.4 322)">Black</text>
<line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1903" y2="1903"/>
<g transform="matrix(1 0 0 1 263 1933)">
<path d="M9.24805 0.830078C13.5547 0.830078 17.1387-2.74414 17.1387-7.05078C17.1387-11.3574 13.5449-14.9316 9.23828-14.9316C4.94141-14.9316 1.36719-11.3574 1.36719-7.05078C1.36719-2.74414 4.95117 0.830078 9.24805 0.830078ZM9.24805-0.654297C5.70312-0.654297 2.87109-3.49609 2.87109-7.05078C2.87109-10.6055 5.69336-13.4473 9.23828-13.4473C12.793-13.4473 15.6445-10.6055 15.6445-7.05078C15.6445-3.49609 12.8027-0.654297 9.24805-0.654297ZM5.6543-7.05078C5.6543-6.62109 5.95703-6.32812 6.40625-6.32812L8.50586-6.32812L8.50586-4.20898C8.50586-3.76953 8.79883-3.4668 9.22852-3.4668C9.67773-3.4668 9.9707-3.76953 9.9707-4.20898L9.9707-6.32812L12.0898-6.32812C12.5293-6.32812 12.832-6.62109 12.832-7.05078C12.832-7.49023 12.5293-7.79297 12.0898-7.79297L9.9707-7.79297L9.9707-9.90234C9.9707-10.3516 9.67773-10.6543 9.22852-10.6543C8.79883-10.6543 8.50586-10.3516 8.50586-9.90234L8.50586-7.79297L6.40625-7.79297C5.95703-7.79297 5.6543-7.49023 5.6543-7.05078Z"/>
</g>
<g transform="matrix(1 0 0 1 281.867 1933)">
<path d="M11.709 2.91016C17.1582 2.91016 21.6699-1.61133 21.6699-7.05078C21.6699-12.5 17.1484-17.0117 11.6992-17.0117C6.25977-17.0117 1.74805-12.5 1.74805-7.05078C1.74805-1.61133 6.26953 2.91016 11.709 2.91016ZM11.709 1.25C7.09961 1.25 3.41797-2.44141 3.41797-7.05078C3.41797-11.6602 7.08984-15.3516 11.6992-15.3516C16.3086-15.3516 20.0098-11.6602 20.0098-7.05078C20.0098-2.44141 16.3184 1.25 11.709 1.25ZM7.17773-7.05078C7.17773-6.57227 7.50977-6.25 8.00781-6.25L10.8789-6.25L10.8789-3.36914C10.8789-2.88086 11.2109-2.53906 11.6895-2.53906C12.1777-2.53906 12.5195-2.87109 12.5195-3.36914L12.5195-6.25L15.4004-6.25C15.8887-6.25 16.2305-6.57227 16.2305-7.05078C16.2305-7.53906 15.8887-7.88086 15.4004-7.88086L12.5195-7.88086L12.5195-10.752C12.5195-11.25 12.1777-11.5918 11.6895-11.5918C11.2109-11.5918 10.8789-11.25 10.8789-10.752L10.8789-7.88086L8.00781-7.88086C7.50977-7.88086 7.17773-7.53906 7.17773-7.05078Z"/>
</g>
<g transform="matrix(1 0 0 1 305.646 1933)">
<path d="M14.9707 5.66406C21.9336 5.66406 27.6953-0.0976562 27.6953-7.05078C27.6953-14.0137 21.9238-19.7754 14.9609-19.7754C8.00781-19.7754 2.25586-14.0137 2.25586-7.05078C2.25586-0.0976562 8.01758 5.66406 14.9707 5.66406ZM14.9707 3.84766C8.93555 3.84766 4.08203-1.01562 4.08203-7.05078C4.08203-13.0957 8.92578-17.9492 14.9609-17.9492C21.0059-17.9492 25.8691-13.0957 25.8691-7.05078C25.8691-1.01562 21.0156 3.84766 14.9707 3.84766ZM9.19922-7.05078C9.19922-6.5332 9.57031-6.17188 10.1172-6.17188L14.0625-6.17188L14.0625-2.2168C14.0625-1.67969 14.4336-1.29883 14.9512-1.29883C15.4883-1.29883 15.8594-1.66992 15.8594-2.2168L15.8594-6.17188L19.8145-6.17188C20.3516-6.17188 20.7324-6.5332 20.7324-7.05078C20.7324-7.59766 20.3613-7.96875 19.8145-7.96875L15.8594-7.96875L15.8594-11.9141C15.8594-12.4609 15.4883-12.8418 14.9512-12.8418C14.4336-12.8418 14.0625-12.4609 14.0625-11.9141L14.0625-7.96875L10.1172-7.96875C9.57031-7.96875 9.19922-7.59766 9.19922-7.05078Z"/>
</g>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 1953)">Design Variations</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1971)">Symbols are supported in up to nine weights and three scales.</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1989)">For optimal layout with text and other symbols, vertically align</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 2007)">symbols with the adjacent text.</text>
<line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="776" x2="776" y1="1919" y2="1933"/>
<g transform="matrix(1 0 0 1 776 1933)">
<path d="M3.31055 0.15625C3.82812 0.15625 4.08203-0.0390625 4.26758-0.585938L5.52734-4.0332L11.2891-4.0332L12.5488-0.585938C12.7344-0.0390625 12.9883 0.15625 13.4961 0.15625C14.0137 0.15625 14.3457-0.15625 14.3457-0.644531C14.3457-0.810547 14.3164-0.966797 14.2383-1.17188L9.6582-13.3691C9.43359-13.9648 9.0332-14.2676 8.4082-14.2676C7.80273-14.2676 7.39258-13.9746 7.17773-13.3789L2.59766-1.16211C2.51953-0.957031 2.49023-0.800781 2.49023-0.634766C2.49023-0.146484 2.80273 0.15625 3.31055 0.15625ZM6.00586-5.51758L8.37891-12.0898L8.42773-12.0898L10.8008-5.51758Z"/>
</g>
<line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="793.197" x2="793.197" y1="1919" y2="1933"/>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 776 1953)">Margins</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1971)">Leading and trailing margins on the left and right side of each symbol</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1989)">can be adjusted by modifying the x-location of the margin guidelines.</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2007)">Modifications are automatically applied proportionally to all</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2025)">scales and weights.</text>
<g transform="matrix(1 0 0 1 1289 1933)">
<path d="M2.8418 1.86523L4.54102 3.57422C5.40039 4.44336 6.38672 4.38477 7.31445 3.35938L18.0078-8.42773L17.041-9.4043L6.42578 2.27539C6.07422 2.67578 5.74219 2.77344 5.27344 2.30469L4.10156 1.14258C3.63281 0.683594 3.74023 0.341797 4.14062-0.0195312L15.6152-10.8203L14.6387-11.7871L3.04688-0.898438C2.06055 0.0195312 1.98242 0.996094 2.8418 1.86523ZM9.25781-16.3281C8.83789-15.918 8.80859-15.3418 9.04297-14.9512C9.27734-14.5898 9.73633-14.3555 10.3809-14.5215C11.8457-14.8633 13.3691-14.9219 14.7949-13.9844L14.209-12.5293C13.8672-11.6992 14.043-11.1133 14.5801-10.5664L16.875-8.25195C17.3633-7.76367 17.7734-7.74414 18.3398-7.8418L19.4043-8.03711L20.0684-7.36328L20.0293-6.80664C19.9902-6.30859 20.1172-5.92773 20.6055-5.44922L21.3672-4.70703C21.8457-4.22852 22.4609-4.19922 22.9297-4.66797L25.8398-7.58789C26.3086-8.05664 26.2891-8.65234 25.8105-9.13086L25.0391-9.89258C24.5605-10.3711 24.1895-10.5273 23.7109-10.4883L23.1348-10.4395L22.4902-11.0742L22.7344-12.1973C22.8613-12.7637 22.7051-13.2031 22.1191-13.7891L19.9219-15.9766C16.582-19.2969 12.1484-19.2188 9.25781-16.3281ZM10.752-15.957C13.1836-17.7344 16.4746-17.4316 18.7012-15.2051L21.1328-12.793C21.3672-12.5586 21.4062-12.373 21.3379-12.0312L21.0156-10.5469L22.5195-9.0625L23.5059-9.12109C23.7598-9.13086 23.8379-9.11133 24.0332-8.91602L24.6094-8.33984L22.168-5.89844L21.5918-6.47461C21.3965-6.66992 21.3672-6.74805 21.377-7.01172L21.4453-7.98828L19.9512-9.47266L18.4277-9.21875C18.1055-9.15039 17.959-9.17969 17.7148-9.41406L15.7129-11.416C15.459-11.6504 15.4297-11.8164 15.5859-12.1875L16.4648-14.2773C14.9023-15.7324 12.8711-16.3574 10.8398-15.7617C10.6836-15.7227 10.625-15.8496 10.752-15.957Z"/>
</g>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 1289 1953)">Exporting</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1971)">Symbols should be outlined when exporting to ensure the</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1989)">design is preserved when submitting to Xcode.</text>
<text id="template-version" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1933)">Template v.4.0</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1951)">Requires Xcode 14 or greater</text>
<text id="descriptive-name" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1969)">Generated from tomato.rotten</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1987)">Typeset at 100 points</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 726)">Small</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1156)">Medium</text>
<text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1586)">Large</text>
</g>
<g id="Guides">
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 696)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="696" y2="696"/>
<line id="Capline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="625.541" y2="625.541"/>
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1126)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1126" y2="1126"/>
<line id="Capline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1055.54" y2="1055.54"/>
<g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1556)">
<path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/>
</g>
<line id="Baseline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1556" y2="1556"/>
<line id="Capline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1485.54" y2="1485.54"/>
<line id="left-margin-Ultralight-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="515.649" x2="515.649" y1="600.785" y2="720.121"/>
<line id="right-margin-Ultralight-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="603.773" x2="603.773" y1="600.785" y2="720.121"/>
<line id="left-margin-Regular-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1403.58" x2="1403.58" y1="600.785" y2="720.121"/>
<line id="right-margin-Regular-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1496.11" x2="1496.11" y1="600.785" y2="720.121"/>
<line id="left-margin-Black-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="2884.57" x2="2884.57" y1="600.785" y2="720.121"/>
<line id="right-margin-Black-S" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="2982.23" x2="2982.23" y1="600.785" y2="720.121"/>
</g>
<g id="Symbols">
<g id="Black-S" transform="matrix(1 0 0 1 2884.57 696)">
<path class="monochrome-0 SFSymbolsPreview000000" d="M33.6764-55.7618C25.3651-60.6086 26.1513-71.156 34.9573-75.2344C50.9141-79.2236 52.7423-66.8174 48.7934-56.6585C44.7975-41.9318 59.846-42.2055 60.9638-50.5094C63.1657-61.7557 72.8098-66.815 80.3081-60.5017C88.0031-53.0895 84.629-38.1576 69.4192-39.6199C59.6279-40.5636 57.4767-27.6572 69.9317-26.6811C89.6169-25.5114 95.885-13.1413 88.8912-4.77441C79.1225 4.47936 65.8692-7.4858 61.092-16.6883C56.9385-22.3731 50.5122-16.6211 52.8931-12.7168C60.8233-0.827361 54.6785 6.35821 46.2316 5.98623C38.0651 5.46704 33.4291 0.452287 38.1604-11.8189C40.5407-19.4424 32.9105-21.2168 28.0393-15.1478C20.8885-3.16982 10.4082-6.79192 7.28639-12.5885C5.30554-17.2435 5.50222-28.3755 22.0185-27.0623C32.2117-24.5353 29.2114-34.7346 21.6337-35.3894C15.9868-35.66 3.00339-39.8508 7.67059-50.3787C12.1539-57.1318 22.9152-57.5667 28.0399-46.5349C29.8949-43.9499 33.1469-39.7903 39.0571-43.4607C41.201-46.6351 39.7961-51.9509 33.6764-55.7593L33.6764-55.7618Z"/>
</g>
<g id="Regular-S" transform="matrix(1 0 0 1 1403.58 696)">
<path class="monochrome-0 SFSymbolsPreview000000" d="M30.6664-55.7618C22.3551-60.6086 23.1413-71.156 31.9473-75.2344C47.9041-79.2236 49.7323-66.8174 45.7834-56.6585C41.7875-41.9318 56.836-42.2055 57.9538-50.5094C60.1557-61.7557 69.7998-66.815 77.2981-60.5017C84.9931-53.0895 81.619-38.1576 66.4092-39.6199C56.6179-40.5636 54.4667-27.6572 66.9217-26.6811C86.6069-25.5114 92.875-13.1413 85.8812-4.77441C76.1125 4.47936 62.8592-7.4858 58.082-16.6883C53.9285-22.3731 47.5022-16.6211 49.8831-12.7168C57.8133-0.827361 51.6685 6.35821 43.2216 5.98623C35.0551 5.46704 30.4191 0.452287 35.1504-11.8189C37.5307-19.4424 29.9005-21.2168 25.0293-15.1478C17.8785-3.16982 7.39824-6.79192 4.27639-12.5885C2.29554-17.2435 2.49222-28.3755 19.0085-27.0623C29.2017-24.5353 26.2014-34.7346 18.6237-35.3894C12.9768-35.66-0.00660683-39.8508 4.66059-50.3787C9.14394-57.1318 19.9052-57.5667 25.0299-46.5349C26.8849-43.9499 30.1369-39.7903 36.0471-43.4607C38.191-46.6351 36.7861-51.9509 30.6664-55.7593L30.6664-55.7618Z"/>
</g>
<g id="Ultralight-S" transform="matrix(1 0 0 1 515.649 696)">
<path class="monochrome-0 SFSymbolsPreview000000" d="M28.5974-55.7618C20.2861-60.6086 21.0723-71.156 29.8783-75.2344C45.8351-79.2236 47.6633-66.8174 43.7144-56.6585C39.7185-41.9318 54.767-42.2055 55.8848-50.5094C58.0867-61.7557 67.7308-66.815 75.2291-60.5017C82.9241-53.0895 79.55-38.1576 64.3402-39.6199C54.5489-40.5636 52.3977-27.6572 64.8527-26.6811C84.5379-25.5114 90.806-13.1413 83.8122-4.77441C74.0435 4.47936 60.7902-7.4858 56.013-16.6883C51.8595-22.3731 45.4332-16.6211 47.8141-12.7168C55.7443-0.827361 49.5995 6.35821 41.1526 5.98623C32.9861 5.46704 28.3501 0.452287 33.0814-11.8189C35.4617-19.4424 27.8315-21.2168 22.9603-15.1478C15.8095-3.16982 5.32924-6.79192 2.20739-12.5885C0.226536-17.2435 0.423217-28.3755 16.9395-27.0623C27.1327-24.5353 24.1324-34.7346 16.5547-35.3894C10.9078-35.66-2.07561-39.8508 2.59159-50.3787C7.07494-57.1318 17.8362-57.5667 22.9609-46.5349C24.8159-43.9499 28.0679-39.7903 33.9781-43.4607C36.122-46.6351 34.7171-51.9509 28.5974-55.7593L28.5974-55.7618Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,49 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
struct ItemOverviewView: View {
let item: BaseItemDto
@ViewBuilder
private var content: some View {
GeometryReader { proxy in
VStack(alignment: .center) {
Text(item.displayTitle)
.font(.title)
.frame(maxHeight: proxy.size.height * 0.33)
VStack(alignment: .leading, spacing: 20) {
if let tagline = item.taglines?.first {
Text(tagline)
.fontWeight(.semibold)
.multilineTextAlignment(.leading)
}
if let overview = item.overview {
Text(overview)
}
}
}
.padding(.horizontal, 100)
}
}
var body: some View {
ZStack {
BlurView()
content
}
.ignoresSafeArea()
}
}

View File

@ -16,43 +16,38 @@ extension ItemView {
var viewModel: ItemViewModel
var body: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: 0) {
L10n.about.text
.font(.title3)
.font(.title2)
.fontWeight(.semibold)
.accessibility(addTraits: [.isHeader])
.padding(.leading, 50)
ScrollView(.horizontal) {
HStack(spacing: 30) {
ImageView(
viewModel.item.type == .episode ? viewModel.item.seriesImageSource(.primary, maxWidth: 300) : viewModel.item
.imageSource(.primary, maxWidth: 300)
)
.failure {
InitialFailureView(viewModel.item.title.initials)
}
.posterStyle(type: .portrait, width: 270)
HStack(alignment: .top, spacing: 30) {
PosterButton(item: viewModel.item, type: .portrait)
.content {
EmptyView()
}
.imageOverlay {
EmptyView()
}
.scaleItem(1.35)
InformationCard(
title: viewModel.item.displayTitle,
content: viewModel.item.overview ?? L10n.noOverviewAvailable
)
OverviewCard(item: viewModel.item)
if let subtitleStreams = viewModel.playButtonItem?.subtitleStreams, !subtitleStreams.isEmpty {
InformationCard(
title: L10n.subtitles,
content: subtitleStreams.compactMap(\.displayTitle).joined(separator: ", ")
)
if let mediaSources = viewModel.item.mediaSources {
ForEach(mediaSources) { source in
MediaSourcesCard(subtitle: mediaSources.count > 1 ? source.displayTitle : nil, source: source)
}
}
if let audioStreams = viewModel.playButtonItem?.audioStreams, !audioStreams.isEmpty {
InformationCard(title: L10n.audio, content: audioStreams.compactMap(\.displayTitle).joined(separator: ", "))
if viewModel.item.hasRatings {
RatingsCard(item: viewModel.item)
}
}
.padding(.horizontal, 50)
.padding(.top)
.padding(.bottom, 100)
.padding(50)
}
}
.focusSection()

View File

@ -1,53 +0,0 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
extension ItemView.AboutView {
struct InformationCard: View {
@State
private var presentingAlert: Bool = false
let title: String
let content: String
var body: some View {
Button {
presentingAlert = true
} label: {
VStack(alignment: .leading) {
title.text
.font(.title3)
.fontWeight(.semibold)
.lineLimit(2)
Spacer()
.frame(maxWidth: .infinity)
TruncatedTextView(text: content)
.font(.subheadline)
.lineLimit(4)
}
.padding2()
.frame(width: 700, height: 405)
}
.buttonStyle(.card)
.alert(title, isPresented: $presentingAlert) {
Button {
presentingAlert = false
} label: {
L10n.close.text
}
} message: {
Text(content)
}
}
}
}

View File

@ -0,0 +1,67 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
extension ItemView.AboutView {
struct Card: View {
private var content: () -> any View
private var onSelect: () -> Void
private let title: String
private let subtitle: String?
var body: some View {
Button {
onSelect()
} label: {
VStack(alignment: .leading) {
Text(title)
.font(.title3)
.fontWeight(.semibold)
.lineLimit(2)
if let subtitle {
Text(subtitle)
.font(.subheadline)
}
Spacer()
.frame(maxWidth: .infinity)
content()
.eraseToAnyView()
}
.padding2()
.frame(width: 700, height: 405)
}
.buttonStyle(.card)
}
}
}
extension ItemView.AboutView.Card {
init(title: String, subtitle: String? = nil) {
self.init(
content: { EmptyView() },
onSelect: {},
title: title,
subtitle: subtitle
)
}
func content(@ViewBuilder _ content: @escaping () -> any View) -> Self {
copy(modifying: \.content, with: content)
}
func onSelect(_ action: @escaping () -> Void) -> Self {
copy(modifying: \.onSelect, with: action)
}
}

View File

@ -0,0 +1,42 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
extension ItemView.AboutView {
struct MediaSourcesCard: View {
@EnvironmentObject
private var router: ItemCoordinator.Router
let subtitle: String?
let source: MediaSourceInfo
var body: some View {
Card(title: L10n.media, subtitle: subtitle)
.content {
if let mediaStreams = source.mediaStreams {
VStack(alignment: .leading) {
Text(mediaStreams.compactMap(\.displayTitle).prefix(4).joined(separator: "\n"))
.font(.footnote)
if mediaStreams.count > 4 {
L10n.seeMore.text
.font(.footnote)
}
}
}
}
.onSelect {
router.route(to: \.mediaSourceInfo, source)
}
}
}
}

View File

@ -0,0 +1,33 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
extension ItemView.AboutView {
struct OverviewCard: View {
@EnvironmentObject
private var router: ItemCoordinator.Router
let item: BaseItemDto
var body: some View {
Card(title: item.displayTitle)
.content {
TruncatedText(item.overview ?? L10n.noOverviewAvailable)
.font(.subheadline)
.lineLimit(4)
}
.onSelect {
router.route(to: \.itemOverview, item)
}
}
}
}

View File

@ -0,0 +1,55 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
extension ItemView.AboutView {
struct RatingsCard: View {
let item: BaseItemDto
var body: some View {
Card(title: L10n.ratings)
.content {
HStack(alignment: .bottom) {
if let criticRating = item.criticRating {
VStack {
Group {
if criticRating >= 60 {
Image("tomato.fresh")
} else {
Image("tomato.fresh")
}
}
.symbolRenderingMode(.multicolor)
.foregroundStyle(.green, .red)
.font(.largeTitle)
Text("\(criticRating, specifier: "%.0f")")
.font(.title3)
}
}
if let communityRating = item.communityRating {
VStack {
Image(systemName: "star.fill")
.symbolRenderingMode(.multicolor)
.foregroundStyle(.yellow)
.font(.largeTitle)
Text("\(communityRating, specifier: "%.1f")")
.font(.title3)
}
}
}
}
}
}
}

View File

@ -81,6 +81,14 @@ extension ItemView {
}
.padding(.bottom)
if let tagline = viewModel.item.taglines?.first {
Text(tagline)
.font(.subheadline)
.fontWeight(.semibold)
.multilineTextAlignment(.leading)
.lineLimit(1)
}
Text(viewModel.item.overview ?? L10n.noOverviewAvailable)
.font(.subheadline)
.lineLimit(3)

View File

@ -0,0 +1,127 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import JellyfinAPI
import SwiftUI
struct MediaSourceInfoView: View {
@FocusState
private var selectedMediaStream: MediaStream?
@State
private var lastSelectedMediaStream: MediaStream?
let source: MediaSourceInfo
@ViewBuilder
private var content: some View {
GeometryReader { proxy in
VStack(alignment: .center) {
Text(source.displayTitle)
.font(.title)
.frame(maxHeight: proxy.size.height * 0.33)
HStack {
Form {
if let videoStreams = source.videoStreams,
!videoStreams.isEmpty
{
Section(L10n.video) {
ForEach(videoStreams, id: \.self) { stream in
Button {
Text(stream.displayTitle ?? .emptyDash)
}
.focused($selectedMediaStream, equals: stream)
}
}
}
if let audioStreams = source.audioStreams,
!audioStreams.isEmpty
{
Section(L10n.audio) {
ForEach(audioStreams, id: \.self) { stream in
Button {
Text(stream.displayTitle ?? .emptyDash)
}
.focused($selectedMediaStream, equals: stream)
}
}
}
if let subtitleStreams = source.subtitleStreams,
!subtitleStreams.isEmpty
{
Section(L10n.subtitle) {
ForEach(subtitleStreams, id: \.self) { stream in
Button {
Text(stream.displayTitle ?? .emptyDash)
}
.focused($selectedMediaStream, equals: stream)
}
}
}
}
Form {
if let lastSelectedMediaStream {
Section {
ForEach(lastSelectedMediaStream.metadataProperties) { property in
Button {
TextPairView(property)
}
}
}
if !lastSelectedMediaStream.colorProperties.isEmpty {
Section(L10n.color) {
ForEach(lastSelectedMediaStream.colorProperties) { property in
Button {
TextPairView(property)
}
}
}
}
if !lastSelectedMediaStream.deliveryProperties.isEmpty {
Section(L10n.delivery) {
ForEach(lastSelectedMediaStream.deliveryProperties) { property in
Button {
TextPairView(property)
}
}
}
}
} else {
Button {
L10n.none.text
}
}
}
}
.padding2(.horizontal)
}
.frame(maxWidth: .infinity)
}
.onChange(of: selectedMediaStream) { newValue in
guard let newValue else { return }
lastSelectedMediaStream = newValue
}
}
var body: some View {
ZStack {
BlurView()
content
}
.ignoresSafeArea()
}
}

View File

@ -72,35 +72,63 @@ struct ServerListView: View {
}
var body: some View {
innerBody
.navigationTitle(L10n.servers)
.if(!viewModel.servers.isEmpty) { view in
view.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
SFSymbolButton(systemName: "plus.circle.fill")
.onSelect {
router.route(to: \.connectToServer)
}
SplitFormWindowView()
.descriptionView {
VStack {
Image("jellyfin-blob-blue")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 400)
Button {
router.route(to: \.connectToServer)
} label: {
Button {
router.route(to: \.connectToServer)
} label: {
L10n.connect.text
.bold()
.font(.callout)
.frame(width: 400, height: 75)
.background(Color.jellyfinPurple)
}
.buttonStyle(.card)
}
}
}
// .toolbar {
// ToolbarItem(placement: .navigationBarLeading) {
// SFSymbolButton(systemName: "gearshape.fill")
// .onSelect {
// router.route(to: \.basicAppSettings)
// }
.contentView {}
}
// var body: some View {
// innerBody
// .navigationTitle(L10n.servers)
// .if(!viewModel.servers.isEmpty) { view in
// view.toolbar {
// ToolbarItem(placement: .navigationBarTrailing) {
// SFSymbolButton(systemName: "plus.circle.fill")
// .onSelect {
// router.route(to: \.connectToServer)
// }
// }
// }
// }
.alert(item: $longPressedServer) { server in
Alert(
title: Text(server.name),
primaryButton: .destructive(L10n.remove.text, action: { viewModel.remove(server: server) }),
secondaryButton: .cancel()
)
}
.onAppear {
viewModel.fetchServers()
}
}
//// .toolbar {
//// ToolbarItem(placement: .navigationBarLeading) {
//// SFSymbolButton(systemName: "gearshape.fill")
//// .onSelect {
//// router.route(to: \.basicAppSettings)
//// }
//// }
//// }
// .alert(item: $longPressedServer) { server in
// Alert(
// title: Text(server.name),
// primaryButton: .destructive(L10n.remove.text, action: { viewModel.remove(server: server) }),
// secondaryButton: .cancel()
// )
// }
// .onAppear {
// viewModel.fetchServers()
// }
// }
}

View File

@ -0,0 +1,29 @@
//
// 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) 2023 Jellyfin & Jellyfin Contributors
//
import SwiftUI
extension VideoPlayer.Overlay.ActionButtons {
struct SubtitleButton: View {
@EnvironmentObject
private var overlayTimer: TimerProxy
@EnvironmentObject
private var videoPlayerManager: VideoPlayerManager
var body: some View {
SFSymbolButton(systemName: "captions.bubble")
.onSelect {
videoPlayerManager.selectPreviousViewModel()
overlayTimer.start(5)
}
.frame(maxWidth: 30, maxHeight: 30)
}
}
}

View File

@ -8,6 +8,8 @@
import SwiftUI
// TODO: add subtitles button
extension VideoPlayer.Overlay {
struct BarActionButtons: View {

View File

@ -225,6 +225,10 @@
E12186DE2718F1C50010884C /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = E12186DD2718F1C50010884C /* Defaults */; };
E122A9132788EAAD0060FA63 /* MediaStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStream.swift */; };
E122A9142788EAAD0060FA63 /* MediaStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E122A9122788EAAD0060FA63 /* MediaStream.swift */; };
E12376AE2A33D680001F5B44 /* AboutViewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376AD2A33D680001F5B44 /* AboutViewCard.swift */; };
E12376B02A33D6AE001F5B44 /* AboutViewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */; };
E12376B12A33DB33001F5B44 /* MediaSourceInfoCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E170D106294D23BA0017224C /* MediaSourceInfoCoordinator.swift */; };
E12376B32A33DFAC001F5B44 /* ItemOverviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12376B22A33DFAC001F5B44 /* ItemOverviewView.swift */; };
E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */; };
E129428528F080B500796AC6 /* OnReceiveNotificationModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E129428428F080B500796AC6 /* OnReceiveNotificationModifier.swift */; };
E129428628F080B500796AC6 /* OnReceiveNotificationModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E129428428F080B500796AC6 /* OnReceiveNotificationModifier.swift */; };
@ -404,6 +408,8 @@
E1575EA3293E7B1E001665B1 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3C727164B1E009D4DAF /* UIDevice.swift */; };
E1575EA6293E7D40001665B1 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1575EA5293E7D40001665B1 /* VideoPlayer.swift */; };
E1581E27291EF59800D6C640 /* SplitContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1581E26291EF59800D6C640 /* SplitContentView.swift */; };
E158C8D12A31947500C527C5 /* MediaSourceInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E158C8D02A31947500C527C5 /* MediaSourceInfoView.swift */; };
E158C8D32A31967600C527C5 /* ForEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = E158C8D22A31967600C527C5 /* ForEach.swift */; };
E168BD10289A4162001A6922 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E168BD08289A4162001A6922 /* HomeView.swift */; };
E168BD11289A4162001A6922 /* HomeContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E168BD09289A4162001A6922 /* HomeContentView.swift */; };
E168BD13289A4162001A6922 /* ContinueWatchingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E168BD0D289A4162001A6922 /* ContinueWatchingView.swift */; };
@ -464,6 +470,10 @@
E18A8E8328D60BC400333B9A /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18A8E8228D60BC400333B9A /* VideoPlayer.swift */; };
E18A8E8528D60D0000333B9A /* VideoPlayerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18A8E8428D60D0000333B9A /* VideoPlayerCoordinator.swift */; };
E18ACA8B2A14301800BB4F35 /* ScalingButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18ACA8A2A14301800BB4F35 /* ScalingButtonStyle.swift */; };
E18ACA8D2A14773500BB4F35 /* (null) in Sources */ = {isa = PBXBuildFile; };
E18ACA8F2A15A2CF00BB4F35 /* (null) in Sources */ = {isa = PBXBuildFile; };
E18ACA922A15A32F00BB4F35 /* (null) in Sources */ = {isa = PBXBuildFile; };
E18ACA952A15A3E100BB4F35 /* (null) in Sources */ = {isa = PBXBuildFile; };
E18CE0AF28A222240092E7F1 /* PublicUserSignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18CE0AE28A222240092E7F1 /* PublicUserSignInView.swift */; };
E18CE0B228A229E70092E7F1 /* UserDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18CE0B128A229E70092E7F1 /* UserDto.swift */; };
E18CE0B428A22EDA0092E7F1 /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18CE0B328A22EDA0092E7F1 /* RepeatingTimer.swift */; };
@ -548,7 +558,6 @@
E1A1529028FD23D600600579 /* PlaybackSettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528F28FD23D600600579 /* PlaybackSettingsCoordinator.swift */; };
E1A1529128FD23D600600579 /* PlaybackSettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528F28FD23D600600579 /* PlaybackSettingsCoordinator.swift */; };
E1A16C9D2889AF1E00EA4679 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A16C9C2889AF1E00EA4679 /* AboutView.swift */; };
E1A16CA1288A7CFD00EA4679 /* AboutViewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A16CA0288A7CFD00EA4679 /* AboutViewCard.swift */; };
E1A2C154279A7D5A005EC829 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A2C153279A7D5A005EC829 /* UIApplication.swift */; };
E1A42E4A28CA6CCD00A14DCB /* CinematicItemSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A42E4928CA6CCD00A14DCB /* CinematicItemSelector.swift */; };
E1A42E4C28CBD39300A14DCB /* HomeContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A42E4B28CBD39300A14DCB /* HomeContentView.swift */; };
@ -576,7 +585,6 @@
E1B5F7A929577BCE004B26CF /* PulseLogHandler in Frameworks */ = {isa = PBXBuildFile; productRef = E1B5F7A829577BCE004B26CF /* PulseLogHandler */; };
E1B5F7AB29577BCE004B26CF /* PulseUI in Frameworks */ = {isa = PBXBuildFile; productRef = E1B5F7AA29577BCE004B26CF /* PulseUI */; };
E1B5F7AD29577BDD004B26CF /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = E1B5F7AC29577BDD004B26CF /* OrderedCollections */; };
E1B5F7AE29577CC7004B26CF /* VisibilityModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF3182952641300CC0294 /* VisibilityModifier.swift */; };
E1BA6FC529D25DBD007D98DC /* LandscapeItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BA6FC429D25DBD007D98DC /* LandscapeItemElement.swift */; };
E1BDF2E52951475300CC0294 /* VideoPlayerActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF2E42951475300CC0294 /* VideoPlayerActionButton.swift */; };
E1BDF2E62951475300CC0294 /* VideoPlayerActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF2E42951475300CC0294 /* VideoPlayerActionButton.swift */; };
@ -590,7 +598,6 @@
E1BDF2F929524FDA00CC0294 /* PlayPreviousItemActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF2F829524FDA00CC0294 /* PlayPreviousItemActionButton.swift */; };
E1BDF2FB2952502300CC0294 /* SubtitleActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF2FA2952502300CC0294 /* SubtitleActionButton.swift */; };
E1BDF31729525F0400CC0294 /* AdvancedActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF31629525F0400CC0294 /* AdvancedActionButton.swift */; };
E1BDF3192952641300CC0294 /* VisibilityModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BDF3182952641300CC0294 /* VisibilityModifier.swift */; };
E1C812BC277A8E5D00918266 /* PlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812B4277A8E5D00918266 /* PlaybackSpeed.swift */; };
E1C812C5277A90B200918266 /* URLComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812C4277A90B200918266 /* URLComponents.swift */; };
E1C8CE5B28FE512400DF5D7B /* CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C8CE5A28FE512400DF5D7B /* CGPoint.swift */; };
@ -647,9 +654,10 @@
E1DA656A28E78B5900592A73 /* SpecialFeaturesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DA656828E78B5900592A73 /* SpecialFeaturesViewModel.swift */; };
E1DA656C28E78C1700592A73 /* MenuPosterHStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DA656B28E78C1700592A73 /* MenuPosterHStackModel.swift */; };
E1DA656F28E78C9900592A73 /* SeriesEpisodeSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DA656E28E78C9900592A73 /* SeriesEpisodeSelector.swift */; };
E1DABAFA2A270E62008AC34A /* OverviewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAF92A270E62008AC34A /* OverviewCard.swift */; };
E1DABAFC2A270EE7008AC34A /* MediaSourcesCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */; };
E1DABAFE2A27B982008AC34A /* RatingsCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DABAFD2A27B982008AC34A /* RatingsCard.swift */; };
E1DC9814296DC06200982F06 /* PulseLogHandler in Frameworks */ = {isa = PBXBuildFile; productRef = E1DC9813296DC06200982F06 /* PulseLogHandler */; };
E1DC9816296DD0FE00982F06 /* BlurViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC9815296DD0FE00982F06 /* BlurViewModifier.swift */; };
E1DC9817296DD0FE00982F06 /* BlurViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC9815296DD0FE00982F06 /* BlurViewModifier.swift */; };
E1DC9819296DD1CD00982F06 /* CinematicBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC9818296DD1CD00982F06 /* CinematicBackgroundView.swift */; };
E1DC981A296DD1CD00982F06 /* CinematicBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DC9818296DD1CD00982F06 /* CinematicBackgroundView.swift */; };
E1DC981E296DD91900982F06 /* CollectionView in Frameworks */ = {isa = PBXBuildFile; productRef = E1DC981D296DD91900982F06 /* CollectionView */; };
@ -690,17 +698,18 @@
E1E6C45129B104850064123F /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E6C44F29B104840064123F /* Button.swift */; };
E1E6C45429B1304E0064123F /* ChaptersActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E6C45229B1304E0064123F /* ChaptersActionButton.swift */; };
E1E6C45629B130F50064123F /* ChapterOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E6C45529B130F50064123F /* ChapterOverlay.swift */; };
E1E750682A33E9B400B2C1EE /* OverviewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E750652A33E9B400B2C1EE /* OverviewCard.swift */; };
E1E750692A33E9B400B2C1EE /* MediaSourcesCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */; };
E1E7506A2A33E9B400B2C1EE /* RatingsCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E750672A33E9B400B2C1EE /* RatingsCard.swift */; };
E1E9017B28DAAE4D001B1594 /* RoundedCorner.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E9017A28DAAE4D001B1594 /* RoundedCorner.swift */; };
E1E9017F28DAB15F001B1594 /* BarActionButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E9017E28DAB15F001B1594 /* BarActionButtons.swift */; };
E1E9EFEA28C6B96500CC1F8B /* ServerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E9EFE928C6B96400CC1F8B /* ServerButton.swift */; };
E1E9EFEB28C7EA2C00CC1F8B /* UserDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18CE0B128A229E70092E7F1 /* UserDto.swift */; };
E1EA9F6A28F8A79E00BEC442 /* VideoPlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EA9F6928F8A79E00BEC442 /* VideoPlayerManager.swift */; };
E1EA9F6B28F8A79E00BEC442 /* VideoPlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EA9F6928F8A79E00BEC442 /* VideoPlayerManager.swift */; };
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */; };
E1EBCB44278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */; };
E1EBCB42278BD174009FE6E9 /* TruncatedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB41278BD174009FE6E9 /* TruncatedText.swift */; };
E1EBCB46278BD595009FE6E9 /* ItemOverviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */; };
E1EBCB4A278BE443009FE6E9 /* ItemOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */; };
E1EF473A289A0F610034046B /* TruncatedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */; };
E1EF473A289A0F610034046B /* TruncatedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EBCB41278BD174009FE6E9 /* TruncatedText.swift */; };
E1EF4C412911B783008CC695 /* StreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1EF4C402911B783008CC695 /* StreamType.swift */; };
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
E1FA891B289A302300176FEB /* iPadOSCollectionItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FA891A289A302300176FEB /* iPadOSCollectionItemView.swift */; };
@ -936,6 +945,9 @@
E11CEB9328999D9E003E74C7 /* EpisodeItemContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeItemContentView.swift; sourceTree = "<group>"; };
E11D224127378428003F9CB3 /* ServerDetailCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailCoordinator.swift; sourceTree = "<group>"; };
E122A9122788EAAD0060FA63 /* MediaStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaStream.swift; sourceTree = "<group>"; };
E12376AD2A33D680001F5B44 /* AboutViewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewCard.swift; sourceTree = "<group>"; };
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewCard.swift; sourceTree = "<group>"; };
E12376B22A33DFAC001F5B44 /* ItemOverviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewView.swift; sourceTree = "<group>"; };
E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingController.swift; sourceTree = "<group>"; };
E129428428F080B500796AC6 /* OnReceiveNotificationModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnReceiveNotificationModifier.swift; sourceTree = "<group>"; };
E129428728F0831F00796AC6 /* SplitTimestamp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitTimestamp.swift; sourceTree = "<group>"; };
@ -1020,6 +1032,8 @@
E15756352936856700976E1F /* VideoPlayerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerType.swift; sourceTree = "<group>"; };
E1575EA5293E7D40001665B1 /* VideoPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayer.swift; sourceTree = "<group>"; };
E1581E26291EF59800D6C640 /* SplitContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitContentView.swift; sourceTree = "<group>"; };
E158C8D02A31947500C527C5 /* MediaSourceInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceInfoView.swift; sourceTree = "<group>"; };
E158C8D22A31967600C527C5 /* ForEach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForEach.swift; sourceTree = "<group>"; };
E168BD08289A4162001A6922 /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
E168BD09289A4162001A6922 /* HomeContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeContentView.swift; sourceTree = "<group>"; };
E168BD0D289A4162001A6922 /* ContinueWatchingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContinueWatchingView.swift; sourceTree = "<group>"; };
@ -1126,7 +1140,6 @@
E1A1528C28FD23AC00600579 /* VideoPlayerSettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerSettingsCoordinator.swift; sourceTree = "<group>"; };
E1A1528F28FD23D600600579 /* PlaybackSettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSettingsCoordinator.swift; sourceTree = "<group>"; };
E1A16C9C2889AF1E00EA4679 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
E1A16CA0288A7CFD00EA4679 /* AboutViewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewCard.swift; sourceTree = "<group>"; };
E1A2C153279A7D5A005EC829 /* UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
E1A42E4928CA6CCD00A14DCB /* CinematicItemSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicItemSelector.swift; sourceTree = "<group>"; };
E1A42E4B28CBD39300A14DCB /* HomeContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeContentView.swift; sourceTree = "<group>"; };
@ -1156,7 +1169,6 @@
E1BDF2F829524FDA00CC0294 /* PlayPreviousItemActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayPreviousItemActionButton.swift; sourceTree = "<group>"; };
E1BDF2FA2952502300CC0294 /* SubtitleActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleActionButton.swift; sourceTree = "<group>"; };
E1BDF31629525F0400CC0294 /* AdvancedActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedActionButton.swift; sourceTree = "<group>"; };
E1BDF3182952641300CC0294 /* VisibilityModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityModifier.swift; sourceTree = "<group>"; };
E1C812B4277A8E5D00918266 /* PlaybackSpeed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaybackSpeed.swift; sourceTree = "<group>"; };
E1C812C4277A90B200918266 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = "<group>"; };
E1C8CE5A28FE512400DF5D7B /* CGPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGPoint.swift; sourceTree = "<group>"; };
@ -1209,7 +1221,9 @@
E1DA656828E78B5900592A73 /* SpecialFeaturesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecialFeaturesViewModel.swift; sourceTree = "<group>"; };
E1DA656B28E78C1700592A73 /* MenuPosterHStackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuPosterHStackModel.swift; sourceTree = "<group>"; };
E1DA656E28E78C9900592A73 /* SeriesEpisodeSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeriesEpisodeSelector.swift; sourceTree = "<group>"; };
E1DC9815296DD0FE00982F06 /* BlurViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurViewModifier.swift; sourceTree = "<group>"; };
E1DABAF92A270E62008AC34A /* OverviewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewCard.swift; sourceTree = "<group>"; };
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourcesCard.swift; sourceTree = "<group>"; };
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingsCard.swift; sourceTree = "<group>"; };
E1DC9818296DD1CD00982F06 /* CinematicBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CinematicBackgroundView.swift; sourceTree = "<group>"; };
E1DC983C296DEB9B00982F06 /* UnwatchedIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnwatchedIndicator.swift; sourceTree = "<group>"; };
E1DC9840296DEBD800982F06 /* WatchedIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchedIndicator.swift; sourceTree = "<group>"; };
@ -1238,12 +1252,14 @@
E1E6C44F29B104840064123F /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
E1E6C45229B1304E0064123F /* ChaptersActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChaptersActionButton.swift; sourceTree = "<group>"; };
E1E6C45529B130F50064123F /* ChapterOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChapterOverlay.swift; sourceTree = "<group>"; };
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverviewCard.swift; sourceTree = "<group>"; };
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaSourcesCard.swift; sourceTree = "<group>"; };
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RatingsCard.swift; sourceTree = "<group>"; };
E1E9017A28DAAE4D001B1594 /* RoundedCorner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCorner.swift; sourceTree = "<group>"; };
E1E9017E28DAB15F001B1594 /* BarActionButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarActionButtons.swift; sourceTree = "<group>"; };
E1E9EFE928C6B96400CC1F8B /* ServerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerButton.swift; sourceTree = "<group>"; };
E1EA9F6928F8A79E00BEC442 /* VideoPlayerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerManager.swift; sourceTree = "<group>"; };
E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TruncatedTextView.swift; sourceTree = "<group>"; };
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewCoordinator.swift; sourceTree = "<group>"; };
E1EBCB41278BD174009FE6E9 /* TruncatedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TruncatedText.swift; sourceTree = "<group>"; };
E1EBCB45278BD595009FE6E9 /* ItemOverviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemOverviewView.swift; sourceTree = "<group>"; };
E1EF4C402911B783008CC695 /* StreamType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamType.swift; sourceTree = "<group>"; };
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = "<group>"; };
@ -1454,10 +1470,9 @@
isa = PBXGroup;
children = (
E12186DF2718F2030010884C /* App */,
535870662669D21700D05A09 /* Assets.xcassets */,
536D3D77267BB9650004248C /* Components */,
535870702669D21700D05A09 /* Info.plist */,
E185920B28CEF23F00326F80 /* Objects */,
E1DABAD62A26E28E008AC34A /* Resources */,
E12186E02718F23B0010884C /* Views */,
);
path = "Swiftfin tvOS";
@ -1467,6 +1482,7 @@
isa = PBXGroup;
children = (
E1401CA32938123400E8B599 /* AppIcons */,
E1AD105326D96F5A003E4A08 /* Components */,
62C29E9D26D0FE5900C1D2E7 /* Coordinators */,
E1FCD08E26C466F3007C8DCF /* Errors */,
621338912660106C00A81A2A /* Extensions */,
@ -1476,7 +1492,6 @@
E1549654296CA2EF00C4EF88 /* Services */,
6286F09F271C0AA500C40ED5 /* Strings */,
532175392671BCED005491E6 /* ViewModels */,
E1AD105326D96F5A003E4A08 /* Views */,
);
path = Shared;
sourceTree = "<group>";
@ -1572,12 +1587,10 @@
children = (
E13DD3BB27163C3E009D4DAF /* App */,
62ECA01926FA6D6900E8EBB7 /* AppURLHandler */,
5377CBF8263B596B003A4E83 /* Assets.xcassets */,
53F866422687A45400DCD1D7 /* Components */,
5377CC02263B596B003A4E83 /* Info.plist */,
E1DD1127271E7D15005BE12F /* Objects */,
E13D02842788B634000FCB04 /* Swiftfin.entitlements */,
E11CEB85289984F5003E74C7 /* Extensions */,
E1DD1127271E7D15005BE12F /* Objects */,
E1DCDE3B2A2D134000FA9C91 /* Resources */,
E13DD3D027165886009D4DAF /* Views */,
);
path = Swiftfin;
@ -1811,6 +1824,7 @@
E133328729538D8D00EE76AB /* Files.swift */,
E15756312935642A00976E1F /* Float.swift */,
E11CEB8C28999B4A003E74C7 /* Font.swift */,
E158C8D22A31967600C527C5 /* ForEach.swift */,
E1E6C44A29AED2B70064123F /* HorizontalAlignment.swift */,
E139CC1E28EC83E400688DE2 /* Int.swift */,
E1AD105226D96D5F003E4A08 /* JellyfinAPI */,
@ -1854,7 +1868,6 @@
6220D0B926D6092100B8E046 /* FilterCoordinator.swift */,
62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */,
6220D0BF26D61C5000B8E046 /* ItemCoordinator.swift */,
E1EBCB43278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift */,
6220D0B326D5ED8000B8E046 /* LibraryCoordinator.swift */,
C4BE07872728448B003F4AD1 /* LiveTVChannelsCoordinator.swift */,
C45942C427F67DA400C54FE7 /* LiveTVCoordinator.swift */,
@ -2023,11 +2036,13 @@
53ABFDEA2679753200886593 /* ConnectToServerView.swift */,
E154967B296CBB1A00C4EF88 /* FontPickerView.swift */,
E1A42E4D28CBD3B200A14DCB /* HomeView */,
E12376B22A33DFAC001F5B44 /* ItemOverviewView.swift */,
E193D54E271942C000900D82 /* ItemView */,
53A83C32268A309300DF3D92 /* LibraryView.swift */,
C4BE078A272844AF003F4AD1 /* LiveTVChannelsView.swift */,
C4BE078D27298817003F4AD1 /* LiveTVHomeView.swift */,
C4BE07732725EB66003F4AD1 /* LiveTVProgramsView.swift */,
E158C8D02A31947500C527C5 /* MediaSourceInfoView.swift */,
C4E508172703E8190045C9AB /* MediaView.swift */,
E1E1643928BAC2EF00323B0A /* SearchView.swift */,
E193D54F2719430400900D82 /* ServerDetailView.swift */,
@ -2102,6 +2117,7 @@
C400DB6927FE894F007B65FE /* LiveTVChannelsView.swift */,
C4AE2C2F27498D2300AE13CF /* LiveTVHomeView.swift */,
C4AE2C3127498D6A00AE13CF /* LiveTVProgramsView.swift */,
E170D104294D21FA0017224C /* MediaSourceInfoView.swift */,
E19F6C5C28F5189300C5197E /* MediaStreamInfoView.swift */,
6213388F265F83A900A81A2A /* MediaView.swift */,
E1171A1828A2212600FA1AF5 /* QuickConnectView.swift */,
@ -2200,11 +2216,9 @@
children = (
E18E0202288749200022598C /* AttributeStyleModifier.swift */,
E11895B22893844A0042947B /* BackgroundParallaxHeaderModifier.swift */,
E1DC9815296DD0FE00982F06 /* BlurViewModifier.swift */,
E19E551E2897326C003CE330 /* BottomEdgeGradientModifier.swift */,
E129428428F080B500796AC6 /* OnReceiveNotificationModifier.swift */,
E11895A8289383BC0042947B /* ScrollViewOffsetModifier.swift */,
E1BDF3182952641300CC0294 /* VisibilityModifier.swift */,
);
path = Modifiers;
sourceTree = "<group>";
@ -2268,6 +2282,26 @@
path = Components;
sourceTree = "<group>";
};
E18ACA902A15A2D600BB4F35 /* AboutView */ = {
isa = PBXGroup;
children = (
E18ACA932A15A3D800BB4F35 /* Components */,
E18E01D5288747230022598C /* AboutView.swift */,
);
path = AboutView;
sourceTree = "<group>";
};
E18ACA932A15A3D800BB4F35 /* Components */ = {
isa = PBXGroup;
children = (
E12376AD2A33D680001F5B44 /* AboutViewCard.swift */,
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */,
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */,
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */,
);
path = Components;
sourceTree = "<group>";
};
E18CE0B028A222310092E7F1 /* Components */ = {
isa = PBXGroup;
children = (
@ -2384,13 +2418,12 @@
E18E01D4288747230022598C /* Components */ = {
isa = PBXGroup;
children = (
E18E01D5288747230022598C /* AboutView.swift */,
E18ACA902A15A2D600BB4F35 /* AboutView */,
E18E01D9288747230022598C /* ActionButtonHStack.swift */,
E18E01D7288747230022598C /* AttributeHStack.swift */,
E17FB55628C1256400311DFE /* CastAndCrewHStack.swift */,
E17AC9722955007A003D2BC2 /* DownloadTaskButton.swift */,
E17FB55A28C1266400311DFE /* GenresHStack.swift */,
E170D104294D21FA0017224C /* MediaSourceInfoView.swift */,
E1D8424E2932F7C400D1041A /* OverviewView.swift */,
E18E01D8288747230022598C /* PlayButton.swift */,
E1DA656E28E78C9900592A73 /* SeriesEpisodeSelector.swift */,
@ -2442,8 +2475,8 @@
E1A16CA2288A7D0000EA4679 /* AboutView */ = {
isa = PBXGroup;
children = (
E1DABAF82A270B00008AC34A /* Components */,
E1A16C9C2889AF1E00EA4679 /* AboutView.swift */,
E1A16CA0288A7CFD00EA4679 /* AboutViewCard.swift */,
);
path = AboutView;
sourceTree = "<group>";
@ -2484,7 +2517,7 @@
path = JellyfinAPI;
sourceTree = "<group>";
};
E1AD105326D96F5A003E4A08 /* Views */ = {
E1AD105326D96F5A003E4A08 /* Components */ = {
isa = PBXGroup;
children = (
E18E0203288749200022598C /* BlurView.swift */,
@ -2498,10 +2531,10 @@
E1E1643D28BB074000323B0A /* SelectorView.swift */,
E1356E0129A7309D00382563 /* SeparatorHStack.swift */,
E1A1528928FD22F600600579 /* TextPairView.swift */,
E1EBCB41278BD174009FE6E9 /* TruncatedTextView.swift */,
E1EBCB41278BD174009FE6E9 /* TruncatedText.swift */,
E1B5784028F8AFCB00D42911 /* Wrapped View.swift */,
);
path = Views;
path = Components;
sourceTree = "<group>";
};
E1BDF2E7295148F400CC0294 /* VideoPlayerSettingsView */ = {
@ -2607,6 +2640,26 @@
path = Slider;
sourceTree = "<group>";
};
E1DABAD62A26E28E008AC34A /* Resources */ = {
isa = PBXGroup;
children = (
535870662669D21700D05A09 /* Assets.xcassets */,
535870702669D21700D05A09 /* Info.plist */,
);
path = Resources;
sourceTree = "<group>";
};
E1DABAF82A270B00008AC34A /* Components */ = {
isa = PBXGroup;
children = (
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */,
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */,
E1DABAF92A270E62008AC34A /* OverviewCard.swift */,
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */,
);
path = Components;
sourceTree = "<group>";
};
E1DC983F296DEBA500982F06 /* PosterIndicators */ = {
isa = PBXGroup;
children = (
@ -2618,6 +2671,16 @@
path = PosterIndicators;
sourceTree = "<group>";
};
E1DCDE3B2A2D134000FA9C91 /* Resources */ = {
isa = PBXGroup;
children = (
5377CBF8263B596B003A4E83 /* Assets.xcassets */,
5377CC02263B596B003A4E83 /* Info.plist */,
E13D02842788B634000FCB04 /* Swiftfin.entitlements */,
);
path = Resources;
sourceTree = "<group>";
};
E1DD1127271E7D15005BE12F /* Objects */ = {
isa = PBXGroup;
children = (
@ -2969,7 +3032,6 @@
E1575E99293E7B1E001665B1 /* UIColor.swift in Sources */,
E1575E92293E7B1E001665B1 /* CGSize.swift in Sources */,
E1575E96293E7B1E001665B1 /* UIScrollView.swift in Sources */,
E1A16CA1288A7CFD00EA4679 /* AboutViewCard.swift in Sources */,
E11E376D293E9CC1009EF240 /* VideoPlayerCoordinator.swift in Sources */,
E1575E6F293E77B5001665B1 /* GestureAction.swift in Sources */,
E18A8E7E28D606BE00333B9A /* BaseItemDto+VideoPlayerViewModel.swift in Sources */,
@ -2994,7 +3056,6 @@
E1575E6A293E77B5001665B1 /* RoundedCorner.swift in Sources */,
E1575EA1293E7B1E001665B1 /* String.swift in Sources */,
E1E6C45429B1304E0064123F /* ChaptersActionButton.swift in Sources */,
E1EBCB4A278BE443009FE6E9 /* ItemOverviewCoordinator.swift in Sources */,
E1E6C44229AECCD50064123F /* ActionButtons.swift in Sources */,
E1575E78293E77B5001665B1 /* TrailingTimestampType.swift in Sources */,
C4BE07772725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift in Sources */,
@ -3021,12 +3082,15 @@
E12CC1C528D12D9B00678D5D /* SeeAllPosterButton.swift in Sources */,
E18A8E8128D6083700333B9A /* MediaSourceInfo+ItemVideoPlayerViewModel.swift in Sources */,
E1002B652793CEE800E47059 /* ChapterInfo.swift in Sources */,
E12376B32A33DFAC001F5B44 /* ItemOverviewView.swift in Sources */,
E111D8FA28D0400900400001 /* PagingLibraryView.swift in Sources */,
E1D3043328D175CE00587289 /* StaticLibraryViewModel.swift in Sources */,
E1EA9F6B28F8A79E00BEC442 /* VideoPlayerManager.swift in Sources */,
E1FCD08926C35A0D007C8DCF /* NetworkError.swift in Sources */,
E1549661296CA2EF00C4EF88 /* SwiftfinDefaults.swift in Sources */,
E158C8D12A31947500C527C5 /* MediaSourceInfoView.swift in Sources */,
E1575E98293E7B1E001665B1 /* UIApplication.swift in Sources */,
E12376B12A33DB33001F5B44 /* MediaSourceInfoCoordinator.swift in Sources */,
E17885A4278105170094FBCF /* SFSymbolButton.swift in Sources */,
E13DD3ED27178A54009D4DAF /* UserSignInViewModel.swift in Sources */,
E1C9261C288756BD002A7A66 /* PosterHStack.swift in Sources */,
@ -3044,7 +3108,7 @@
E11895AA289383BC0042947B /* ScrollViewOffsetModifier.swift in Sources */,
E1575E76293E77B5001665B1 /* VideoPlayerType.swift in Sources */,
E17AC96B2954D00E003D2BC2 /* URLResponse.swift in Sources */,
E1EF473A289A0F610034046B /* TruncatedTextView.swift in Sources */,
E1EF473A289A0F610034046B /* TruncatedText.swift in Sources */,
E1C926112887565C002A7A66 /* ActionButtonHStack.swift in Sources */,
E178859B2780F1F40094FBCF /* tvOSSlider.swift in Sources */,
E18E02252887492B0022598C /* PlainNavigationLinkButton.swift in Sources */,
@ -3070,7 +3134,7 @@
E1575E9C293E7B1E001665B1 /* Collection.swift in Sources */,
E1C9260F2887565C002A7A66 /* AttributeHStack.swift in Sources */,
E11CEB9428999D9E003E74C7 /* EpisodeItemContentView.swift in Sources */,
E1B5F7AE29577CC7004B26CF /* VisibilityModifier.swift in Sources */,
E12376B02A33D6AE001F5B44 /* AboutViewCard.swift in Sources */,
E12A9EF929499E0100731C3A /* JellyfinClient.swift in Sources */,
E148128328C1443D003B8787 /* NameGuidPair.swift in Sources */,
E185920828CDAAA200326F80 /* SimilarItemsHStack.swift in Sources */,
@ -3101,6 +3165,7 @@
E18A17F0298C68B700C22F62 /* Overlay.swift in Sources */,
E1A42E4A28CA6CCD00A14DCB /* CinematicItemSelector.swift in Sources */,
E154677A289AF48200087E35 /* CollectionItemContentView.swift in Sources */,
E1DABAFC2A270EE7008AC34A /* MediaSourcesCard.swift in Sources */,
E193D53D27193F9700900D82 /* UserSignInCoordinator.swift in Sources */,
C4BE07862728446F003F4AD1 /* LiveTVChannelsViewModel.swift in Sources */,
E1AD104E26D96CE3003E4A08 /* BaseItemDto.swift in Sources */,
@ -3108,7 +3173,6 @@
62E632DD267D2E130063E547 /* SearchViewModel.swift in Sources */,
E1575EA2293E7B1E001665B1 /* Color.swift in Sources */,
E1575E77293E77B5001665B1 /* MenuPosterHStackModel.swift in Sources */,
E1DC9817296DD0FE00982F06 /* BlurViewModifier.swift in Sources */,
E12E30F5296392EC0022FAC9 /* EnumPickerView.swift in Sources */,
E1575E72293E77B5001665B1 /* Utilities.swift in Sources */,
E1575E84293E7A00001665B1 /* PrimaryAppIcon.swift in Sources */,
@ -3123,6 +3187,7 @@
E1575E88293E7A00001665B1 /* LightAppIcon.swift in Sources */,
E1549678296CB22B00C4EF88 /* InlineEnumToggle.swift in Sources */,
E193D5432719407E00900D82 /* tvOSMainCoordinator.swift in Sources */,
E1DABAFA2A270E62008AC34A /* OverviewCard.swift in Sources */,
E11CEB8928998549003E74C7 /* BottomEdgeGradientModifier.swift in Sources */,
E129428628F080B500796AC6 /* OnReceiveNotificationModifier.swift in Sources */,
53ABFDE7267974EF00886593 /* ConnectToServerViewModel.swift in Sources */,
@ -3133,6 +3198,7 @@
E1E5D553278419D900692DFE /* ConfirmCloseOverlay.swift in Sources */,
E18A17F2298C68BB00C22F62 /* MainOverlay.swift in Sources */,
E1E6C44B29AED2B70064123F /* HorizontalAlignment.swift in Sources */,
E158C8D32A31967600C527C5 /* ForEach.swift in Sources */,
E193D549271941CC00900D82 /* UserSignInView.swift in Sources */,
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */,
E148128628C15475003B8787 /* APISortOrder.swift in Sources */,
@ -3216,8 +3282,10 @@
E174121029AE9D94003EF3B5 /* NavigationCoordinatable.swift in Sources */,
E154965F296CA2EF00C4EF88 /* DownloadTask.swift in Sources */,
E154967E296CCB6C00C4EF88 /* BasicNavigationCoordinator.swift in Sources */,
E1DABAFE2A27B982008AC34A /* RatingsCard.swift in Sources */,
E1C9261B288756BD002A7A66 /* DotHStack.swift in Sources */,
E104C873296E0D0A00C1C3F9 /* IndicatorSettingsView.swift in Sources */,
E18ACA8D2A14773500BB4F35 /* (null) in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3245,7 +3313,6 @@
E1E9017F28DAB15F001B1594 /* BarActionButtons.swift in Sources */,
E17FB55928C125E900311DFE /* StudiosHStack.swift in Sources */,
E1C812C5277A90B200918266 /* URLComponents.swift in Sources */,
E1EBCB44278BD1CE009FE6E9 /* ItemOverviewCoordinator.swift in Sources */,
E1C925F428875037002A7A66 /* ItemViewType.swift in Sources */,
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
@ -3323,7 +3390,7 @@
E104C870296E087200C1C3F9 /* IndicatorSettingsView.swift in Sources */,
E12A9EF829499E0100731C3A /* JellyfinClient.swift in Sources */,
E1722DB129491C3900CC0239 /* ImageBlurHashes.swift in Sources */,
E1EBCB42278BD174009FE6E9 /* TruncatedTextView.swift in Sources */,
E1EBCB42278BD174009FE6E9 /* TruncatedText.swift in Sources */,
62133890265F83A900A81A2A /* MediaView.swift in Sources */,
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
E13332942953BAA100EE76AB /* DownloadTaskContentView.swift in Sources */,
@ -3336,6 +3403,7 @@
E18E01DA288747230022598C /* iPadOSEpisodeContentView.swift in Sources */,
E1047E2327E5880000CB0D4A /* InitialFailureView.swift in Sources */,
E1C8CE5B28FE512400DF5D7B /* CGPoint.swift in Sources */,
E18ACA922A15A32F00BB4F35 /* (null) in Sources */,
E1E1E24D28DF8A2E000DF5FD /* PreferenceKeys.swift in Sources */,
E1CEFBF527914C7700F60429 /* CustomizeViewsSettings.swift in Sources */,
E1C812BC277A8E5D00918266 /* PlaybackSpeed.swift in Sources */,
@ -3359,7 +3427,6 @@
62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */,
62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */,
E113133428BE988200930F75 /* FilterDrawerHStack.swift in Sources */,
E1BDF3192952641300CC0294 /* VisibilityModifier.swift in Sources */,
5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */,
E129428528F080B500796AC6 /* OnReceiveNotificationModifier.swift in Sources */,
E107BB9327880A8F00354E07 /* CollectionItemViewModel.swift in Sources */,
@ -3370,7 +3437,6 @@
E139CC1F28EC83E400688DE2 /* Int.swift in Sources */,
E11895A9289383BC0042947B /* ScrollViewOffsetModifier.swift in Sources */,
E1DA656C28E78C1700592A73 /* MenuPosterHStackModel.swift in Sources */,
E1DC9816296DD0FE00982F06 /* BlurViewModifier.swift in Sources */,
E14A08CB28E6831D004FC984 /* VideoPlayerViewModel.swift in Sources */,
E1DC9847296DEFF500982F06 /* FavoriteIndicator.swift in Sources */,
E1E306CD28EF6E8000537998 /* TimerProxy.swift in Sources */,
@ -3451,9 +3517,11 @@
C4BE07762725EBEA003F4AD1 /* LiveTVProgramsViewModel.swift in Sources */,
E13DD3E927177ED6009D4DAF /* ServerListCoordinator.swift in Sources */,
E1CCF12E28ABF989006CAC9E /* PosterType.swift in Sources */,
E1E7506A2A33E9B400B2C1EE /* RatingsCard.swift in Sources */,
E1D842912933F87500D1041A /* ItemFields.swift in Sources */,
E1BDF2F729524ECD00CC0294 /* PlaybackSpeedActionButton.swift in Sources */,
E113132F28BDB66A00930F75 /* NavBarDrawerModifier.swift in Sources */,
E1E750692A33E9B400B2C1EE /* MediaSourcesCard.swift in Sources */,
E18295E429CAC6F100F91ED0 /* BasicNavigationCoordinator.swift in Sources */,
C45942C527F67DA400C54FE7 /* LiveTVCoordinator.swift in Sources */,
E129429328F2845000796AC6 /* SliderType.swift in Sources */,
@ -3471,11 +3539,13 @@
E1401CA92938140700E8B599 /* DarkAppIcon.swift in Sources */,
E1A1529028FD23D600600579 /* PlaybackSettingsCoordinator.swift in Sources */,
E1AA331F2782639D00F6439C /* OverlayType.swift in Sources */,
E12376AE2A33D680001F5B44 /* AboutViewCard.swift in Sources */,
E1A2C154279A7D5A005EC829 /* UIApplication.swift in Sources */,
E1D8428F2933F2D900D1041A /* MediaSourceInfo.swift in Sources */,
E1BDF2EC2952290200CC0294 /* AspectFillActionButton.swift in Sources */,
E1BDF2F529524E6400CC0294 /* PlayNextItemActionButton.swift in Sources */,
E18E01DD288747230022598C /* iPadOSSeriesItemContentView.swift in Sources */,
E18ACA952A15A3E100BB4F35 /* (null) in Sources */,
C4E5598928124C10003DECA5 /* LiveTVChannelItemElement.swift in Sources */,
E1D5C39B28DF993400CDBEFB /* ThumbSlider.swift in Sources */,
E1DC983D296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */,
@ -3493,6 +3563,7 @@
E17FB55728C1256400311DFE /* CastAndCrewHStack.swift in Sources */,
62E632E3267D3BA60063E547 /* MovieItemViewModel.swift in Sources */,
E113133828BEADBA00930F75 /* LibraryParent.swift in Sources */,
E18ACA8F2A15A2CF00BB4F35 /* (null) in Sources */,
E1401CA72938140300E8B599 /* PrimaryAppIcon.swift in Sources */,
E1937A3E288F0D3D00CB80AA /* UIScreen.swift in Sources */,
C4BE076F2720FEFF003F4AD1 /* PlainNavigationLinkButton.swift in Sources */,
@ -3504,6 +3575,7 @@
E187A60229AB28F0008387E6 /* RotateContentView.swift in Sources */,
091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */,
E1721FAE28FB801C00762992 /* SmallPlaybackButtons.swift in Sources */,
E1E750682A33E9B400B2C1EE /* OverviewCard.swift in Sources */,
5D64683D277B1649009E09AE /* PreferenceUIHostingSwizzling.swift in Sources */,
E1CCF13128AC07EC006CAC9E /* PosterHStack.swift in Sources */,
E13DD3C827164B1E009D4DAF /* UIDevice.swift in Sources */,
@ -3703,7 +3775,7 @@
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Swiftfin tvOS/Info.plist";
INFOPLIST_FILE = "Swiftfin tvOS/Resources/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -3732,7 +3804,7 @@
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Swiftfin tvOS/Info.plist";
INFOPLIST_FILE = "Swiftfin tvOS/Resources/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -3875,7 +3947,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-primary-primary";
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = Swiftfin/Swiftfin.entitlements;
CODE_SIGN_ENTITLEMENTS = Swiftfin/Resources/Swiftfin.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 78;
@ -3885,7 +3957,7 @@
ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = "";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = Swiftfin/Info.plist;
INFOPLIST_FILE = Swiftfin/Resources/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Swiftfin;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@ -3912,7 +3984,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-primary-primary";
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CODE_SIGN_ENTITLEMENTS = Swiftfin/Swiftfin.entitlements;
CODE_SIGN_ENTITLEMENTS = Swiftfin/Resources/Swiftfin.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 78;
@ -3923,7 +3995,7 @@
ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = "";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = Swiftfin/Info.plist;
INFOPLIST_FILE = Swiftfin/Resources/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Swiftfin;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;

View File

@ -68,6 +68,7 @@ extension FilterDrawerHStack {
}
extension FilterDrawerHStack.FilterDrawerButton {
init(title: String, activated: Bool) {
self.init(
systemName: nil,

View File

@ -12,7 +12,8 @@ import SwiftUI
struct FilterDrawerHStack: View {
@ObservedObject
var viewModel: FilterViewModel
private var viewModel: FilterViewModel
private var onSelect: (FilterCoordinator.Parameters) -> Void
var body: some View {
@ -49,22 +50,20 @@ struct FilterDrawerHStack: View {
))
}
// TODO: Localize
FilterDrawerButton(title: "Order", activated: viewModel.currentFilters.sortOrder != [APISortOrder.ascending.filter])
FilterDrawerButton(title: L10n.order, activated: viewModel.currentFilters.sortOrder != [APISortOrder.ascending.filter])
.onSelect {
onSelect(.init(
title: "Order",
title: L10n.order,
viewModel: viewModel,
filter: \.sortOrder,
selectorType: .single
))
}
// TODO: Localize
FilterDrawerButton(title: "Sort", activated: viewModel.currentFilters.sortBy != [SortBy.name.filter])
FilterDrawerButton(title: L10n.sort, activated: viewModel.currentFilters.sortBy != [SortBy.name.filter])
.onSelect {
onSelect(.init(
title: "Sort",
title: L10n.sort,
viewModel: viewModel,
filter: \.sortBy,
selectorType: .single
@ -75,9 +74,12 @@ struct FilterDrawerHStack: View {
}
extension FilterDrawerHStack {
init(viewModel: FilterViewModel) {
self.viewModel = viewModel
self.onSelect = { _ in }
self.init(
viewModel: viewModel,
onSelect: { _ in }
)
}
func onSelect(_ action: @escaping (FilterCoordinator.Parameters) -> Void) -> Self {

View File

@ -61,9 +61,12 @@ struct LibraryItemRow: View {
}
extension LibraryItemRow {
init(item: BaseItemDto) {
self.item = item
self.onSelect = {}
self.init(
item: item,
onSelect: {}
)
}
func onSelect(_ action: @escaping () -> Void) -> Self {

View File

@ -15,16 +15,11 @@ struct PrimaryButton: View {
private var accentColor
private let title: String
private let action: () -> Void
init(title: String, _ action: @escaping () -> Void) {
self.title = title
self.action = action
}
private var onSelect: () -> Void
var body: some View {
Button {
action()
onSelect()
} label: {
ZStack {
Rectangle()
@ -40,3 +35,17 @@ struct PrimaryButton: View {
}
}
}
extension PrimaryButton {
init(title: String) {
self.init(
title: title,
onSelect: {}
)
}
func onSelect(_ action: @escaping () -> Void) -> Self {
copy(modifying: \.onSelect, with: action)
}
}

Some files were not shown because too many files have changed in this diff Show More