mirror of
https://github.com/jellyfin/Swiftfin.git
synced 2025-03-04 04:59:42 +00:00
[iOS & tvOS] Fix Version Selection (#1429)
* iOS + tvOS Versioning * hasMultipleVersions Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com> * v1 * Button Witdh to avoid overflow. Fix build issues. * Let instead of Var. * cleanup --------- Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>
This commit is contained in:
parent
c113c341bf
commit
137f0dbf13
@ -27,6 +27,7 @@ class ItemViewModel: ViewModel, Stateful {
|
||||
case replace(BaseItemDto)
|
||||
case toggleIsFavorite
|
||||
case toggleIsPlayed
|
||||
case selectMediaSource(MediaSourceInfo)
|
||||
}
|
||||
|
||||
// MARK: BackgroundState
|
||||
@ -272,6 +273,11 @@ class ItemViewModel: ViewModel, Stateful {
|
||||
}
|
||||
.asAnyCancellable()
|
||||
|
||||
return state
|
||||
case let .selectMediaSource(newSource):
|
||||
|
||||
selectedMediaSource = newSource
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ extension ItemView {
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
}
|
||||
.padding(0)
|
||||
.focused($isFocused)
|
||||
.buttonStyle(.card)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ extension ItemView {
|
||||
var viewModel: ItemViewModel
|
||||
|
||||
@StateObject
|
||||
var deleteViewModel: DeleteItemViewModel
|
||||
private var deleteViewModel: DeleteItemViewModel
|
||||
|
||||
// MARK: - Defaults
|
||||
|
||||
@ -73,7 +73,6 @@ extension ItemView {
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
/// Shrink to minWidth 100 (button) / 50 (menu) and 16 spacing to get 3 buttons + menu
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 24) {
|
||||
|
||||
@ -88,7 +87,7 @@ extension ItemView {
|
||||
}
|
||||
.foregroundStyle(.purple)
|
||||
.environment(\.isSelected, viewModel.item.userData?.isPlayed ?? false)
|
||||
.frame(minWidth: 140, maxWidth: .infinity)
|
||||
.frame(minWidth: 80, maxWidth: .infinity)
|
||||
|
||||
// MARK: - Toggle Favorite
|
||||
|
||||
@ -101,7 +100,14 @@ extension ItemView {
|
||||
}
|
||||
.foregroundStyle(.pink)
|
||||
.environment(\.isSelected, viewModel.item.userData?.isFavorite ?? false)
|
||||
.frame(minWidth: 140, maxWidth: .infinity)
|
||||
.frame(minWidth: 80, maxWidth: .infinity)
|
||||
|
||||
// MARK: - Select Merged Version
|
||||
|
||||
if let mediaSources = viewModel.playButtonItem?.mediaSources, mediaSources.count > 1 {
|
||||
VersionMenu(viewModel: viewModel, mediaSources: mediaSources)
|
||||
.frame(minWidth: 80, maxWidth: .infinity)
|
||||
}
|
||||
|
||||
// MARK: - Additional Menu Options
|
||||
|
||||
@ -118,7 +124,7 @@ extension ItemView {
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: 70)
|
||||
.frame(minWidth: 30, maxWidth: 50)
|
||||
}
|
||||
}
|
||||
.frame(height: 100)
|
||||
|
@ -0,0 +1,59 @@
|
||||
//
|
||||
// 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 ItemView {
|
||||
|
||||
struct VersionMenu: View {
|
||||
|
||||
// MARK: - Focus State
|
||||
|
||||
@FocusState
|
||||
private var isFocused: Bool
|
||||
|
||||
@ObservedObject
|
||||
var viewModel: ItemViewModel
|
||||
|
||||
let mediaSources: [MediaSourceInfo]
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
Menu {
|
||||
ForEach(mediaSources, id: \.hashValue) { mediaSource in
|
||||
Button {
|
||||
viewModel.send(.selectMediaSource(mediaSource))
|
||||
} label: {
|
||||
if let selectedMediaSource = viewModel.selectedMediaSource, selectedMediaSource == mediaSource {
|
||||
Label(selectedMediaSource.displayTitle, systemImage: "checkmark")
|
||||
} else {
|
||||
Text(mediaSource.displayTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.fill(isFocused ? Color.white : Color.white.opacity(0.5))
|
||||
|
||||
Label(L10n.version, systemImage: "list.dash")
|
||||
.font(.title3)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundStyle(.black)
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
}
|
||||
.focused($isFocused)
|
||||
.scaleEffect(isFocused ? 1.20 : 1.0)
|
||||
.animation(.easeInOut(duration: 0.15), value: isFocused)
|
||||
.menuStyle(.borderlessButton)
|
||||
}
|
||||
}
|
||||
}
|
@ -225,6 +225,7 @@
|
||||
4ECF5D8B2D0A57EF00F066B1 /* DynamicDayOfWeek.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ECF5D892D0A57EF00F066B1 /* DynamicDayOfWeek.swift */; };
|
||||
4ED25CA12D07E3590010333C /* EditAccessScheduleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED25CA02D07E3520010333C /* EditAccessScheduleView.swift */; };
|
||||
4ED25CA42D07E4990010333C /* EditAccessScheduleRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED25CA22D07E4990010333C /* EditAccessScheduleRow.swift */; };
|
||||
4EDDB49C2D596E1200DA16E8 /* VersionMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EDDB49B2D596E0700DA16E8 /* VersionMenu.swift */; };
|
||||
4EE07CBB2D08B19700B0B636 /* ErrorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE07CBA2D08B19100B0B636 /* ErrorMessage.swift */; };
|
||||
4EE07CBC2D08B19700B0B636 /* ErrorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE07CBA2D08B19100B0B636 /* ErrorMessage.swift */; };
|
||||
4EE141692C8BABDF0045B661 /* ActiveSessionProgressSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE141682C8BABDF0045B661 /* ActiveSessionProgressSection.swift */; };
|
||||
@ -1441,6 +1442,7 @@
|
||||
4ED25CA02D07E3520010333C /* EditAccessScheduleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAccessScheduleView.swift; sourceTree = "<group>"; };
|
||||
4ED25CA22D07E4990010333C /* EditAccessScheduleRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAccessScheduleRow.swift; sourceTree = "<group>"; };
|
||||
4EDBDCD02CBDD6510033D347 /* SessionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionInfo.swift; sourceTree = "<group>"; };
|
||||
4EDDB49B2D596E0700DA16E8 /* VersionMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionMenu.swift; sourceTree = "<group>"; };
|
||||
4EE07CBA2D08B19100B0B636 /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = "<group>"; };
|
||||
4EE141682C8BABDF0045B661 /* ActiveSessionProgressSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveSessionProgressSection.swift; sourceTree = "<group>"; };
|
||||
4EE766F42D131FB7009658F0 /* IdentifyItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifyItemView.swift; sourceTree = "<group>"; };
|
||||
@ -2490,6 +2492,7 @@
|
||||
E1C926032887565C002A7A66 /* ActionButtonHStack.swift */,
|
||||
4EF659E22CDD270B00E0BE5D /* ActionMenu.swift */,
|
||||
4E97D1842D064B43004B89AD /* RefreshMetadataButton.swift */,
|
||||
4EDDB49B2D596E0700DA16E8 /* VersionMenu.swift */,
|
||||
);
|
||||
path = ActionButtons;
|
||||
sourceTree = "<group>";
|
||||
@ -5971,6 +5974,7 @@
|
||||
E1CAF6602BA345830087D991 /* MediaViewModel.swift in Sources */,
|
||||
E19D41A82BEEDC5F0082B8B2 /* UserLocalSecurityViewModel.swift in Sources */,
|
||||
E111D8FA28D0400900400001 /* PagingLibraryView.swift in Sources */,
|
||||
4EDDB49C2D596E1200DA16E8 /* VersionMenu.swift in Sources */,
|
||||
E1EA9F6B28F8A79E00BEC442 /* VideoPlayerManager.swift in Sources */,
|
||||
BD0BA22F2AD6508C00306A8D /* DownloadVideoPlayerManager.swift in Sources */,
|
||||
4E0A8FFC2CAF74D20014B047 /* TaskCompletionStatus.swift in Sources */,
|
||||
|
@ -80,7 +80,7 @@ extension ItemView {
|
||||
Menu {
|
||||
ForEach(mediaSources, id: \.hashValue) { mediaSource in
|
||||
Button {
|
||||
// viewModel.selectedMediaSource = mediaSource
|
||||
viewModel.send(.selectMediaSource(mediaSource))
|
||||
} label: {
|
||||
if let selectedMediaSource = viewModel.selectedMediaSource, selectedMediaSource == mediaSource {
|
||||
Label(selectedMediaSource.displayTitle, systemImage: "checkmark")
|
||||
|
Loading…
x
Reference in New Issue
Block a user