Sources/OrgstarMobile/SettingsScreen.swift
64 lines · 3154 bytes
2 symbols in this file
1#if os(iOS)
2import OrgApp
3import OrgCore
4import SwiftUI
5import UIKit
6
7/// Where settings come from: a folder with the Mac's `config.toml` and `capture.toml`, kept in
8/// sync by iCloud Drive or another app.
9struct SettingsScreen: View {
10 let model: MobileModel
11 @State private var choosing = false
12
13 var body: some View {
14 Form {
15 Section {
16 LabeledContent("Folder", value: model.configFolder?.lastPathComponent ?? "None")
17 Button(model.configFolder == nil ? "Choose Folder…" : "Choose Another Folder…") { choosing = true }
18 if model.configFolder != nil {
19 Button("Stop Using This Folder", role: .destructive) { model.setConfigFolder(nil) }
20 }
21 ForEach(model.configProblems, id: \.self) { Text($0).foregroundStyle(.red) }
22 } header: {
23 Text("Configuration")
24 } footer: {
25 Text("A folder with config.toml and capture.toml, such as a synced copy of ~/.config/orgstar from your Mac. Changes to them apply as they sync.")
26 }
27 Section("In use") {
28 let _ = model.settingsVersion
29 LabeledContent("TODO keywords", value: todoKeywords)
30 LabeledContent("Agenda", value: agenda)
31 LabeledContent("Reminders", value: OrgPreferences.reminders() ? "\(OrgPreferences.reminderLead()) min before" : "Off")
32 LabeledContent("Capture templates", value: CaptureTemplates.load().templates.map(\.key).joined(separator: " "))
33 LabeledContent("Theme", value: UserDefaults.standard.string(forKey: "themeFile").flatMap { $0.isEmpty ? nil : $0 } ?? "Default")
34 LabeledContent("Font", value: font)
35 }
36 }
37 .navigationTitle("Settings")
38 .fileImporter(isPresented: $choosing, allowedContentTypes: [.folder]) { result in
39 if case .success(let url) = result { model.setConfigFolder(url) }
40 }
41 }
42
43 /// The span and start day, worded as the Mac's Settings word the start.
44 private var agenda: String {
45 func days(_ count: Int) -> String { count == 1 ? "1 day" : "\(count) days" }
46 let offset = OrgPreferences.agendaStartOffset()
47 let start = offset == 0 ? "today" : offset < 0 ? "\(days(-offset)) before today" : "\(days(offset)) after today"
48 return "\(days(OrgPreferences.agendaSpan())), starting \(start)"
49 }
50
51 /// The theme's family, or the system's monospaced font when it's unset or not on the device.
52 private var font: String {
53 let spec = model.theme
54 let family = spec.font.isEmpty || UIFont.fontNames(forFamilyName: spec.font).isEmpty ? "System monospaced" : spec.font
55 let missing = !spec.font.isEmpty && family != spec.font ? " (\(spec.font) isn't installed)" : ""
56 return "\(family), \(spec.fontSize) pt\(missing)"
57 }
58
59 private var todoKeywords: String {
60 OrgPreferences.orgSettings().todoSequences.map { ($0.active.map(\.name) + ["|"] + $0.done.map(\.name)).joined(separator: " ") }
61 .joined(separator: "; ")
62 }
63}
64#endif