Skip to content

Commit

Permalink
[iOS] Media Item Menu - Identify Media Item (#1369)
Browse files Browse the repository at this point in the history
* WIP

* All item types.

* V2: Functionally better. UI still weird

* Rework!

* Organization, new LoadingIcon, remove unnecessary components, and standardize: CancellableLoadingButton

* Organization & Static Method Re-Use.

* wip

* fix tvOS

* wip

* localize

* Update RemoteSearchResultRow.swift

* Update Localizable.strings

* Update RemoteSearchResultRow.swift

---------

Co-authored-by: Ethan Pippin <[email protected]>
  • Loading branch information
JPKribs and LePips authored Dec 31, 2024
1 parent 23beb08 commit 486995b
Show file tree
Hide file tree
Showing 23 changed files with 779 additions and 32 deletions.
7 changes: 7 additions & 0 deletions Shared/Coordinators/ItemEditorCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ final class ItemEditorCoordinator: ObservableObject, NavigationCoordinatable {

// MARK: - Route to Metadata

@Route(.push)
var identifyItem = makeIdentifyItem
@Route(.modal)
var editMetadata = makeEditMetadata

Expand Down Expand Up @@ -60,6 +62,11 @@ final class ItemEditorCoordinator: ObservableObject, NavigationCoordinatable {

// MARK: - Item Metadata

@ViewBuilder
func makeIdentifyItem(item: BaseItemDto) -> some View {
IdentifyItemView(item: item)
}

func makeEditMetadata(item: BaseItemDto) -> NavigationViewCoordinator<BasicNavigationViewCoordinator> {
NavigationViewCoordinator {
EditMetadataView(viewModel: ItemEditorViewModel(item: item))
Expand Down
56 changes: 56 additions & 0 deletions Shared/Extensions/JellyfinAPI/RemoteSearchResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// 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) 2024 Jellyfin & Jellyfin Contributors
//

import Foundation
import JellyfinAPI
import SwiftUI

extension RemoteSearchResult: Displayable {

var displayTitle: String {
name ?? L10n.unknown
}
}

// TODO: fix in SDK, should already be equatable
extension RemoteSearchResult: @retroactive Hashable, @retroactive Identifiable {

public var id: Int {
hashValue
}

public func hash(into hasher: inout Hasher) {
hasher.combine(albumArtist)
hasher.combine(artists)
hasher.combine(imageURL)
hasher.combine(indexNumber)
hasher.combine(indexNumberEnd)
hasher.combine(name)
hasher.combine(overview)
hasher.combine(parentIndexNumber)
hasher.combine(premiereDate)
hasher.combine(productionYear)
hasher.combine(providerIDs)
hasher.combine(searchProviderName)
}

public static func == (lhs: RemoteSearchResult, rhs: RemoteSearchResult) -> Bool {
lhs.albumArtist == rhs.albumArtist &&
lhs.artists == rhs.artists &&
lhs.imageURL == rhs.imageURL &&
lhs.indexNumber == rhs.indexNumber &&
lhs.indexNumberEnd == rhs.indexNumberEnd &&
lhs.name == rhs.name &&
lhs.overview == rhs.overview &&
lhs.parentIndexNumber == rhs.parentIndexNumber &&
lhs.premiereDate == rhs.premiereDate &&
lhs.productionYear == rhs.productionYear &&
lhs.providerIDs == rhs.providerIDs &&
lhs.searchProviderName == rhs.searchProviderName
}
}
4 changes: 4 additions & 0 deletions Shared/Extensions/Optional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import Foundation

extension Optional where Wrapped: Collection {

var isNilOrEmpty: Bool {
self?.isEmpty ?? true
}

mutating func appendedOrInit(_ element: Wrapped.Element) -> [Wrapped.Element] {
if let self {
return self + [element]
Expand Down
8 changes: 8 additions & 0 deletions Shared/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ extension String {
self + String(element)
}

func appending(_ element: @autoclosure () -> String, if condition: Bool) -> String {
if condition {
return self + element()
} else {
return self
}
}

func prepending(_ element: String) -> String {
element + self
}
Expand Down
8 changes: 8 additions & 0 deletions Shared/Extensions/URL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ extension URL: Identifiable {
}
}

extension URL {

init?(string: String?) {
guard let string = string else { return nil }
self.init(string: string)
}
}

extension URL {

static var documents: URL {
Expand Down
5 changes: 4 additions & 1 deletion Shared/Services/Notifications.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,15 @@ extension Notifications.Key {

// MARK: - Media Items

// TODO: come up with a cleaner, more defined way for item update notifications

/// - Payload: The new item with updated metadata.
static var itemMetadataDidChange: Key<BaseItemDto> {
Key("itemMetadataDidChange")
}

static var itemShouldRefresh: Key<(itemID: String, parentID: String?)> {
/// - Payload: The ID of the item that should refresh
static var itemShouldRefreshMetadata: Key<String> {
Key("itemShouldRefresh")
}

Expand Down
12 changes: 12 additions & 0 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ internal enum L10n {
internal static let appIcon = L10n.tr("Localizable", "appIcon", fallback: "App Icon")
/// Application Name
internal static let applicationName = L10n.tr("Localizable", "applicationName", fallback: "Application Name")
/// Applying media information
internal static let applyingMediaInformation = L10n.tr("Localizable", "applyingMediaInformation", fallback: "Applying media information")
/// Arranger
internal static let arranger = L10n.tr("Localizable", "arranger", fallback: "Arranger")
/// Artist
Expand Down Expand Up @@ -602,6 +604,10 @@ internal enum L10n {
internal static let home = L10n.tr("Localizable", "home", fallback: "Home")
/// Hours
internal static let hours = L10n.tr("Localizable", "hours", fallback: "Hours")
/// ID
internal static let id = L10n.tr("Localizable", "id", fallback: "ID")
/// Identify
internal static let identify = L10n.tr("Localizable", "identify", fallback: "Identify")
/// Idle
internal static let idle = L10n.tr("Localizable", "idle", fallback: "Idle")
/// Illustrator
Expand Down Expand Up @@ -906,6 +912,8 @@ internal enum L10n {
internal static let production = L10n.tr("Localizable", "production", fallback: "Production")
/// Production Locations
internal static let productionLocations = L10n.tr("Localizable", "productionLocations", fallback: "Production Locations")
/// Production Year
internal static let productionYear = L10n.tr("Localizable", "productionYear", fallback: "Production Year")
/// Profile Image
internal static let profileImage = L10n.tr("Localizable", "profileImage", fallback: "Profile Image")
/// Profiles
Expand All @@ -914,6 +922,8 @@ internal enum L10n {
internal static let programs = L10n.tr("Localizable", "programs", fallback: "Programs")
/// Progress
internal static let progress = L10n.tr("Localizable", "progress", fallback: "Progress")
/// Provider
internal static let provider = L10n.tr("Localizable", "provider", fallback: "Provider")
/// Public Users
internal static let publicUsers = L10n.tr("Localizable", "publicUsers", fallback: "Public Users")
/// Quick Connect
Expand Down Expand Up @@ -1298,6 +1308,8 @@ internal enum L10n {
internal static let unsavedChangesMessage = L10n.tr("Localizable", "unsavedChangesMessage", fallback: "You have unsaved changes. Are you sure you want to discard them?")
/// URL
internal static let url = L10n.tr("Localizable", "url", fallback: "URL")
/// Use as item
internal static let useAsItem = L10n.tr("Localizable", "useAsItem", fallback: "Use as item")
/// Use as Transcoding Profile
internal static let useAsTranscodingProfile = L10n.tr("Localizable", "useAsTranscodingProfile", fallback: "Use as Transcoding Profile")
/// Use Primary Image
Expand Down
Loading

0 comments on commit 486995b

Please sign in to comment.