Skip to content

Commit

Permalink
Clean up ItemImageDetails types.
Browse files Browse the repository at this point in the history
  • Loading branch information
JPKribs committed Jan 7, 2025
1 parent eb1570f commit d004bcf
Show file tree
Hide file tree
Showing 11 changed files with 323 additions and 213 deletions.
21 changes: 21 additions & 0 deletions Shared/Extensions/RatingType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import JellyfinAPI

extension RatingType: @retroactive Displayable {

var displayTitle: String {
switch self {
case .score:
return L10n.score
case .likes:
return L10n.likes
}
}
}
12 changes: 12 additions & 0 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ internal enum L10n {
internal static let devices = L10n.tr("Localizable", "devices", fallback: "Devices")
/// Digital
internal static let digital = L10n.tr("Localizable", "digital", fallback: "Digital")
/// Dimensions
internal static let dimensions = L10n.tr("Localizable", "dimensions", fallback: "Dimensions")
/// Direct Play
internal static let direct = L10n.tr("Localizable", "direct", fallback: "Direct Play")
/// Plays content in its original format. May cause playback issues on unsupported media types.
Expand Down Expand Up @@ -628,6 +630,10 @@ internal enum L10n {
internal static let illustrator = L10n.tr("Localizable", "illustrator", fallback: "Illustrator")
/// Images
internal static let images = L10n.tr("Localizable", "images", fallback: "Images")
/// Image source
internal static let imageSource = L10n.tr("Localizable", "imageSource", fallback: "Image source")
/// Index
internal static let index = L10n.tr("Localizable", "index", fallback: "Index")
/// Indicators
internal static let indicators = L10n.tr("Localizable", "indicators", fallback: "Indicators")
/// Inker
Expand Down Expand Up @@ -700,6 +706,8 @@ internal enum L10n {
internal static let light = L10n.tr("Localizable", "light", fallback: "Light")
/// Liked Items
internal static let likedItems = L10n.tr("Localizable", "likedItems", fallback: "Liked Items")
/// Likes
internal static let likes = L10n.tr("Localizable", "likes", fallback: "Likes")
/// List
internal static let list = L10n.tr("Localizable", "list", fallback: "List")
/// Live TV
Expand Down Expand Up @@ -1070,6 +1078,8 @@ internal enum L10n {
internal static let saveUserWithoutAuthDescription = L10n.tr("Localizable", "saveUserWithoutAuthDescription", fallback: "Save the user to this device without any local authentication.")
/// Schedule already exists
internal static let scheduleAlreadyExists = L10n.tr("Localizable", "scheduleAlreadyExists", fallback: "Schedule already exists")
/// Score
internal static let score = L10n.tr("Localizable", "score", fallback: "Score")
/// Scrub Current Time
internal static let scrubCurrentTime = L10n.tr("Localizable", "scrubCurrentTime", fallback: "Scrub Current Time")
/// Search
Expand Down Expand Up @@ -1382,6 +1392,8 @@ internal enum L10n {
internal static let videoTranscoding = L10n.tr("Localizable", "videoTranscoding", fallback: "Video transcoding")
/// Some views may need an app restart to update.
internal static let viewsMayRequireRestart = L10n.tr("Localizable", "viewsMayRequireRestart", fallback: "Some views may need an app restart to update.")
/// Votes
internal static let votes = L10n.tr("Localizable", "votes", fallback: "Votes")
/// Weekday
internal static let weekday = L10n.tr("Localizable", "weekday", fallback: "Weekday")
/// Weekend
Expand Down
26 changes: 18 additions & 8 deletions Swiftfin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@
4EA78B102D29B0880093BFCE /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B0E2D29B0820093BFCE /* Request.swift */; };
4EA78B132D29F62E0093BFCE /* ItemImagesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B112D29F6240093BFCE /* ItemImagesCoordinator.swift */; };
4EA78B162D2A0C4A0093BFCE /* ItemImageDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B142D2A0C4A0093BFCE /* ItemImageDetailsView.swift */; };
4EA78B182D2A265E0093BFCE /* RemoteImageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B172D2A26560093BFCE /* RemoteImageInfoView.swift */; };
4EA78B1A2D2A26670093BFCE /* LocalImageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B192D2A26600093BFCE /* LocalImageInfoView.swift */; };
4EA78B202D2B5AA30093BFCE /* ItemPhotoPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B1F2D2B5A9E0093BFCE /* ItemPhotoPickerView.swift */; };
4EA78B232D2B5CFC0093BFCE /* ItemPhotoCropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B222D2B5CEF0093BFCE /* ItemPhotoCropView.swift */; };
4EA78B252D2B5DBD0093BFCE /* ItemPhotoCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EA78B242D2B5DB20093BFCE /* ItemPhotoCoordinator.swift */; };
Expand Down Expand Up @@ -244,6 +242,11 @@
4EECA4E32D2C7D530080A863 /* PhotoPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4E22D2C7D530080A863 /* PhotoPickerView.swift */; };
4EECA4E62D2C7D650080A863 /* PhotoCropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4E52D2C7D650080A863 /* PhotoCropView.swift */; };
4EECA4ED2D2C89D70080A863 /* UserProfileImageCropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4EC2D2C89D20080A863 /* UserProfileImageCropView.swift */; };
4EECA4EF2D2C9B310080A863 /* ItemImageDetailsHeaderSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4EE2D2C9B260080A863 /* ItemImageDetailsHeaderSection.swift */; };
4EECA4F12D2C9E860080A863 /* ItemImageDetailsDetailsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4F02D2C9E7B0080A863 /* ItemImageDetailsDetailsSection.swift */; };
4EECA4F32D2CA5A10080A863 /* ItemImageDetailsDeleteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4F22D2CA59B0080A863 /* ItemImageDetailsDeleteButton.swift */; };
4EECA4F52D2CAA380080A863 /* RatingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4F42D2CAA350080A863 /* RatingType.swift */; };
4EECA4F62D2CAA380080A863 /* RatingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EECA4F42D2CAA350080A863 /* RatingType.swift */; };
4EED874A2CBF824B002354D2 /* DeviceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EED87462CBF824B002354D2 /* DeviceRow.swift */; };
4EED874B2CBF824B002354D2 /* DevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EED87482CBF824B002354D2 /* DevicesView.swift */; };
4EED87512CBF84AD002354D2 /* DevicesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EED874F2CBF84AD002354D2 /* DevicesViewModel.swift */; };
Expand Down Expand Up @@ -1342,8 +1345,6 @@
4EA78B0E2D29B0820093BFCE /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
4EA78B112D29F6240093BFCE /* ItemImagesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemImagesCoordinator.swift; sourceTree = "<group>"; };
4EA78B142D2A0C4A0093BFCE /* ItemImageDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemImageDetailsView.swift; sourceTree = "<group>"; };
4EA78B172D2A26560093BFCE /* RemoteImageInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteImageInfoView.swift; sourceTree = "<group>"; };
4EA78B192D2A26600093BFCE /* LocalImageInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalImageInfoView.swift; sourceTree = "<group>"; };
4EA78B1F2D2B5A9E0093BFCE /* ItemPhotoPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPhotoPickerView.swift; sourceTree = "<group>"; };
4EA78B222D2B5CEF0093BFCE /* ItemPhotoCropView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPhotoCropView.swift; sourceTree = "<group>"; };
4EA78B242D2B5DB20093BFCE /* ItemPhotoCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPhotoCoordinator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1391,6 +1392,10 @@
4EECA4E22D2C7D530080A863 /* PhotoPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerView.swift; sourceTree = "<group>"; };
4EECA4E52D2C7D650080A863 /* PhotoCropView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoCropView.swift; sourceTree = "<group>"; };
4EECA4EC2D2C89D20080A863 /* UserProfileImageCropView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileImageCropView.swift; sourceTree = "<group>"; };
4EECA4EE2D2C9B260080A863 /* ItemImageDetailsHeaderSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemImageDetailsHeaderSection.swift; sourceTree = "<group>"; };
4EECA4F02D2C9E7B0080A863 /* ItemImageDetailsDetailsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemImageDetailsDetailsSection.swift; sourceTree = "<group>"; };
4EECA4F22D2CA59B0080A863 /* ItemImageDetailsDeleteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemImageDetailsDeleteButton.swift; sourceTree = "<group>"; };
4EECA4F42D2CAA350080A863 /* RatingType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingType.swift; sourceTree = "<group>"; };
4EED87462CBF824B002354D2 /* DeviceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRow.swift; sourceTree = "<group>"; };
4EED87482CBF824B002354D2 /* DevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesView.swift; sourceTree = "<group>"; };
4EED874F2CBF84AD002354D2 /* DevicesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicesViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2715,8 +2720,9 @@
4EA78B1B2D2A266A0093BFCE /* Components */ = {
isa = PBXGroup;
children = (
4EA78B192D2A26600093BFCE /* LocalImageInfoView.swift */,
4EA78B172D2A26560093BFCE /* RemoteImageInfoView.swift */,
4EECA4F22D2CA59B0080A863 /* ItemImageDetailsDeleteButton.swift */,
4EECA4F02D2C9E7B0080A863 /* ItemImageDetailsDetailsSection.swift */,
4EECA4EE2D2C9B260080A863 /* ItemImageDetailsHeaderSection.swift */,
);
path = Components;
sourceTree = "<group>";
Expand Down Expand Up @@ -3512,6 +3518,7 @@
E1A505692D0B733F007EE305 /* Optional.swift */,
E1B4E4362CA7795200DC49DE /* OrderedDictionary.swift */,
E1B490432967E26300D3EDCE /* PersistentLogHandler.swift */,
4EECA4F42D2CAA350080A863 /* RatingType.swift */,
E1B5861129E32EEF00E45D6E /* Sequence.swift */,
E145EB442BE0AD4E003BF6F3 /* Set.swift */,
621338922660107500A81A2A /* String.swift */,
Expand Down Expand Up @@ -5544,6 +5551,7 @@
E1E2F8462B757E3400B75998 /* SinceLastDisappearModifier.swift in Sources */,
E1575E80293E77CF001665B1 /* VideoPlayerViewModel.swift in Sources */,
E1C926122887565C002A7A66 /* SeriesItemContentView.swift in Sources */,
4EECA4F62D2CAA380080A863 /* RatingType.swift in Sources */,
E193D53727193F8700900D82 /* MediaCoordinator.swift in Sources */,
E12CC1CB28D1333400678D5D /* CinematicResumeItemView.swift in Sources */,
4E2AC4D42C6C4C1200DD600D /* OrderedSectionSelectorView.swift in Sources */,
Expand Down Expand Up @@ -5840,7 +5848,6 @@
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
625CB5732678C32A00530A6E /* HomeViewModel.swift in Sources */,
62C29EA826D103D500C1D2E7 /* MediaCoordinator.swift in Sources */,
4EA78B182D2A265E0093BFCE /* RemoteImageInfoView.swift in Sources */,
E1F5CF052CB09EA000607465 /* CurrentDate.swift in Sources */,
E13316FE2ADE42B6009BF865 /* OnSizeChangedModifier.swift in Sources */,
62E632DC267D2E130063E547 /* SearchViewModel.swift in Sources */,
Expand Down Expand Up @@ -5996,6 +6003,7 @@
E1CB75752C80EAFA00217C76 /* ArrayBuilder.swift in Sources */,
E1047E2327E5880000CB0D4A /* SystemImageContentView.swift in Sources */,
E1C8CE5B28FE512400DF5D7B /* CGPoint.swift in Sources */,
4EECA4F52D2CAA380080A863 /* RatingType.swift in Sources */,
4E49DECF2CE54D3000352DCD /* MaxBitratePolicy.swift in Sources */,
E18ACA922A15A32F00BB4F35 /* (null) in Sources */,
E1A3E4C92BB74EA3005C59F8 /* LoadingCard.swift in Sources */,
Expand Down Expand Up @@ -6083,6 +6091,7 @@
E1BE1CEA2BDB5AFE008176A9 /* UserGridButton.swift in Sources */,
E1401CB129386C9200E8B599 /* UIColor.swift in Sources */,
E1E2F8452B757E3400B75998 /* SinceLastDisappearModifier.swift in Sources */,
4EECA4F32D2CA5A10080A863 /* ItemImageDetailsDeleteButton.swift in Sources */,
E18E01AB288746AF0022598C /* PillHStack.swift in Sources */,
E19070492C84F2BB0004600E /* ButtonStyle-iOS.swift in Sources */,
E1401CAB2938140A00E8B599 /* LightAppIcon.swift in Sources */,
Expand Down Expand Up @@ -6191,7 +6200,6 @@
4E35CE612CBED3F300DBD886 /* TimeLimitSection.swift in Sources */,
E11B1B6C2718CD68006DA3E8 /* JellyfinAPIError.swift in Sources */,
4E182C9C2C94993200FBEFD5 /* ServerTasksView.swift in Sources */,
4EA78B1A2D2A26670093BFCE /* LocalImageInfoView.swift in Sources */,
E1D4BF812719D22800A11E64 /* AppAppearance.swift in Sources */,
4E6619FD2CEFE2BE00025C99 /* ItemEditorViewModel.swift in Sources */,
E1BDF2EF29522A5900CC0294 /* AudioActionButton.swift in Sources */,
Expand Down Expand Up @@ -6360,6 +6368,7 @@
C46DD8DC2A8DC3420046A504 /* LiveVideoPlayer.swift in Sources */,
E11BDF972B865F550045C54A /* ItemTag.swift in Sources */,
E1D4BF8A2719D3D000A11E64 /* AppSettingsCoordinator.swift in Sources */,
4EECA4F12D2C9E860080A863 /* ItemImageDetailsDetailsSection.swift in Sources */,
E1D37F482B9C648E00343D2B /* MaxHeightText.swift in Sources */,
BD3957752C112A330078CEF8 /* ButtonSection.swift in Sources */,
E1ED7FE32CAA6BAF00ACB6E3 /* ServerLogsViewModel.swift in Sources */,
Expand Down Expand Up @@ -6409,6 +6418,7 @@
E13DD4022717EE79009D4DAF /* SelectUserCoordinator.swift in Sources */,
E11245B128D919CD00D8A977 /* Overlay.swift in Sources */,
E145EB4D2BE1688E003BF6F3 /* SwiftinStore+UserState.swift in Sources */,
4EECA4EF2D2C9B310080A863 /* ItemImageDetailsHeaderSection.swift in Sources */,
53EE24E6265060780068F029 /* SearchView.swift in Sources */,
E164A8152BE58C2F00A54B18 /* V2AnyData.swift in Sources */,
E1DC9841296DEBD800982F06 /* WatchedIndicator.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Defaults
import JellyfinAPI
import SwiftUI

extension ItemImageDetailsView {

struct DeleteButton: View {

// MARK: - Defaults

@Default(.accentColor)
private var accentColor

// MARK: - Delete Action

let onDelete: () -> Void

// MARK: - Header

@ViewBuilder
var body: some View {
ListRowButton(L10n.delete) {
onDelete()
}
.foregroundStyle(
accentColor.overlayColor,
.red
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import JellyfinAPI
import SwiftUI

extension ItemImageDetailsView {

struct DetailsSection: View {

let imageID: Int?
let imageURL: URL?
let imageIndex: Int?
let imageLanguage: String?
let imageWidth: Int?
let imageHeight: Int?
let provider: String?
let rating: Double?
let ratingType: RatingType?
let ratingVotes: Int?

// MARK: - Initializer

init(
imageID: Int? = nil,
imageURL: URL? = nil,
imageIndex: Int? = nil,
imageLanguage: String? = nil,
imageWidth: Int? = nil,
imageHeight: Int? = nil,
provider: String? = nil,
rating: Double? = nil,
ratingType: RatingType? = nil,
ratingVotes: Int? = nil
) {
self.imageID = imageID
self.imageURL = imageURL
self.imageIndex = imageIndex
self.imageLanguage = imageLanguage
self.imageWidth = imageWidth
self.imageHeight = imageHeight
self.provider = provider
self.rating = rating
self.ratingType = ratingType
self.ratingVotes = ratingVotes
}

// MARK: - Body

@ViewBuilder
var body: some View {
Section(L10n.details) {
if let provider {
TextPairView(leading: L10n.provider, trailing: provider)
}

if let imageID {
TextPairView(leading: L10n.id, trailing: imageID.description)
}

if let imageIndex {
TextPairView(leading: L10n.index, trailing: imageIndex.description)
}

if let imageLanguage {
TextPairView(leading: L10n.language, trailing: imageLanguage)
}

if let imageWidth, let imageHeight {
TextPairView(
leading: L10n.dimensions,
trailing: "\(imageWidth) x \(imageHeight)"
)
}
}

if let rating {
Section(L10n.ratings) {
TextPairView(leading: L10n.rating, trailing: rating.formatted(.number.precision(.fractionLength(2))))

if let ratingType {
TextPairView(leading: L10n.rating, trailing: ratingType.displayTitle)
}

if let ratingVotes {
TextPairView(leading: L10n.votes, trailing: ratingVotes.description)
}
}
}

if let imageURL = imageURL {
Section {
Button {
UIApplication.shared.open(imageURL)
} label: {
HStack {
Text(L10n.imageSource)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(.primary)

Image(systemName: "arrow.up.forward")
.font(.body.weight(.regular))
.foregroundColor(.secondary)
}
.foregroundStyle(.primary, .secondary)
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//

import Defaults
import JellyfinAPI
import SwiftUI

extension ItemImageDetailsView {

struct HeaderSection: View {

// MARK: - Image Info

let imageURL: URL?

let imageType: PosterDisplayType

// MARK: - Header

@ViewBuilder
var body: some View {
Section {
ImageView(imageURL)
.placeholder { _ in
Image(systemName: "circle")
}
.failure {
Image(systemName: "circle")
}
.scaledToFill()
.frame(maxWidth: .infinity)
.posterStyle(imageType)
.accessibilityIgnoresInvertColors()
}
.listRowBackground(Color.clear)
.listRowCornerRadius(0)
.listRowInsets(.zero)
}
}
}
Loading

0 comments on commit d004bcf

Please sign in to comment.