From d5594625ec6f058237766aa736eaf86e768c45b9 Mon Sep 17 00:00:00 2001 From: Ethan Pippin Date: Fri, 20 Aug 2021 15:34:34 -0600 Subject: [PATCH] Create advanced settings view --- JellyfinPlayer.xcodeproj/project.pbxproj | 12 ++++ JellyfinPlayer/ServerDetailView.swift | 62 ++++++++++++++++++ JellyfinPlayer/SettingsView.swift | 65 +++++++++---------- JellyfinPlayer/VideoUpNextView.swift | 2 +- Shared/Extensions/ColorExtension.swift | 16 +++++ .../JellyfinPlayer.xcdatamodel/contents | 6 +- Shared/Singleton/ServerEnvironment.swift | 2 + Shared/ViewModels/ServerDetailViewModel.swift | 25 +++++++ 8 files changed, 154 insertions(+), 36 deletions(-) create mode 100644 JellyfinPlayer/ServerDetailView.swift create mode 100644 Shared/Extensions/ColorExtension.swift create mode 100644 Shared/ViewModels/ServerDetailViewModel.swift diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj index 1bb21ac6..15b8a920 100644 --- a/JellyfinPlayer.xcodeproj/project.pbxproj +++ b/JellyfinPlayer.xcodeproj/project.pbxproj @@ -200,6 +200,9 @@ E131691726C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; + E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */; }; + E173DA5226D04AAF00CC4EB7 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */; }; + E173DA5426D050F500CC4EB7 /* ServerDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5326D050F500CC4EB7 /* ServerDetailViewModel.swift */; }; E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; }; E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; }; E1FCD08826C35A0D007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; }; @@ -388,6 +391,9 @@ DE5004F745B19E28744A7DE7 /* Pods-JellyfinPlayer tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JellyfinPlayer tvOS.debug.xcconfig"; path = "Target Support Files/Pods-JellyfinPlayer tvOS/Pods-JellyfinPlayer tvOS.debug.xcconfig"; sourceTree = ""; }; E100720626BDABC100CE3E31 /* MediaPlayButtonRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayButtonRowView.swift; sourceTree = ""; }; E131691626C583BC0074BFEE /* LogConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogConstructor.swift; sourceTree = ""; }; + E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailView.swift; sourceTree = ""; }; + E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = ""; }; + E173DA5326D050F500CC4EB7 /* ServerDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailViewModel.swift; sourceTree = ""; }; E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = ""; }; E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E1FCD09526C47118007C8DCF /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = ""; }; @@ -488,6 +494,7 @@ 62E632E2267D3BA60063E547 /* MovieItemViewModel.swift */, 62E632E8267D3FF50063E547 /* SeasonItemViewModel.swift */, 62E632EB267D410B0063E547 /* SeriesItemViewModel.swift */, + E173DA5326D050F500CC4EB7 /* ServerDetailViewModel.swift */, 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */, 625CB5692678B71200530A6E /* SplashViewModel.swift */, 09389CC626819B4500AE350E /* VideoPlayerModel.swift */, @@ -654,6 +661,7 @@ 53987CA326572C1300E7EA70 /* SeasonItemView.swift */, 53987CA526572F0700E7EA70 /* SeriesItemView.swift */, 539B2DA4263BA5B8007FF1A4 /* SettingsView.swift */, + E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */, 535BAEA4264A151C005FA86D /* VideoPlayer.swift */, 0959A5FC2686D29800C7C9A9 /* VideoUpNextView.swift */, 53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */, @@ -717,6 +725,7 @@ isa = PBXGroup; children = ( 53DE4BD1267098F300739748 /* SearchBarView.swift */, + E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */, 53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */, 531AC8BE26750DE20091C7EB /* ImageView.swift */, 5364F454266CA0DC0026ECBA /* APIExtensions.swift */, @@ -1176,6 +1185,7 @@ 536D3D78267BD5C30004248C /* ViewModel.swift in Sources */, 62CB3F4B2685BB77003D0A6F /* DefaultsExtension.swift in Sources */, E1FCD08826C35A0D007C8DCF /* NetworkError.swift in Sources */, + E173DA5426D050F500CC4EB7 /* ServerDetailViewModel.swift in Sources */, 53DE4BD02670961400739748 /* EpisodeItemView.swift in Sources */, 53F8377D265FF67C00F456B3 /* VideoPlayerSettingsView.swift in Sources */, 53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */, @@ -1183,6 +1193,7 @@ 0959A5FD2686D29800C7C9A9 /* VideoUpNextView.swift in Sources */, 62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */, 625CB56F2678C23300530A6E /* HomeView.swift in Sources */, + E173DA5226D04AAF00CC4EB7 /* ColorExtension.swift in Sources */, 53892770263C25230035E14B /* NextUpView.swift in Sources */, 625CB5682678B6FB00530A6E /* SplashView.swift in Sources */, 535BAEA5264A151C005FA86D /* VideoPlayer.swift in Sources */, @@ -1207,6 +1218,7 @@ 531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */, 62E632E0267D30CA0063E547 /* LibraryViewModel.swift in Sources */, 624C21752685CF60007F1390 /* SearchablePickerView.swift in Sources */, + E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */, 62EC352F267666A5000E9F2D /* SessionManager.swift in Sources */, 62E632E3267D3BA60063E547 /* MovieItemViewModel.swift in Sources */, 091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */, diff --git a/JellyfinPlayer/ServerDetailView.swift b/JellyfinPlayer/ServerDetailView.swift new file mode 100644 index 00000000..ca8d2986 --- /dev/null +++ b/JellyfinPlayer/ServerDetailView.swift @@ -0,0 +1,62 @@ +// + /* + * 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 2021 Aiden Vigue & Jellyfin Contributors + */ + +import SwiftUI + +struct ServerDetailView: View { + + @ObservedObject var viewModel = ServerDetailViewModel() + + var body: some View { + Form { + Section(header: Text("")) { + HStack { + Text("Name") + Spacer() + Text(ServerEnvironment.current.server.name ?? "") + .foregroundColor(.secondary) + } + + HStack { + Text("URI") + Spacer() + Text(ServerEnvironment.current.server.baseURI ?? "") + .foregroundColor(.secondary) + } + + HStack { + Text("Version") + Spacer() + Text(ServerEnvironment.current.server.version ?? "") + .foregroundColor(.secondary) + } + + HStack { + Text("Operating System") + Spacer() + Text(ServerEnvironment.current.server.os ?? "") + .foregroundColor(.secondary) + } + } + + Button(action: { + viewModel.refreshServerLibrary() + }, label: { + HStack { + Text("Refresh Library") + .font(.callout) + Spacer() + if viewModel.isLoading { + ProgressView() + } + } + }).disabled(viewModel.isLoading) + } + } +} diff --git a/JellyfinPlayer/SettingsView.swift b/JellyfinPlayer/SettingsView.swift index 5637d055..0aaac110 100644 --- a/JellyfinPlayer/SettingsView.swift +++ b/JellyfinPlayer/SettingsView.swift @@ -23,15 +23,41 @@ struct SettingsView: View { @Default(.appAppearance) var appAppearance @Default(.videoPlayerJumpForward) var jumpForwardLength @Default(.videoPlayerJumpBackward) var jumpBackwardLength - @State private var username: String = "" - - func onAppear() { - username = SessionManager.current.user?.username ?? "" - } var body: some View { NavigationView { Form { + Section(header: Text("")) { + HStack { + Text("User") + Spacer() + Text(SessionManager.current.user.username ?? "") + .foregroundColor(.JellyfinPurple) + } + + NavigationLink( + destination: ServerDetailView(), + label: { + HStack { + Text("Server") + Spacer() + Text(ServerEnvironment.current.server.name ?? "") + .foregroundColor(.JellyfinPurple) + } + }) + + Button { + close = false + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + SessionManager.current.logout() + let nc = NotificationCenter.default + nc.post(name: Notification.Name("didSignOut"), object: nil) + } + } label: { + Text("Sign out") + .font(.callout) + } + } Section(header: Text("Playback settings")) { Picker("Default local quality", selection: $inNetworkStreamBitrate) { ForEach(self.viewModel.bitrates, id: \.self) { bitrate in @@ -85,33 +111,6 @@ struct SettingsView: View { UIApplication.shared.windows.first?.overrideUserInterfaceStyle = appearance.style }) } - - Section(header: Text(ServerEnvironment.current.server.name ?? "")) { - HStack { - Text("Signed in as \(username)").foregroundColor(.primary) - Spacer() - Button { - print("logging out") - close = false - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - let nc = NotificationCenter.default - nc.post(name: Notification.Name("didSignOut"), object: nil) - } - } label: { - Text("Switch user").font(.callout) - } - } - Button { - close = false - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - SessionManager.current.logout() - let nc = NotificationCenter.default - nc.post(name: Notification.Name("didSignOut"), object: nil) - } - } label: { - Text("Sign out").font(.callout) - } - } } .navigationBarTitle("Settings", displayMode: .inline) .toolbar { @@ -123,6 +122,6 @@ struct SettingsView: View { } } } - }.onAppear(perform: onAppear) + } } } diff --git a/JellyfinPlayer/VideoUpNextView.swift b/JellyfinPlayer/VideoUpNextView.swift index 07c5bfae..ab1b31bd 100644 --- a/JellyfinPlayer/VideoUpNextView.swift +++ b/JellyfinPlayer/VideoUpNextView.swift @@ -45,7 +45,7 @@ struct VideoUpNextView: View { .font(.subheadline) } .frame(width: 120, height: 35) - .background(Color(red: 172 / 255, green: 92 / 255, blue: 195 / 255)) + .background(Color.JellyfinPurple) .cornerRadius(10) }.buttonStyle(PlainButtonStyle()) .frame(width: 120, height: 35) diff --git a/Shared/Extensions/ColorExtension.swift b/Shared/Extensions/ColorExtension.swift new file mode 100644 index 00000000..40b65a74 --- /dev/null +++ b/Shared/Extensions/ColorExtension.swift @@ -0,0 +1,16 @@ +// + /* + * 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 2021 Aiden Vigue & Jellyfin Contributors + */ + +import SwiftUI + +extension Color { + + static let JellyfinPurple = Color(red: 172 / 255, green: 92 / 255, blue: 195 / 255) + +} diff --git a/Shared/Resources/Model.xcdatamodeld/JellyfinPlayer.xcdatamodel/contents b/Shared/Resources/Model.xcdatamodeld/JellyfinPlayer.xcdatamodel/contents index cf44cb8f..28542225 100644 --- a/Shared/Resources/Model.xcdatamodeld/JellyfinPlayer.xcdatamodel/contents +++ b/Shared/Resources/Model.xcdatamodeld/JellyfinPlayer.xcdatamodel/contents @@ -1,9 +1,11 @@ - + + + @@ -12,7 +14,7 @@ - + \ No newline at end of file diff --git a/Shared/Singleton/ServerEnvironment.swift b/Shared/Singleton/ServerEnvironment.swift index 58b2beee..326ede82 100644 --- a/Shared/Singleton/ServerEnvironment.swift +++ b/Shared/Singleton/ServerEnvironment.swift @@ -44,6 +44,8 @@ final class ServerEnvironment { server.baseURI = uri server.name = response.serverName server.server_id = response.id + server.version = response.version + server.os = response.operatingSystem return server } .handleEvents(receiveOutput: { [unowned self] response in diff --git a/Shared/ViewModels/ServerDetailViewModel.swift b/Shared/ViewModels/ServerDetailViewModel.swift new file mode 100644 index 00000000..1a8e20af --- /dev/null +++ b/Shared/ViewModels/ServerDetailViewModel.swift @@ -0,0 +1,25 @@ +// + /* + * 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 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Foundation +import JellyfinAPI + +class ServerDetailViewModel: ViewModel { + + func refreshServerLibrary() { + LibraryAPI.refreshLibrary() + .trackActivity(loading) + .sink(receiveCompletion: { completion in + self.handleAPIRequestError(completion: completion) + }, receiveValue: { + LogManager.shared.log.debug("Refreshed server library successfully") + }) + .store(in: &cancellables) + } +}