iOS: Add preferences
This commit is contained in:
parent
87fcc576c5
commit
fd2463b917
|
@ -7,8 +7,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public protocol NavigationManagerDelegate: class {
|
||||
func loadNonGeminiURL(_ url: URL)
|
||||
}
|
||||
|
||||
public class NavigationManager: NSObject, ObservableObject {
|
||||
|
||||
public weak var delegate: NavigationManagerDelegate?
|
||||
|
||||
@Published public var currentURL: URL
|
||||
@Published public var backStack = [URL]()
|
||||
@Published public var forwardStack = [URL]()
|
||||
|
@ -18,6 +24,11 @@ public class NavigationManager: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
public func changeURL(_ url: URL) {
|
||||
guard url.scheme == "gemini" else {
|
||||
delegate?.loadNonGeminiURL(url)
|
||||
return
|
||||
}
|
||||
|
||||
backStack.append(currentURL)
|
||||
currentURL = cannonicalizeURL(url)
|
||||
forwardStack = []
|
||||
|
|
|
@ -36,7 +36,7 @@ struct ContentView: View {
|
|||
urlFieldContents = new.absoluteString
|
||||
})
|
||||
.sheet(isPresented: $showPreferencesSheet, content: {
|
||||
Text("Test")
|
||||
PreferencesView(presented: $showPreferencesSheet)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Preferences.swift
|
||||
// Gemini-iOS
|
||||
//
|
||||
// Created by Shadowfacts on 9/27/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class Preferences: Codable, ObservableObject {
|
||||
|
||||
static let shared: Preferences = load()
|
||||
|
||||
private static var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
private static var archiveURL = Preferences.documentsDirectory.appendingPathComponent("Preferences").appendingPathExtension("plist")
|
||||
|
||||
static func save() {
|
||||
let encoder = PropertyListEncoder()
|
||||
let data = try? encoder.encode(shared)
|
||||
try? data?.write(to: archiveURL, options: .noFileProtection)
|
||||
}
|
||||
|
||||
static func load() -> Preferences {
|
||||
let decoder = PropertyListDecoder()
|
||||
if let data = try? Data(contentsOf: archiveURL),
|
||||
let prefs = try? decoder.decode(Preferences.self, from: data) {
|
||||
return prefs
|
||||
}
|
||||
return Preferences()
|
||||
}
|
||||
|
||||
private init() {}
|
||||
|
||||
required init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
useInAppSafari = try container.decode(Bool.self, forKey: .useInAppSafari)
|
||||
useReaderMode = try container.decode(Bool.self, forKey: .useReaderMode)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(useInAppSafari, forKey: .useInAppSafari)
|
||||
try container.encode(useReaderMode, forKey: .useReaderMode)
|
||||
}
|
||||
|
||||
@Published var useInAppSafari = false
|
||||
@Published var useReaderMode = false
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case useInAppSafari
|
||||
case useReaderMode
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// PreferencesView.swift
|
||||
// Gemini-iOS
|
||||
//
|
||||
// Created by Shadowfacts on 9/27/20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PreferencesView: View {
|
||||
@ObservedObject var preferences: Preferences = .shared
|
||||
|
||||
@Binding var presented: Bool
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
safariSection
|
||||
}
|
||||
.navigationBarTitle("Preferences")
|
||||
.insetOrGroupedListStyle()
|
||||
.navigationBarItems(trailing: doneButton)
|
||||
}
|
||||
}
|
||||
|
||||
private var doneButton: some View {
|
||||
Button(action: {
|
||||
presented = false
|
||||
}, label: {
|
||||
Text("Done")
|
||||
})
|
||||
}
|
||||
|
||||
private var safariSection: some View {
|
||||
Section(header: Text("Safari")) {
|
||||
Toggle("Use In-App Safari", isOn: $preferences.useInAppSafari)
|
||||
|
||||
Toggle("Use Reader Mode", isOn: $preferences.useReaderMode)
|
||||
.disabled(!preferences.useInAppSafari)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension View {
|
||||
@ViewBuilder
|
||||
func insetOrGroupedListStyle() -> some View {
|
||||
if #available(iOS 14.0, *) {
|
||||
self.listStyle(InsetGroupedListStyle())
|
||||
} else {
|
||||
self.listStyle(GroupedListStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PreferencesView_Previews: PreviewProvider {
|
||||
@State static var presented = true
|
||||
|
||||
static var previews: some View {
|
||||
PreferencesView(presented: $presented)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
import UIKit
|
||||
import SwiftUI
|
||||
import BrowserCore
|
||||
import SafariServices
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
|
@ -20,6 +21,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
navigationManager.delegate = self
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(navigator: navigationManager)
|
||||
|
||||
|
@ -63,3 +66,20 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
|
||||
}
|
||||
|
||||
extension SceneDelegate: NavigationManagerDelegate {
|
||||
func loadNonGeminiURL(_ url: URL) {
|
||||
UIApplication.shared.open(url, options: [.universalLinksOnly: true]) { (success) in
|
||||
if !success {
|
||||
if Preferences.shared.useInAppSafari {
|
||||
let config = SFSafariViewController.Configuration()
|
||||
config.entersReaderIfAvailable = Preferences.shared.useReaderMode
|
||||
let vc = SFSafariViewController(url: url, configuration: config)
|
||||
self.window?.rootViewController?.present(vc, animated: true)
|
||||
} else {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
D664673624BD07F700B0B741 /* RenderingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673524BD07F700B0B741 /* RenderingBlock.swift */; };
|
||||
D664673824BD086F00B0B741 /* RenderingBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673724BD086F00B0B741 /* RenderingBlockView.swift */; };
|
||||
D664673A24BD0B8E00B0B741 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673924BD0B8E00B0B741 /* Fonts.swift */; };
|
||||
D691A64E25217C6F00348C4B /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691A64D25217C6F00348C4B /* Preferences.swift */; };
|
||||
D691A66725217FD800348C4B /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691A66625217FD800348C4B /* PreferencesView.swift */; };
|
||||
D69F00AC24BE9DD300E37622 /* GeminiDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */; };
|
||||
D69F00AE24BEA29100E37622 /* GeminiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AD24BEA29100E37622 /* GeminiResponse.swift */; };
|
||||
D6E1529824BFAAA400FDF9D3 /* BrowserWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */; };
|
||||
|
@ -272,6 +274,8 @@
|
|||
D664673524BD07F700B0B741 /* RenderingBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderingBlock.swift; sourceTree = "<group>"; };
|
||||
D664673724BD086F00B0B741 /* RenderingBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderingBlockView.swift; sourceTree = "<group>"; };
|
||||
D664673924BD0B8E00B0B741 /* Fonts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = "<group>"; };
|
||||
D691A64D25217C6F00348C4B /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
|
||||
D691A66625217FD800348C4B /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = "<group>"; };
|
||||
D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiDataTask.swift; sourceTree = "<group>"; };
|
||||
D69F00AD24BEA29100E37622 /* GeminiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiResponse.swift; sourceTree = "<group>"; };
|
||||
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationManager.swift; sourceTree = "<group>"; };
|
||||
|
@ -523,6 +527,8 @@
|
|||
D6E152A424BFFDF500FDF9D3 /* AppDelegate.swift */,
|
||||
D6E152A624BFFDF500FDF9D3 /* SceneDelegate.swift */,
|
||||
D6E152A824BFFDF500FDF9D3 /* ContentView.swift */,
|
||||
D691A64D25217C6F00348C4B /* Preferences.swift */,
|
||||
D691A66625217FD800348C4B /* PreferencesView.swift */,
|
||||
D6E152AA24BFFDF600FDF9D3 /* Assets.xcassets */,
|
||||
D6E152AF24BFFDF600FDF9D3 /* LaunchScreen.storyboard */,
|
||||
D6E152B224BFFDF600FDF9D3 /* Info.plist */,
|
||||
|
@ -1021,8 +1027,10 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D691A66725217FD800348C4B /* PreferencesView.swift in Sources */,
|
||||
D6E152A524BFFDF500FDF9D3 /* AppDelegate.swift in Sources */,
|
||||
D6E152A724BFFDF500FDF9D3 /* SceneDelegate.swift in Sources */,
|
||||
D691A64E25217C6F00348C4B /* Preferences.swift in Sources */,
|
||||
D6E152A924BFFDF500FDF9D3 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<key>BrowserCore.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
<key>Gemini-iOS.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
@ -27,7 +27,7 @@
|
|||
<key>GeminiProtocol.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>4</integer>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>GeminiRenderer.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
|
Loading…
Reference in New Issue