Added setting to select in app or default browser to open external links
This commit is contained in:
parent
26990c59fa
commit
f78de1f740
@ -14,6 +14,8 @@ struct Settings {
|
||||
var theme: Theme? = nil
|
||||
var cardLayoutStyle: CardLayoutStyle? = nil
|
||||
|
||||
var urlOpener: UrlOpener? = nil
|
||||
|
||||
var isLoggedIn: Bool {
|
||||
token != nil && !token!.isEmpty
|
||||
}
|
||||
@ -91,6 +93,10 @@ class SettingsRepository: PSettingsRepository {
|
||||
existingSettings.theme = theme.rawValue
|
||||
}
|
||||
|
||||
if let urlOpener = settings.urlOpener {
|
||||
existingSettings.urlOpener = urlOpener.rawValue
|
||||
}
|
||||
|
||||
if let cardLayoutStyle = settings.cardLayoutStyle {
|
||||
existingSettings.cardLayoutStyle = cardLayoutStyle.rawValue
|
||||
}
|
||||
@ -132,7 +138,8 @@ class SettingsRepository: PSettingsRepository {
|
||||
fontSize: FontSize(rawValue: settingEntity?.fontSize ?? FontSize.medium.rawValue),
|
||||
enableTTS: settingEntity?.enableTTS,
|
||||
theme: Theme(rawValue: settingEntity?.theme ?? Theme.system.rawValue),
|
||||
cardLayoutStyle: CardLayoutStyle(rawValue: settingEntity?.cardLayoutStyle ?? CardLayoutStyle.magazine.rawValue)
|
||||
cardLayoutStyle: CardLayoutStyle(rawValue: settingEntity?.cardLayoutStyle ?? CardLayoutStyle.magazine.rawValue),
|
||||
urlOpener: UrlOpener(rawValue: settingEntity?.urlOpener ?? UrlOpener.inAppBrowser.rawValue)
|
||||
)
|
||||
continuation.resume(returning: settings)
|
||||
} catch {
|
||||
|
||||
13
readeck/Domain/Model/UrlOpener.swift
Normal file
13
readeck/Domain/Model/UrlOpener.swift
Normal file
@ -0,0 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
enum UrlOpener: String, CaseIterable {
|
||||
case inAppBrowser = "inAppBrowser"
|
||||
case defaultBrowser = "defaultBrowser"
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .inAppBrowser: return "In App Browser"
|
||||
case .defaultBrowser: return "Default Browser"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ protocol PSaveSettingsUseCase {
|
||||
func execute(selectedFontFamily: FontFamily, selectedFontSize: FontSize) async throws
|
||||
func execute(enableTTS: Bool) async throws
|
||||
func execute(theme: Theme) async throws
|
||||
func execute(urlOpener: UrlOpener) async throws
|
||||
}
|
||||
|
||||
class SaveSettingsUseCase: PSaveSettingsUseCase {
|
||||
@ -33,4 +34,10 @@ class SaveSettingsUseCase: PSaveSettingsUseCase {
|
||||
.init(theme: theme)
|
||||
)
|
||||
}
|
||||
|
||||
func execute(urlOpener: UrlOpener) async throws {
|
||||
try await settingsRepository.saveSettings(
|
||||
.init(urlOpener: urlOpener)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ struct BookmarkDetailView: View {
|
||||
.padding()
|
||||
} else {
|
||||
Button(action: {
|
||||
SafariUtil.openInSafari(url: viewModel.bookmarkDetail.url)
|
||||
URLUtil.open(url: viewModel.bookmarkDetail.url, urlOpener: appSettings.urlOpener)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "safari")
|
||||
@ -263,7 +263,7 @@ struct BookmarkDetailView: View {
|
||||
.padding()
|
||||
} else {
|
||||
Button(action: {
|
||||
SafariUtil.openInSafari(url: viewModel.bookmarkDetail.url)
|
||||
URLUtil.open(url: viewModel.bookmarkDetail.url, urlOpener: appSettings.urlOpener)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "safari")
|
||||
@ -319,7 +319,7 @@ struct BookmarkDetailView: View {
|
||||
|
||||
metaRow(icon: "safari") {
|
||||
Button(action: {
|
||||
SafariUtil.openInSafari(url: viewModel.bookmarkDetail.url)
|
||||
URLUtil.open(url: viewModel.bookmarkDetail.url, urlOpener: appSettings.urlOpener)
|
||||
}) {
|
||||
Text((URLUtil.extractDomain(from: viewModel.bookmarkDetail.url) ?? "Open original page") + " open")
|
||||
.font(.subheadline)
|
||||
|
||||
@ -14,6 +14,7 @@ extension View {
|
||||
|
||||
struct BookmarkCardView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@EnvironmentObject var appSettings: AppSettings
|
||||
|
||||
let bookmark: Bookmark
|
||||
let currentState: BookmarkState
|
||||
@ -255,7 +256,7 @@ struct BookmarkCardView: View {
|
||||
HStack {
|
||||
Label((URLUtil.extractDomain(from: bookmark.url) ?? "Original Site") + " open", systemImage: "safari")
|
||||
.onTapGesture {
|
||||
SafariUtil.openInSafari(url: bookmark.url)
|
||||
URLUtil.open(url: bookmark.url, urlOpener: appSettings.urlOpener)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -336,7 +337,7 @@ struct BookmarkCardView: View {
|
||||
HStack {
|
||||
Label((URLUtil.extractDomain(from: bookmark.url) ?? "Original Site") + " open", systemImage: "safari")
|
||||
.onTapGesture {
|
||||
SafariUtil.openInSafari(url: bookmark.url)
|
||||
URLUtil.open(url: bookmark.url, urlOpener: appSettings.urlOpener)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -434,4 +435,4 @@ struct IconBadge: View {
|
||||
.foregroundColor(.white)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,6 +150,7 @@ class MockSaveSettingsUseCase: PSaveSettingsUseCase {
|
||||
func execute(selectedFontFamily: FontFamily, selectedFontSize: FontSize) async throws {}
|
||||
func execute(enableTTS: Bool) async throws {}
|
||||
func execute(theme: Theme) async throws {}
|
||||
func execute(urlOpener: UrlOpener) async throws {}
|
||||
}
|
||||
|
||||
class MockGetBookmarkUseCase: PGetBookmarkUseCase {
|
||||
|
||||
@ -26,6 +26,10 @@ class AppSettings: ObservableObject {
|
||||
var theme: Theme {
|
||||
settings?.theme ?? .system
|
||||
}
|
||||
|
||||
var urlOpener: UrlOpener {
|
||||
settings?.urlOpener ?? .inAppBrowser
|
||||
}
|
||||
|
||||
init(settings: Settings? = nil) {
|
||||
self.settings = settings
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsGeneralView: View {
|
||||
@State private var viewModel: SettingsGeneralViewModel
|
||||
@State private var viewModel: SettingsGeneralViewModel
|
||||
|
||||
init(viewModel: SettingsGeneralViewModel = SettingsGeneralViewModel()) {
|
||||
self.viewModel = viewModel
|
||||
@ -33,6 +33,23 @@ struct SettingsGeneralView: View {
|
||||
.font(.footnote)
|
||||
}
|
||||
|
||||
// Reading Settings
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("Open external links in")
|
||||
.font(.headline)
|
||||
Picker("urlOpener", selection: $viewModel.urlOpener) {
|
||||
ForEach(UrlOpener.allCases, id: \.self) { urlOpener in
|
||||
Text(urlOpener.displayName).tag(urlOpener)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
.onChange(of: viewModel.urlOpener) {
|
||||
Task {
|
||||
await viewModel.saveGeneralSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// Sync Settings
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
@ -55,8 +72,6 @@ struct SettingsGeneralView: View {
|
||||
.font(.headline)
|
||||
Toggle("Safari Reader Mode", isOn: $viewModel.enableReaderMode)
|
||||
.toggleStyle(SwitchToggleStyle())
|
||||
Toggle("Open external links in in-app Safari", isOn: $viewModel.openExternalLinksInApp)
|
||||
.toggleStyle(SwitchToggleStyle())
|
||||
Toggle("Automatically mark articles as read", isOn: $viewModel.autoMarkAsRead)
|
||||
.toggleStyle(SwitchToggleStyle())
|
||||
}
|
||||
|
||||
@ -15,8 +15,8 @@ class SettingsGeneralViewModel {
|
||||
// MARK: - Reading Settings
|
||||
var enableReaderMode: Bool = false
|
||||
var enableTTS: Bool = false
|
||||
var openExternalLinksInApp: Bool = true
|
||||
var autoMarkAsRead: Bool = false
|
||||
var urlOpener: UrlOpener = .inAppBrowser
|
||||
|
||||
// MARK: - Messages
|
||||
|
||||
@ -36,6 +36,7 @@ class SettingsGeneralViewModel {
|
||||
if let settings = try await loadSettingsUseCase.execute() {
|
||||
enableTTS = settings.enableTTS ?? false
|
||||
selectedTheme = settings.theme ?? .system
|
||||
urlOpener = settings.urlOpener ?? .inAppBrowser
|
||||
autoSyncEnabled = false
|
||||
}
|
||||
} catch {
|
||||
@ -48,6 +49,7 @@ class SettingsGeneralViewModel {
|
||||
do {
|
||||
try await saveSettingsUseCase.execute(enableTTS: enableTTS)
|
||||
try await saveSettingsUseCase.execute(theme: selectedTheme)
|
||||
try await saveSettingsUseCase.execute(urlOpener: urlOpener)
|
||||
|
||||
successMessage = "Settings saved"
|
||||
|
||||
|
||||
@ -1,8 +1,25 @@
|
||||
import UIKit
|
||||
import SafariServices
|
||||
|
||||
class SafariUtil {
|
||||
static func openInSafari(url: String) {
|
||||
struct URLUtil {
|
||||
|
||||
static func open(url: String, urlOpener: UrlOpener = .inAppBrowser) {
|
||||
// Could be extended to open in other browsers like Firefox, Brave etc. if somebody has a multi browser setup
|
||||
// and wants readeck links to always opened in a specific browser
|
||||
switch urlOpener {
|
||||
case .defaultBrowser:
|
||||
openUrlInDefaultBrowser(url: url)
|
||||
default:
|
||||
openUrlInInAppBrowser(url: url)
|
||||
}
|
||||
}
|
||||
|
||||
static func openUrlInDefaultBrowser(url: String) {
|
||||
guard let url = URL(string: url) else { return }
|
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||
}
|
||||
|
||||
static func openUrlInInAppBrowser(url: String) {
|
||||
guard let url = URL(string: url) else { return }
|
||||
|
||||
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||
@ -22,9 +39,7 @@ class SafariUtil {
|
||||
presentingViewController.present(safariViewController, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct URLUtil {
|
||||
|
||||
static func extractDomain(from urlString: String) -> String? {
|
||||
guard let url = URL(string: urlString), let host = url.host else { return nil }
|
||||
return host.replacingOccurrences(of: "www.", with: "")
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23788.4" systemVersion="24G84" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="24299" systemVersion="25A354" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="ArticleURLEntity" representedClassName="ArticleURLEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="tags" optional="YES" attributeType="String"/>
|
||||
@ -57,6 +57,7 @@
|
||||
<attribute name="fontSize" optional="YES" attributeType="String"/>
|
||||
<attribute name="theme" optional="YES" attributeType="String"/>
|
||||
<attribute name="token" optional="YES" attributeType="String"/>
|
||||
<attribute name="urlOpener" optional="YES" attributeType="String"/>
|
||||
</entity>
|
||||
<entity name="TagEntity" representedClassName="TagEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user