Integrate Settings with WebView font customization
- Connect SettingsView font selection to WebView CSS rendering - Add dynamic font size and family mapping in WebView - Implement CSS custom properties for responsive font scaling - Add font family fallback stacks for cross-platform compatibility - Update WebView to use Settings object for typography configuration
This commit is contained in:
parent
2bc93abe24
commit
789d581705
@ -22,10 +22,6 @@ class AuthRepository: PAuthRepository {
|
|||||||
func getCurrentSettings() async throws -> Settings? {
|
func getCurrentSettings() async throws -> Settings? {
|
||||||
return try await settingsRepository.loadSettings()
|
return try await settingsRepository.loadSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveSettings(_ settings: Settings) async throws {
|
|
||||||
try await settingsRepository.saveSettings(settings)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
|
|||||||
@ -2,10 +2,13 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
let endpoint: String
|
var endpoint: String? = nil
|
||||||
let username: String
|
var username: String? = nil
|
||||||
let password: String
|
var password: String? = nil
|
||||||
var token: String?
|
var token: String? = nil
|
||||||
|
|
||||||
|
var fontFamily: FontFamily? = nil
|
||||||
|
var fontSize: FontSize? = nil
|
||||||
|
|
||||||
var isLoggedIn: Bool {
|
var isLoggedIn: Bool {
|
||||||
token != nil && !token!.isEmpty
|
token != nil && !token!.isEmpty
|
||||||
@ -34,19 +37,35 @@ class SettingsRepository: PSettingsRepository {
|
|||||||
do {
|
do {
|
||||||
// Vorhandene Einstellungen löschen
|
// Vorhandene Einstellungen löschen
|
||||||
let fetchRequest: NSFetchRequest<SettingEntity> = SettingEntity.fetchRequest()
|
let fetchRequest: NSFetchRequest<SettingEntity> = SettingEntity.fetchRequest()
|
||||||
let existingSettings = try context.fetch(fetchRequest)
|
if let existingSettings = try context.fetch(fetchRequest).first {
|
||||||
for setting in existingSettings {
|
|
||||||
context.delete(setting)
|
if let endpoint = settings.endpoint, !endpoint.isEmpty {
|
||||||
|
existingSettings.endpoint = endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
if let username = settings.username, !username.isEmpty {
|
||||||
|
existingSettings.username = username
|
||||||
|
}
|
||||||
|
|
||||||
|
if let password = settings.password, !password.isEmpty {
|
||||||
|
existingSettings.password = password
|
||||||
|
}
|
||||||
|
|
||||||
|
if let token = settings.token, !token.isEmpty {
|
||||||
|
existingSettings.token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
if let fontFamily = settings.fontFamily {
|
||||||
|
existingSettings.fontFamily = fontFamily.rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
if let fontSize = settings.fontSize {
|
||||||
|
existingSettings.fontSize = fontSize.rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
try context.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Neue Einstellungen erstellen
|
|
||||||
let settingEntity = SettingEntity(context: context)
|
|
||||||
settingEntity.endpoint = settings.endpoint
|
|
||||||
settingEntity.username = settings.username
|
|
||||||
settingEntity.password = settings.password
|
|
||||||
settingEntity.token = settings.token
|
|
||||||
|
|
||||||
try context.save()
|
|
||||||
continuation.resume()
|
continuation.resume()
|
||||||
} catch {
|
} catch {
|
||||||
continuation.resume(throwing: error)
|
continuation.resume(throwing: error)
|
||||||
@ -71,7 +90,9 @@ class SettingsRepository: PSettingsRepository {
|
|||||||
endpoint: settingEntity.endpoint ?? "",
|
endpoint: settingEntity.endpoint ?? "",
|
||||||
username: settingEntity.username ?? "",
|
username: settingEntity.username ?? "",
|
||||||
password: settingEntity.password ?? "",
|
password: settingEntity.password ?? "",
|
||||||
token: settingEntity.token
|
token: settingEntity.token,
|
||||||
|
fontFamily: FontFamily(rawValue: settingEntity.fontFamily ?? FontFamily.system.rawValue),
|
||||||
|
fontSize: FontSize(rawValue: settingEntity.fontSize ?? FontSize.medium.rawValue)
|
||||||
)
|
)
|
||||||
continuation.resume(returning: settings)
|
continuation.resume(returning: settings)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -10,5 +10,4 @@ protocol PAuthRepository {
|
|||||||
func login(username: String, password: String) async throws -> User
|
func login(username: String, password: String) async throws -> User
|
||||||
func logout() async throws
|
func logout() async throws
|
||||||
func getCurrentSettings() async throws -> Settings?
|
func getCurrentSettings() async throws -> Settings?
|
||||||
func saveSettings(_ settings: Settings) async throws
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,4 +10,4 @@ class GetBookmarkArticleUseCase {
|
|||||||
func execute(id: String) async throws -> String {
|
func execute(id: String) async throws -> String {
|
||||||
return try await repository.fetchBookmarkArticle(id: id)
|
return try await repository.fetchBookmarkArticle(id: id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,36 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class SaveSettingsUseCase {
|
class SaveSettingsUseCase {
|
||||||
private let authRepository: PAuthRepository
|
private let settingsRepository: PSettingsRepository
|
||||||
|
|
||||||
init(authRepository: PAuthRepository) {
|
init(settingsRepository: PSettingsRepository) {
|
||||||
self.authRepository = authRepository
|
self.settingsRepository = settingsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute(endpoint: String, username: String, password: String) async throws {
|
func execute(endpoint: String, username: String, password: String) async throws {
|
||||||
let settings = Settings(
|
try await settingsRepository.saveSettings(
|
||||||
endpoint: endpoint,
|
.init(
|
||||||
username: username,
|
endpoint: endpoint,
|
||||||
password: password,
|
username: username,
|
||||||
token: nil
|
password: password
|
||||||
|
)
|
||||||
)
|
)
|
||||||
try await authRepository.saveSettings(settings)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
func execute(token: String) async throws {
|
||||||
|
try await settingsRepository.saveSettings(
|
||||||
|
.init(
|
||||||
|
token: token
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func execute(selectedFontFamily: FontFamily, selectedFontSize: FontSize) async throws {
|
||||||
|
try await settingsRepository.saveSettings(
|
||||||
|
.init(
|
||||||
|
fontFamily: selectedFontFamily,
|
||||||
|
fontSize: selectedFontSize
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -36,8 +36,8 @@ struct BookmarkDetailView: View {
|
|||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
// Artikel-Inhalt mit WebView
|
// Artikel-Inhalt mit WebView
|
||||||
if !viewModel.articleContent.isEmpty {
|
if let settings = viewModel.settings, !viewModel.articleContent.isEmpty {
|
||||||
WebView(htmlContent: viewModel.articleContent) { height in
|
WebView(htmlContent: viewModel.articleContent, settings: settings) { height in
|
||||||
webViewHeight = height
|
webViewHeight = height
|
||||||
}
|
}
|
||||||
.frame(height: webViewHeight)
|
.frame(height: webViewHeight)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import Foundation
|
|||||||
class BookmarkDetailViewModel {
|
class BookmarkDetailViewModel {
|
||||||
private let getBookmarkUseCase: GetBookmarkUseCase
|
private let getBookmarkUseCase: GetBookmarkUseCase
|
||||||
private let getBookmarkArticleUseCase: GetBookmarkArticleUseCase
|
private let getBookmarkArticleUseCase: GetBookmarkArticleUseCase
|
||||||
|
private let loadSettingsUseCase: LoadSettingsUseCase
|
||||||
|
|
||||||
var bookmarkDetail: BookmarkDetail = BookmarkDetail.empty
|
var bookmarkDetail: BookmarkDetail = BookmarkDetail.empty
|
||||||
var articleContent: String = ""
|
var articleContent: String = ""
|
||||||
@ -12,11 +13,13 @@ class BookmarkDetailViewModel {
|
|||||||
var isLoading = false
|
var isLoading = false
|
||||||
var isLoadingArticle = false
|
var isLoadingArticle = false
|
||||||
var errorMessage: String?
|
var errorMessage: String?
|
||||||
|
var settings: Settings?
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
let factory = DefaultUseCaseFactory.shared
|
let factory = DefaultUseCaseFactory.shared
|
||||||
self.getBookmarkUseCase = factory.makeGetBookmarkUseCase()
|
self.getBookmarkUseCase = factory.makeGetBookmarkUseCase()
|
||||||
self.getBookmarkArticleUseCase = factory.makeGetBookmarkArticleUseCase()
|
self.getBookmarkArticleUseCase = factory.makeGetBookmarkArticleUseCase()
|
||||||
|
self.loadSettingsUseCase = factory.makeLoadSettingsUseCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
@ -25,6 +28,7 @@ class BookmarkDetailViewModel {
|
|||||||
errorMessage = nil
|
errorMessage = nil
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
settings = try await loadSettingsUseCase.execute()
|
||||||
bookmarkDetail = try await getBookmarkUseCase.execute(id: id)
|
bookmarkDetail = try await getBookmarkUseCase.execute(id: id)
|
||||||
|
|
||||||
// Auch das vollständige Bookmark für readProgress laden
|
// Auch das vollständige Bookmark für readProgress laden
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import WebKit
|
|||||||
|
|
||||||
struct WebView: UIViewRepresentable {
|
struct WebView: UIViewRepresentable {
|
||||||
let htmlContent: String
|
let htmlContent: String
|
||||||
|
let settings: Settings
|
||||||
let onHeightChange: (CGFloat) -> Void
|
let onHeightChange: (CGFloat) -> Void
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
|
||||||
@ -26,6 +27,10 @@ struct WebView: UIViewRepresentable {
|
|||||||
|
|
||||||
let isDarkMode = colorScheme == .dark
|
let isDarkMode = colorScheme == .dark
|
||||||
|
|
||||||
|
// Font Settings aus Settings-Objekt
|
||||||
|
let fontSize = getFontSize(from: settings.fontSize ?? .extraLarge)
|
||||||
|
let fontFamily = getFontFamily(from: settings.fontFamily ?? .serif)
|
||||||
|
|
||||||
let styledHTML = """
|
let styledHTML = """
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@ -42,16 +47,20 @@ struct WebView: UIViewRepresentable {
|
|||||||
--code-background: \(isDarkMode ? "#1C1C1E" : "#f5f5f5");
|
--code-background: \(isDarkMode ? "#1C1C1E" : "#f5f5f5");
|
||||||
--code-text: \(isDarkMode ? "#ffffff" : "#000000");
|
--code-text: \(isDarkMode ? "#ffffff" : "#000000");
|
||||||
--separator-color: \(isDarkMode ? "#38383A" : "#e0e0e0");
|
--separator-color: \(isDarkMode ? "#38383A" : "#e0e0e0");
|
||||||
|
|
||||||
|
/* Font Settings from Settings */
|
||||||
|
--base-font-size: \(fontSize)px;
|
||||||
|
--font-family: \(fontFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: var(--font-family);
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-size: 16px;
|
font-size: var(--base-font-size);
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,13 +69,19 @@ struct WebView: UIViewRepresentable {
|
|||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
font-family: var(--font-family);
|
||||||
}
|
}
|
||||||
h1 { font-size: 24px; }
|
h1 { font-size: calc(var(--base-font-size) * 1.5); }
|
||||||
h2 { font-size: 20px; }
|
h2 { font-size: calc(var(--base-font-size) * 1.25); }
|
||||||
h3 { font-size: 18px; }
|
h3 { font-size: calc(var(--base-font-size) * 1.125); }
|
||||||
|
h4 { font-size: var(--base-font-size); }
|
||||||
|
h5 { font-size: calc(var(--base-font-size) * 0.875); }
|
||||||
|
h6 { font-size: calc(var(--base-font-size) * 0.75); }
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: var(--base-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -79,6 +94,7 @@ struct WebView: UIViewRepresentable {
|
|||||||
a {
|
a {
|
||||||
color: var(--link-color);
|
color: var(--link-color);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
font-family: var(--font-family);
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
@ -93,6 +109,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
background-color: \(isDarkMode ? "rgba(58, 58, 60, 0.3)" : "rgba(0, 122, 255, 0.05)");
|
background-color: \(isDarkMode ? "rgba(58, 58, 60, 0.3)" : "rgba(0, 122, 255, 0.05)");
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: var(--base-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
@ -100,8 +118,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
color: var(--code-text);
|
color: var(--code-text);
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;
|
font-family: \(settings.fontFamily == .monospace ? "var(--font-family)" : "'SF Mono', Menlo, Monaco, Consolas, monospace");
|
||||||
font-size: 14px;
|
font-size: calc(var(--base-font-size) * 0.875);
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
@ -110,14 +128,15 @@ struct WebView: UIViewRepresentable {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;
|
font-family: \(settings.fontFamily == .monospace ? "var(--font-family)" : "'SF Mono', Menlo, Monaco, Consolas, monospace");
|
||||||
font-size: 14px;
|
font-size: calc(var(--base-font-size) * 0.875);
|
||||||
border: 1px solid var(--separator-color);
|
border: 1px solid var(--separator-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
pre code {
|
pre code {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@ -131,6 +150,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: var(--base-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th, td {
|
||||||
@ -147,6 +168,8 @@ struct WebView: UIViewRepresentable {
|
|||||||
ul, ol {
|
ul, ol {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: var(--base-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
@ -211,6 +234,28 @@ struct WebView: UIViewRepresentable {
|
|||||||
func makeCoordinator() -> WebViewCoordinator {
|
func makeCoordinator() -> WebViewCoordinator {
|
||||||
WebViewCoordinator()
|
WebViewCoordinator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func getFontSize(from fontSize: FontSize) -> Int {
|
||||||
|
switch fontSize {
|
||||||
|
case .small: return 14
|
||||||
|
case .medium: return 16
|
||||||
|
case .large: return 18
|
||||||
|
case .extraLarge: return 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getFontFamily(from fontFamily: FontFamily) -> String {
|
||||||
|
switch fontFamily {
|
||||||
|
case .system:
|
||||||
|
return "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
||||||
|
case .serif:
|
||||||
|
return "'Times New Roman', Times, 'Liberation Serif', serif"
|
||||||
|
case .sansSerif:
|
||||||
|
return "'Helvetica Neue', Helvetica, Arial, sans-serif"
|
||||||
|
case .monospace:
|
||||||
|
return "'SF Mono', Menlo, Monaco, Consolas, 'Liberation Mono', monospace"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebViewCoordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
|
class WebViewCoordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
|
||||||
@ -238,4 +283,4 @@ class WebViewCoordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler
|
|||||||
deinit {
|
deinit {
|
||||||
// Der Message Handler wird automatisch mit der WebView entfernt
|
// Der Message Handler wird automatisch mit der WebView entfernt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,9 @@ protocol UseCaseFactory {
|
|||||||
class DefaultUseCaseFactory: UseCaseFactory {
|
class DefaultUseCaseFactory: UseCaseFactory {
|
||||||
private let tokenProvider = CoreDataTokenProvider()
|
private let tokenProvider = CoreDataTokenProvider()
|
||||||
private lazy var api: PAPI = API(tokenProvider: tokenProvider)
|
private lazy var api: PAPI = API(tokenProvider: tokenProvider)
|
||||||
private lazy var authRepository: PAuthRepository = AuthRepository(api: api, settingsRepository: SettingsRepository())
|
private lazy var authRepository: PAuthRepository = AuthRepository(api: api, settingsRepository: settingsRepository)
|
||||||
private lazy var bookmarksRepository: PBookmarksRepository = BookmarksRepository(api: api)
|
private lazy var bookmarksRepository: PBookmarksRepository = BookmarksRepository(api: api)
|
||||||
|
private let settingsRepository: PSettingsRepository = SettingsRepository()
|
||||||
|
|
||||||
static let shared = DefaultUseCaseFactory()
|
static let shared = DefaultUseCaseFactory()
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class DefaultUseCaseFactory: UseCaseFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeSaveSettingsUseCase() -> SaveSettingsUseCase {
|
func makeSaveSettingsUseCase() -> SaveSettingsUseCase {
|
||||||
SaveSettingsUseCase(authRepository: authRepository)
|
SaveSettingsUseCase(settingsRepository: settingsRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLoadSettingsUseCase() -> LoadSettingsUseCase {
|
func makeLoadSettingsUseCase() -> LoadSettingsUseCase {
|
||||||
|
|||||||
@ -37,6 +37,11 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
.disabled(!viewModel.canLogin || viewModel.isLoading)
|
.disabled(!viewModel.canLogin || viewModel.isLoading)
|
||||||
|
|
||||||
|
Button("Debug-Anmeldung") {
|
||||||
|
viewModel.username = "admin"
|
||||||
|
viewModel.password = "Diggah123"
|
||||||
|
}
|
||||||
|
|
||||||
if viewModel.isLoggedIn {
|
if viewModel.isLoggedIn {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "checkmark.circle.fill")
|
Image(systemName: "checkmark.circle.fill")
|
||||||
@ -69,7 +74,7 @@ struct SettingsView: View {
|
|||||||
ForEach(Theme.allCases, id: \.self) { theme in
|
ForEach(Theme.allCases, id: \.self) { theme in
|
||||||
Text(theme.displayName).tag(theme)
|
Text(theme.displayName).tag(theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Font Settings with Preview
|
// Font Settings with Preview
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
@ -84,13 +89,23 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pickerStyle(MenuPickerStyle())
|
.pickerStyle(MenuPickerStyle())
|
||||||
|
.onChange(of: viewModel.selectedFontFamily) {
|
||||||
|
Task {
|
||||||
|
await viewModel.saveFontSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Picker("Schriftgröße", selection: $viewModel.selectedFontSize) {
|
Picker("Schriftgröße", selection: $viewModel.selectedFontSize) {
|
||||||
ForEach(FontSize.allCases, id: \.self) { size in
|
ForEach(FontSize.allCases, id: \.self) { size in
|
||||||
Text(size.displayName).tag(size)
|
Text(size.displayName).tag(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
|
.onChange(of: viewModel.selectedFontSize) {
|
||||||
|
Task {
|
||||||
|
await viewModel.saveFontSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@ -93,9 +93,9 @@ class SettingsViewModel {
|
|||||||
func loadSettings() async {
|
func loadSettings() async {
|
||||||
do {
|
do {
|
||||||
if let settings = try await loadSettingsUseCase.execute() {
|
if let settings = try await loadSettingsUseCase.execute() {
|
||||||
endpoint = settings.endpoint
|
endpoint = settings.endpoint ?? ""
|
||||||
username = settings.username
|
username = settings.username ?? ""
|
||||||
password = settings.password
|
password = settings.password ?? ""
|
||||||
isLoggedIn = settings.isLoggedIn // Verwendet die neue Hilfsmethode
|
isLoggedIn = settings.isLoggedIn // Verwendet die neue Hilfsmethode
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@ -103,6 +103,17 @@ class SettingsViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func saveFontSettings() async {
|
||||||
|
do {
|
||||||
|
try await saveSettingsUseCase.execute(
|
||||||
|
selectedFontFamily: selectedFontFamily, selectedFontSize: selectedFontSize
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
errorMessage = "Fehler beim Speichern der Font-Einstellungen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
func saveSettings() async {
|
func saveSettings() async {
|
||||||
isSaving = true
|
isSaving = true
|
||||||
@ -134,7 +145,8 @@ class SettingsViewModel {
|
|||||||
successMessage = nil
|
successMessage = nil
|
||||||
|
|
||||||
do {
|
do {
|
||||||
_ = try await loginUseCase.execute(username: username, password: password)
|
let user = try await loginUseCase.execute(username: username, password: password)
|
||||||
|
|
||||||
isLoggedIn = true
|
isLoggedIn = true
|
||||||
successMessage = "Erfolgreich angemeldet"
|
successMessage = "Erfolgreich angemeldet"
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23507" systemVersion="24B83" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23788.4" systemVersion="24F74" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="Item" representedClassName="Item" syncable="YES" codeGenerationType="class">
|
<entity name="Item" representedClassName="Item" syncable="YES" codeGenerationType="class">
|
||||||
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="SettingEntity" representedClassName="SettingEntity" syncable="YES" codeGenerationType="class">
|
<entity name="SettingEntity" representedClassName="SettingEntity" syncable="YES" codeGenerationType="class">
|
||||||
<attribute name="endpoint" optional="YES" attributeType="String"/>
|
<attribute name="endpoint" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="fontFamily" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="fontSize" optional="YES" attributeType="String"/>
|
||||||
<attribute name="password" optional="YES" attributeType="String"/>
|
<attribute name="password" optional="YES" attributeType="String"/>
|
||||||
<attribute name="token" optional="YES" attributeType="String"/>
|
<attribute name="token" optional="YES" attributeType="String"/>
|
||||||
<attribute name="username" optional="YES" attributeType="String"/>
|
<attribute name="username" optional="YES" attributeType="String"/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user