font size setting
This commit is contained in:
@@ -1638,6 +1638,7 @@ private struct RunSummary: View {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func styled(_ parts: [(String, CGFloat, Color?)], size: CGFloat = 12) -> AttributedString {
|
||||
var out = AttributedString()
|
||||
for (text, weight, color) in parts {
|
||||
|
||||
@@ -277,10 +277,12 @@ struct DiagramLayout {
|
||||
let size: CGSize
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private var labelFont: CTFont {
|
||||
Fonts.ns(13) as CTFont
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private var edgeFont: CTFont {
|
||||
Fonts.ns(12) as CTFont
|
||||
}
|
||||
@@ -296,6 +298,7 @@ func textSize(_ text: String, _ font: CTFont) -> CGSize {
|
||||
return CGSize(width: ceil(width), height: ceil(lineHeight * CGFloat(lines.count)))
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func layoutFlowchart(_ chart: Flowchart) -> DiagramLayout {
|
||||
let ids = chart.order
|
||||
var succ: [String: [String]] = [:]
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
import CoreText
|
||||
import Foundation
|
||||
import Synchronization
|
||||
import SwiftData
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
final class FontSize {
|
||||
static let shared = FontSize()
|
||||
static let range = 9...20
|
||||
|
||||
private(set) var body = PrefsRecord.defaultFontSize
|
||||
|
||||
private init() {
|
||||
load()
|
||||
}
|
||||
|
||||
func load() {
|
||||
body = record()?.fontSize ?? PrefsRecord.defaultFontSize
|
||||
}
|
||||
|
||||
func set(_ size: Int) {
|
||||
if let r = record() {
|
||||
r.fontSize = size
|
||||
r.saved = Date()
|
||||
} else {
|
||||
persistence.insert(PrefsRecord(fontSize: size))
|
||||
}
|
||||
saveRecords()
|
||||
body = size
|
||||
}
|
||||
|
||||
private func record() -> PrefsRecord? {
|
||||
fetchRecords(FetchDescriptor<PrefsRecord>(sortBy: [SortDescriptor(\.saved, order: .reverse)])).first
|
||||
}
|
||||
}
|
||||
|
||||
enum Fonts {
|
||||
private static func file(_ subset: String, _ italic: Bool, _ weight: CGFloat) -> CTFontDescriptor {
|
||||
let url = Bundle.main.resourceURL!.appending(path: "fonts/atkinson-hyperlegible-mono-\(subset)-wght-\(italic ? "italic" : "normal").woff2")
|
||||
@@ -17,7 +51,10 @@ enum Fonts {
|
||||
|
||||
private static let fonts = Mutex<[String: CTFont]>([:])
|
||||
|
||||
// Call sites give sizes relative to a 13pt body; the user's font size shifts them all.
|
||||
@MainActor
|
||||
private static func cached(_ size: CGFloat, _ weight: CGFloat, _ italic: Bool) -> CTFont {
|
||||
let size = size + CGFloat(FontSize.shared.body - 13)
|
||||
let key = "\(size) \(weight) \(italic)"
|
||||
return fonts.withLock { fonts in
|
||||
if let f = fonts[key] {
|
||||
@@ -29,10 +66,12 @@ enum Fonts {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
static func font(_ size: CGFloat, weight: CGFloat = 400, italic: Bool = false) -> Font {
|
||||
Font(cached(size, weight, italic))
|
||||
}
|
||||
|
||||
@MainActor
|
||||
static func ns(_ size: CGFloat, weight: CGFloat = 400, italic: Bool = false) -> NSFont {
|
||||
cached(size, weight, italic) as NSFont
|
||||
}
|
||||
|
||||
@@ -38,8 +38,21 @@ final class VisitRecord {
|
||||
}
|
||||
}
|
||||
|
||||
@Model
|
||||
final class PrefsRecord {
|
||||
static let defaultFontSize = 12
|
||||
|
||||
var fontSize = PrefsRecord.defaultFontSize
|
||||
var saved = Date.distantPast
|
||||
|
||||
init(fontSize: Int) {
|
||||
self.fontSize = fontSize
|
||||
saved = Date()
|
||||
}
|
||||
}
|
||||
|
||||
private let container: ModelContainer = {
|
||||
let schema = Schema([ServerRecord.self, DraftRecord.self, VisitRecord.self])
|
||||
let schema = Schema([ServerRecord.self, DraftRecord.self, VisitRecord.self, PrefsRecord.self])
|
||||
let dir = URL.applicationSupportDirectory.appending(path: "run.fc.byre.mac", directoryHint: .isDirectory)
|
||||
do {
|
||||
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
||||
|
||||
@@ -27,6 +27,11 @@ struct SettingsView: View {
|
||||
.foregroundStyle(Palette.muted)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
ServerColorPicker()
|
||||
heading("Font size")
|
||||
Text("The size of body text, on every Mac you use. Other text grows and shrinks with it.")
|
||||
.foregroundStyle(Palette.muted)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
FontSizeStepper()
|
||||
heading("Notifications")
|
||||
DeviceNotifications()
|
||||
PrefsBox()
|
||||
@@ -87,12 +92,33 @@ private struct ServerColorPicker: View {
|
||||
}
|
||||
}
|
||||
|
||||
private struct FontSizeStepper: View {
|
||||
var body: some View {
|
||||
let fonts = FontSize.shared
|
||||
HStack(spacing: 8) {
|
||||
Button("−") {
|
||||
fonts.set(fonts.body - 1)
|
||||
}
|
||||
.buttonStyle(WebButtonStyle())
|
||||
.disabled(fonts.body <= FontSize.range.lowerBound)
|
||||
Text("\(fonts.body) pt")
|
||||
.monospacedDigit()
|
||||
Button("+") {
|
||||
fonts.set(fonts.body + 1)
|
||||
}
|
||||
.buttonStyle(WebButtonStyle())
|
||||
.disabled(fonts.body >= FontSize.range.upperBound)
|
||||
}
|
||||
.padding(.top, 8)
|
||||
}
|
||||
}
|
||||
|
||||
private struct SyncState: View {
|
||||
var body: some View {
|
||||
TimelineView(.periodic(from: .now, by: 30)) { _ in
|
||||
if let sync = Servers.shared.sync {
|
||||
if sync.ok {
|
||||
Text("This Mac shares its servers, window colours, drafts and task visits through iCloud. Last synced \(ago(sync.at)).")
|
||||
Text("This Mac shares its servers, window colours, font size, drafts and task visits through iCloud. Last synced \(ago(sync.at)).")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
} else {
|
||||
Text("iCloud sync is failing on this Mac, so changes made here aren't reaching your other Macs. Failed \(ago(sync.at)): \(sync.error ?? "")")
|
||||
|
||||
@@ -34,6 +34,7 @@ final class Servers {
|
||||
connection.store?.drafts?.reload()
|
||||
}
|
||||
load()
|
||||
FontSize.shared.load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,10 @@ struct TerminalHost: NSViewRepresentable {
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: TerminalView, context: Context) {
|
||||
let font = Fonts.ns(13)
|
||||
if nsView.font !== font {
|
||||
nsView.font = font
|
||||
}
|
||||
if context.coordinator.scheme == scheme {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user