diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj
index a522db30..77236bcd 100644
--- a/JellyfinPlayer.xcodeproj/project.pbxproj
+++ b/JellyfinPlayer.xcodeproj/project.pbxproj
@@ -478,7 +478,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 19;
+ CURRENT_PROJECT_VERSION = 20;
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer/Preview Content\"";
DEVELOPMENT_TEAM = 9R8RREG67J;
ENABLE_BITCODE = NO;
@@ -508,7 +508,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 19;
+ CURRENT_PROJECT_VERSION = 20;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer/Preview Content\"";
DEVELOPMENT_TEAM = 9R8RREG67J;
diff --git a/JellyfinPlayer/ContinueWatchingView.swift b/JellyfinPlayer/ContinueWatchingView.swift
index 570dc66f..8bce8cce 100644
--- a/JellyfinPlayer/ContinueWatchingView.swift
+++ b/JellyfinPlayer/ContinueWatchingView.swift
@@ -118,7 +118,7 @@ struct ContinueWatchingView: View {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!)
+ Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!)
.resizable()
.frame(width: 320, height: 180)
.cornerRadius(10)
@@ -148,7 +148,7 @@ struct ContinueWatchingView: View {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!)
+ Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!)
.resizable()
.frame(width: 320, height: 180)
.cornerRadius(10)
diff --git a/JellyfinPlayer/EpisodeItemView.swift b/JellyfinPlayer/EpisodeItemView.swift
index 4b919e4c..dd2f2293 100644
--- a/JellyfinPlayer/EpisodeItemView.swift
+++ b/JellyfinPlayer/EpisodeItemView.swift
@@ -196,6 +196,9 @@ struct EpisodeItemView: View {
.supportedOrientations(.landscape)
.overrideViewPreference(.dark)
.prefersHomeIndicatorAutoHidden(true)
+ .introspectTabBarController { (UITabBarController) in
+ UITabBarController.tabBar.isHidden = true
+ }
} else {
LoadingView(isShowing: $isLoading) {
VStack(alignment:.leading) {
@@ -570,11 +573,12 @@ struct EpisodeItemView: View {
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("\(fullItem.Name) - S\(String(fullItem.ParentIndexNumber ?? 0)):E\(String(fullItem.IndexNumber ?? 0)) - \(fullItem.SeriesName ?? "")")
.introspectTabBarController { (UITabBarController) in
- UITabBarController.tabBar.isHidden = true
+ UITabBarController.tabBar.isHidden = false
}
}.onAppear(perform: loadData)
.supportedOrientations(.allButUpsideDown)
.overrideViewPreference(.unspecified)
+ .preferredColorScheme(.none)
.prefersHomeIndicatorAutoHidden(false)
}
}
diff --git a/JellyfinPlayer/Info.plist b/JellyfinPlayer/Info.plist
index 0044587d..de1bc59e 100644
--- a/JellyfinPlayer/Info.plist
+++ b/JellyfinPlayer/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
$(MARKETING_VERSION)
CFBundleVersion
- 19
+ 20
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/JellyfinPlayer/LatestMediaView.swift b/JellyfinPlayer/LatestMediaView.swift
index b760b601..a2f11bb4 100644
--- a/JellyfinPlayer/LatestMediaView.swift
+++ b/JellyfinPlayer/LatestMediaView.swift
@@ -91,10 +91,10 @@ struct LatestMediaView: View {
VStack(alignment: .leading) {
if(item.Type == "Series") {
Spacer().frame(height:10)
- WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=150&quality=80&tag=\(item.Image)")!)
+ WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!)
+ Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
.resizable()
.frame(width: 100, height: 150)
.cornerRadius(10)
@@ -122,10 +122,10 @@ struct LatestMediaView: View {
).shadow(radius: 6)
} else {
Spacer().frame(height:10)
- WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=150&quality=80&tag=\(item.Image)")!)
+ WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!)
+ Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
.resizable()
.frame(width: 100, height: 150)
.cornerRadius(10)
diff --git a/JellyfinPlayer/LibraryView.swift b/JellyfinPlayer/LibraryView.swift
index 84fb0c5e..43ebc1ad 100644
--- a/JellyfinPlayer/LibraryView.swift
+++ b/JellyfinPlayer/LibraryView.swift
@@ -208,7 +208,7 @@ struct LibraryView: View {
NavigationLink(destination: ItemView(item: item )) {
VStack(alignment: .leading) {
if(item.Type == "Movie") {
- WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=150&quality=80&tag=\(item.Image)"))
+ WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable()
.placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
@@ -218,8 +218,9 @@ struct LibraryView: View {
}
.frame(width:100, height: 150)
.cornerRadius(10)
+ .shadow(radius: 5)
} else {
- WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=150&quality=80&tag=\(item.Image)"))
+ WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable()
.placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
@@ -245,7 +246,7 @@ struct LibraryView: View {
.opacity(0.8)
.cornerRadius(10.0)
.padding(3), alignment: .topTrailing
- )
+ ).shadow(radius: 5)
}
Text(item.Name)
.font(.caption)
diff --git a/JellyfinPlayer/Models/SettingsModel.swift b/JellyfinPlayer/Models/SettingsModel.swift
index 8646f1bd..41155dde 100644
--- a/JellyfinPlayer/Models/SettingsModel.swift
+++ b/JellyfinPlayer/Models/SettingsModel.swift
@@ -12,6 +12,8 @@ struct UserSettings: Decodable {
var RemoteMaxBitrate: Int;
var AutoSelectSubtitles: Bool;
var AutoSelectSubtitlesLangcode: String;
+ var SubtitlePositionOffset: Int;
+ var SubtitleFontName: String;
}
struct Bitrates: Codable, Hashable {
diff --git a/JellyfinPlayer/MovieItemView.swift b/JellyfinPlayer/MovieItemView.swift
index 7a4af16a..27b55bca 100644
--- a/JellyfinPlayer/MovieItemView.swift
+++ b/JellyfinPlayer/MovieItemView.swift
@@ -224,6 +224,7 @@ struct MovieItemView: View {
_progressString.wrappedValue = "\(String(progminutes).leftPad(toWidth: 2, withString: "0"))m"
}
}
+ _isLoading.wrappedValue = false;
} catch {
}
@@ -232,7 +233,6 @@ struct MovieItemView: View {
debugPrint(error)
break
}
- _isLoading.wrappedValue = false;
}
}
@@ -243,6 +243,9 @@ struct MovieItemView: View {
.preferredColorScheme(.dark)
.overrideViewPreference(.dark)
.prefersHomeIndicatorAutoHidden(true)
+ .introspectTabBarController { (UITabBarController) in
+ UITabBarController.tabBar.isHidden = true
+ }
} else {
LoadingView(isShowing: $isLoading) {
VStack(alignment:.leading) {
@@ -382,14 +385,14 @@ struct MovieItemView: View {
WebImage(url: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 4, height: 4))!)
+ Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 16, height: 16))!)
.resizable()
.aspectRatio(contentMode: .fill)
- .frame(width: 70, height: 70)
+ .frame(width: 100, height: 100)
.cornerRadius(10)
}
.aspectRatio(contentMode: .fill)
- .frame(width: 70, height: 70)
+ .frame(width: 100, height: 100)
.cornerRadius(10).shadow(radius: 6)
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1).frame(width: 100).foregroundColor(Color.primary)
if(cast.Role != "") {
@@ -564,7 +567,7 @@ struct MovieItemView: View {
WebImage(url: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
- Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 8, height: 8))!)
+ Image(uiImage: UIImage(blurHash: (cast.ImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : cast.ImageBlurHash), size: CGSize(width: 16, height: 16))!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
@@ -621,6 +624,7 @@ struct MovieItemView: View {
}.onAppear(perform: loadData)
.supportedOrientations(.allButUpsideDown)
.overrideViewPreference(.unspecified)
+ .preferredColorScheme(.none)
.prefersHomeIndicatorAutoHidden(false)
}
}
diff --git a/JellyfinPlayer/NextUpView.swift b/JellyfinPlayer/NextUpView.swift
index f850fda7..f228a223 100644
--- a/JellyfinPlayer/NextUpView.swift
+++ b/JellyfinPlayer/NextUpView.swift
@@ -79,7 +79,7 @@ struct NextUpView: View {
NavigationLink(destination: ItemView(item: item)) {
VStack(alignment: .leading) {
Spacer().frame(height:10)
- WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?maxWidth=150&quality=80&tag=\(item.Image)")!)
+ WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
diff --git a/JellyfinPlayer/Resources/bitrates.json b/JellyfinPlayer/Resources/bitrates.json
index db47b15d..2b5863ce 100644
--- a/JellyfinPlayer/Resources/bitrates.json
+++ b/JellyfinPlayer/Resources/bitrates.json
@@ -7,6 +7,10 @@
"name": "4K - 100 Mbps",
"value": 100000000
},
+ {
+ "name": "4K - 80 Mbps",
+ "value": 80000000
+ },
{
"name": "1080p - 60 Mbps",
"value": 60000000
diff --git a/JellyfinPlayer/VideoPlayerView.swift b/JellyfinPlayer/VideoPlayerView.swift
index 2fbc9b2f..9438afaa 100644
--- a/JellyfinPlayer/VideoPlayerView.swift
+++ b/JellyfinPlayer/VideoPlayerView.swift
@@ -44,7 +44,7 @@ struct VideoPlayerView: View {
var item: DetailItem;
@State private var pbitem: PlaybackItem = PlaybackItem(videoType: VideoType.direct, videoUrl: URL(string: "https://example.com")!, subtitles: []);
@State private var streamLoading = false;
- @State private var vlcplayer: VLCMediaPlayer = VLCMediaPlayer(options: ["--sub-margin=-50"]);
+ @State private var vlcplayer: VLCMediaPlayer = VLCMediaPlayer();
@State private var isPlaying = false;
@State private var subtitles: [Subtitle] = [];
@State private var audioTracks: [Subtitle] = [];
@@ -272,7 +272,7 @@ struct VideoPlayerView: View {
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed", codec: "")
_subtitles.wrappedValue.append(disableSubtitleTrack);
for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] {
- if(stream["Type"].string == "Subtitle" && stream["Codec"] != "subrip") { //ignore ripped subtitles - we don't want to extract subtitles
+ if(stream["Type"].string == "Subtitle") { //ignore ripped subtitles - we don't want to extract subtitles
let deliveryUrl = URL(string: "\(globalData.server?.baseURI ?? "")\(stream["DeliveryUrl"].string ?? "")")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "", codec: stream["Codec"].string ?? "")
_subtitles.wrappedValue.append(subtitle);
@@ -315,7 +315,7 @@ struct VideoPlayerView: View {
let disableSubtitleTrack = Subtitle(name: "Disabled", id: -1, url: URL(string: "https://example.com")!, delivery: "Embed", codec: "")
_subtitles.wrappedValue.append(disableSubtitleTrack);
for (_,stream):(String, JSON) in json["MediaSources"][0]["MediaStreams"] {
- if(stream["Type"].string == "Subtitle" && stream["Codec"] != "subrip") {
+ if(stream["Type"].string == "Subtitle") {
let deliveryUrl = URL(string: "\(globalData.server?.baseURI ?? "")\(stream["DeliveryUrl"].string ?? "")")!
let subtitle = Subtitle(name: stream["DisplayTitle"].string ?? "", id: Int32(stream["Index"].int ?? 0), url: deliveryUrl, delivery: stream["DeliveryMethod"].string ?? "", codec: stream["Codec"].string ?? "")
_subtitles.wrappedValue.append(subtitle);
@@ -490,10 +490,14 @@ struct VideoPlayerView: View {
.onAppear(perform: startStream)
.navigationBarHidden(true)
.overrideViewPreference(.dark)
+ .preferredColorScheme(.dark)
.navigationBarBackButtonHidden(true)
.edgesIgnoringSafeArea(.all)
- .introspectTabBarController { (UITabBarController) in
- UITabBarController.tabBar.isHidden = true
+ .withHostingWindow { window in
+ if let vc = window?.rootViewController {
+ let preferenceHost = vc as! PreferenceUIHostingController
+ preferenceHost._viewPreference = .dark
+ }
}
.statusBar(hidden: true)
.onTapGesture(perform: resetTimer)
diff --git a/JellyfinPlayer/Views/SettingsView.swift b/JellyfinPlayer/Views/SettingsView.swift
index f068cfae..4b520ece 100644
--- a/JellyfinPlayer/Views/SettingsView.swift
+++ b/JellyfinPlayer/Views/SettingsView.swift
@@ -18,19 +18,23 @@ struct SettingsView: View {
@State private var username: String = "";
@State private var inNetworkStreamBitrate: Int = 40000000;
@State private var outOfNetworkStreamBitrate: Int = 40000000;
+ @State private var autoSelectSubtitles: Bool = false;
+ @State private var autoSelectSubtitlesLangcode: String = "none";
func onAppear() {
_username.wrappedValue = globalData.user?.username ?? "";
let defaults = UserDefaults.standard
_inNetworkStreamBitrate.wrappedValue = defaults.integer(forKey: "InNetworkBandwidth");
_outOfNetworkStreamBitrate.wrappedValue = defaults.integer(forKey: "OutOfNetworkBandwidth");
+ _autoSelectSubtitles.wrappedValue = defaults.bool(forKey: "AutoSelectSubtitles");
+ _autoSelectSubtitlesLangcode.wrappedValue = defaults.string(forKey: "AutoSelectSubtitlesLangcode") ?? "";
}
var body: some View {
NavigationView() {
Form() {
Section(header: Text("Playback settings")) {
- Picker("Default local playback bitrate", selection: $inNetworkStreamBitrate) {
+ Picker("Default local quality", selection: $inNetworkStreamBitrate) {
ForEach(self.viewModel.bitrates, id: \.self) { bitrate in
Text(bitrate.name).tag(bitrate.value)
}
@@ -39,7 +43,7 @@ struct SettingsView: View {
defaults.setValue(_inNetworkStreamBitrate.wrappedValue, forKey: "InNetworkBandwidth")
}
- Picker("Default remote playback bitrate", selection: $outOfNetworkStreamBitrate) {
+ Picker("Default remote quality", selection: $outOfNetworkStreamBitrate) {
ForEach(self.viewModel.bitrates, id: \.self) { bitrate in
Text(bitrate.name).tag(bitrate.value)
}
@@ -49,38 +53,53 @@ struct SettingsView: View {
}
}
+ Section(header: Text("Accessibility")) {
+ Toggle("Automatically show subtitles", isOn: $autoSelectSubtitles).onChange(of: autoSelectSubtitles, perform: { _ in
+ let defaults = UserDefaults.standard
+ defaults.setValue(autoSelectSubtitles, forKey: "AutoSelectSubtitles")
+ })
+ Picker("Language preferences", selection: $autoSelectSubtitlesLangcode) {
+
+ }
+ }
+
Section() {
- Button {
- let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Server")
- let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
+ HStack() {
+ Text("Signed in as \(username)").foregroundColor(.primary)
+ Spacer()
+ Button {
+ let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Server")
+ let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
- do {
- try viewContext.execute(deleteRequest)
- } catch _ as NSError {
- // TODO: handle the error
- }
-
- let fetchRequest2: NSFetchRequest = NSFetchRequest(entityName: "SignedInUser")
- let deleteRequest2 = NSBatchDeleteRequest(fetchRequest: fetchRequest2)
+ do {
+ try viewContext.execute(deleteRequest)
+ } catch _ as NSError {
+ // TODO: handle the error
+ }
+
+ let fetchRequest2: NSFetchRequest = NSFetchRequest(entityName: "SignedInUser")
+ let deleteRequest2 = NSBatchDeleteRequest(fetchRequest: fetchRequest2)
- do {
- try viewContext.execute(deleteRequest2)
- } catch _ as NSError {
- // TODO: handle the error
+ do {
+ try viewContext.execute(deleteRequest2)
+ } catch _ as NSError {
+ // TODO: handle the error
+ }
+
+ globalData.server = nil
+ globalData.user = nil
+ globalData.authToken = ""
+ globalData.authHeader = ""
+ jsi.did = true
+ // TODO: This should redirect to the server selection screen
+ exit(-1)
+ } label: {
+ Text("Log out").font(.callout)
}
-
- globalData.server = nil
- globalData.user = nil
- globalData.authToken = ""
- globalData.authHeader = ""
- jsi.did = true
- // TODO: This should redirect to the server selection screen
- exit(-1)
- } label: {
- Text("Log out")
}
}
}
+
.navigationBarTitle("Settings", displayMode: .inline)
.toolbar {
ToolbarItemGroup(placement: .navigationBarLeading) {