feat: add Font Size, List Row Density, and Menu Bar Icon settings

This commit is contained in:
nimbold
2026-06-03 05:03:31 +03:30
parent 1f82d342e3
commit ff03a4cda5
5 changed files with 85 additions and 2 deletions
+24
View File
@@ -68,6 +68,18 @@ final class AppSettings: ObservableObject {
@Published var appTheme: AppTheme = .system {
didSet { save() }
}
@Published var appFontSize: AppFontSize = .standard {
didSet { save() }
}
@Published var listRowDensity: ListRowDensity = .standard {
didSet { save() }
}
@Published var showMenuBarIcon: Bool = true {
didSet { save() }
}
@Published var perServerConnections: Int {
didSet {
@@ -134,6 +146,9 @@ final class AppSettings: ObservableObject {
if let data = defaults.data(forKey: storageKey),
let stored = try? JSONDecoder().decode(StoredSettings.self, from: data) {
appTheme = stored.appTheme ?? .system
appFontSize = stored.appFontSize ?? .standard
listRowDensity = stored.listRowDensity ?? .standard
showMenuBarIcon = stored.showMenuBarIcon ?? true
perServerConnections = min(max(stored.perServerConnections, 1), 16)
maxConcurrentDownloads = min(max(stored.maxConcurrentDownloads ?? 3, 1), 12)
globalSpeedLimitKiBPerSecond = min(max(stored.globalSpeedLimitKiBPerSecond ?? 0, 0), 10_485_760)
@@ -143,6 +158,9 @@ final class AppSettings: ObservableObject {
downloadDirectories = Self.decodeDirectories(stored.downloadDirectories)
} else {
appTheme = .system
appFontSize = .standard
listRowDensity = .standard
showMenuBarIcon = true
perServerConnections = 16
maxConcurrentDownloads = 3
globalSpeedLimitKiBPerSecond = 0
@@ -225,6 +243,9 @@ final class AppSettings: ObservableObject {
private func save() {
let stored = StoredSettings(
appTheme: appTheme,
appFontSize: appFontSize,
listRowDensity: listRowDensity,
showMenuBarIcon: showMenuBarIcon,
perServerConnections: perServerConnections,
maxConcurrentDownloads: maxConcurrentDownloads,
globalSpeedLimitKiBPerSecond: globalSpeedLimitKiBPerSecond,
@@ -285,6 +306,9 @@ final class AppSettings: ObservableObject {
private struct StoredSettings: Codable {
var appTheme: AppTheme?
var appFontSize: AppFontSize?
var listRowDensity: ListRowDensity?
var showMenuBarIcon: Bool?
var perServerConnections: Int
var maxConcurrentDownloads: Int?
var globalSpeedLimitKiBPerSecond: Int?
+2 -1
View File
@@ -526,6 +526,7 @@ struct DownloadTable: View {
}
private struct DownloadRow: View {
@EnvironmentObject private var settings: AppSettings
let item: DownloadItem
let priorityNumber: Int?
let visibleColumns: [DownloadColumn]
@@ -537,7 +538,7 @@ private struct DownloadRow: View {
ForEach(visibleColumns) { column in
cell(for: column)
.padding(.horizontal, 8)
.padding(.vertical, 8)
.padding(.vertical, settings.listRowDensity.verticalPadding)
.frame(width: columnWidth(column), alignment: alignment(for: column))
.clipped()
}
+5 -1
View File
@@ -21,6 +21,7 @@ struct FirelinkApp: App {
.environmentObject(settings)
.environmentObject(schedulerController)
.modifier(AppThemeModifier(theme: settings.appTheme))
.dynamicTypeSize(settings.appFontSize.dynamicTypeSize)
.frame(minWidth: 1180, idealWidth: 1280, minHeight: 720, idealHeight: 760)
}
.windowStyle(.titleBar)
@@ -30,6 +31,7 @@ struct FirelinkApp: App {
.environmentObject(controller)
.environmentObject(settings)
.modifier(AppThemeModifier(theme: settings.appTheme))
.dynamicTypeSize(settings.appFontSize.dynamicTypeSize)
}
.windowResizability(.contentSize)
@@ -39,9 +41,11 @@ struct FirelinkApp: App {
.environmentObject(controller)
.environmentObject(settings)
.modifier(AppThemeModifier(theme: settings.appTheme))
.dynamicTypeSize(settings.appFontSize.dynamicTypeSize)
} else {
ContentUnavailableView("Download Not Found", systemImage: "questionmark.circle")
.modifier(AppThemeModifier(theme: settings.appTheme))
.dynamicTypeSize(settings.appFontSize.dynamicTypeSize)
}
}
.windowResizability(.contentSize)
@@ -55,7 +59,7 @@ struct FirelinkApp: App {
}
}
MenuBarExtra("Firelink", systemImage: "arrow.down.circle") {
MenuBarExtra("Firelink", systemImage: "arrow.down.circle", isInserted: $settings.showMenuBarIcon) {
TrayMenuView()
.environmentObject(controller)
}
+22
View File
@@ -137,6 +137,28 @@ private struct LookAndFeelSettingsPane: View {
.font(.caption)
.foregroundStyle(.secondary)
}
Section("Display") {
Picker("Font Size", selection: $settings.appFontSize) {
ForEach(AppFontSize.allCases) { size in
Text(size.rawValue).tag(size)
}
}
Picker("List Row Density", selection: $settings.listRowDensity) {
ForEach(ListRowDensity.allCases) { density in
Text(density.rawValue).tag(density)
}
}
}
Section("Menu Bar") {
Toggle("Show menu bar icon", isOn: $settings.showMenuBarIcon)
Text("Provides quick access to downloads and queues from the macOS menu bar.")
.font(.caption)
.foregroundStyle(.secondary)
}
}
.formStyle(.grouped)
}
+32
View File
@@ -1,6 +1,38 @@
import SwiftUI
import AppKit
enum AppFontSize: String, Codable, CaseIterable, Identifiable, Sendable {
case small = "Small"
case standard = "Standard"
case large = "Large"
var id: String { rawValue }
var dynamicTypeSize: DynamicTypeSize {
switch self {
case .small: return .small
case .standard: return .medium
case .large: return .xLarge
}
}
}
enum ListRowDensity: String, Codable, CaseIterable, Identifiable, Sendable {
case compact = "Compact"
case standard = "Standard"
case relaxed = "Relaxed"
var id: String { rawValue }
var verticalPadding: CGFloat {
switch self {
case .compact: return 4
case .standard: return 8
case .relaxed: return 14
}
}
}
enum AppTheme: String, Codable, CaseIterable, Identifiable, Sendable {
case system = "System Default"
case light = "Light"