mirror of
https://github.com/pawelorzech/MacTorn.git
synced 2026-01-29 19:54:27 +00:00
feat: Improve accessibility support and update README
- Fix Reduce Transparency mode in light mode (dark buttons issue) - Lower opacity values for better readability when reduceTransparency is enabled - Add Accessibility section to README documenting macOS accessibility support - Update README with new light/dark mode screenshots - Bump version to 1.4.4
This commit is contained in:
parent
273fd31884
commit
21ac399269
24 changed files with 180 additions and 63 deletions
Binary file not shown.
BIN
MacTorn-v1.4.4.zip
Normal file
BIN
MacTorn-v1.4.4.zip
Normal file
Binary file not shown.
|
|
@ -30,6 +30,7 @@
|
||||||
AAA00021 /* NetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10022 /* NetworkSession.swift */; };
|
AAA00021 /* NetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10022 /* NetworkSession.swift */; };
|
||||||
AAA00022 /* TravelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10023 /* TravelView.swift */; };
|
AAA00022 /* TravelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10023 /* TravelView.swift */; };
|
||||||
AAA00023 /* CreditsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10024 /* CreditsView.swift */; };
|
AAA00023 /* CreditsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10024 /* CreditsView.swift */; };
|
||||||
|
AAA00024 /* TransparencyEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA10025 /* TransparencyEnvironment.swift */; };
|
||||||
/* Unit Tests */
|
/* Unit Tests */
|
||||||
BBB00001 /* MockNetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB10001 /* MockNetworkSession.swift */; };
|
BBB00001 /* MockNetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB10001 /* MockNetworkSession.swift */; };
|
||||||
BBB00002 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB10002 /* TestHelpers.swift */; };
|
BBB00002 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB10002 /* TestHelpers.swift */; };
|
||||||
|
|
@ -89,6 +90,7 @@
|
||||||
AAA10022 /* NetworkSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSession.swift; sourceTree = "<group>"; };
|
AAA10022 /* NetworkSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSession.swift; sourceTree = "<group>"; };
|
||||||
AAA10023 /* TravelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TravelView.swift; sourceTree = "<group>"; };
|
AAA10023 /* TravelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TravelView.swift; sourceTree = "<group>"; };
|
||||||
AAA10024 /* CreditsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsView.swift; sourceTree = "<group>"; };
|
AAA10024 /* CreditsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsView.swift; sourceTree = "<group>"; };
|
||||||
|
AAA10025 /* TransparencyEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransparencyEnvironment.swift; sourceTree = "<group>"; };
|
||||||
AAA10000 /* MacTorn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MacTorn.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
AAA10000 /* MacTorn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MacTorn.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* Unit Test Files */
|
/* Unit Test Files */
|
||||||
BBB10001 /* MockNetworkSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNetworkSession.swift; sourceTree = "<group>"; };
|
BBB10001 /* MockNetworkSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNetworkSession.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -155,6 +157,7 @@
|
||||||
AAA30005 /* Views */,
|
AAA30005 /* Views */,
|
||||||
AAA30007 /* Utilities */,
|
AAA30007 /* Utilities */,
|
||||||
AAA30008 /* Networking */,
|
AAA30008 /* Networking */,
|
||||||
|
AAA30009 /* Helpers */,
|
||||||
);
|
);
|
||||||
path = MacTorn;
|
path = MacTorn;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -233,6 +236,14 @@
|
||||||
path = Networking;
|
path = Networking;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
AAA30009 /* Helpers */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
AAA10025 /* TransparencyEnvironment.swift */,
|
||||||
|
);
|
||||||
|
path = Helpers;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* Unit Tests Groups */
|
/* Unit Tests Groups */
|
||||||
BBB30000 /* MacTornTests */ = {
|
BBB30000 /* MacTornTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
@ -445,6 +456,7 @@
|
||||||
AAA00021 /* NetworkSession.swift in Sources */,
|
AAA00021 /* NetworkSession.swift in Sources */,
|
||||||
AAA00022 /* TravelView.swift in Sources */,
|
AAA00022 /* TravelView.swift in Sources */,
|
||||||
AAA00023 /* CreditsView.swift in Sources */,
|
AAA00023 /* CreditsView.swift in Sources */,
|
||||||
|
AAA00024 /* TransparencyEnvironment.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -627,7 +639,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -654,7 +666,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -672,7 +684,7 @@
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
|
|
@ -690,7 +702,7 @@
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
|
|
@ -708,7 +720,7 @@
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
|
|
@ -725,7 +737,7 @@
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.4.3;
|
MARKETING_VERSION = 1.4.4;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mactorn.MacTornUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||||
|
|
|
||||||
13
MacTorn/MacTorn/Helpers/TransparencyEnvironment.swift
Normal file
13
MacTorn/MacTorn/Helpers/TransparencyEnvironment.swift
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// Environment key for reduce transparency setting
|
||||||
|
private struct ReduceTransparencyKey: EnvironmentKey {
|
||||||
|
static let defaultValue: Bool = false
|
||||||
|
}
|
||||||
|
|
||||||
|
extension EnvironmentValues {
|
||||||
|
var reduceTransparency: Bool {
|
||||||
|
get { self[ReduceTransparencyKey.self] }
|
||||||
|
set { self[ReduceTransparencyKey.self] = newValue }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,16 +3,37 @@ import SwiftUI
|
||||||
@main
|
@main
|
||||||
struct MacTornApp: App {
|
struct MacTornApp: App {
|
||||||
@StateObject private var appState = AppState()
|
@StateObject private var appState = AppState()
|
||||||
|
@AppStorage("appearanceMode") private var appearanceModeRaw: String = AppearanceMode.system.rawValue
|
||||||
|
@AppStorage("reduceTransparency") private var reduceTransparency: Bool = false
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
MenuBarExtra {
|
MenuBarExtra {
|
||||||
ContentView()
|
ContentView()
|
||||||
.environmentObject(appState)
|
.environmentObject(appState)
|
||||||
|
.environment(\.reduceTransparency, reduceTransparency)
|
||||||
|
.onAppear {
|
||||||
|
updateAppearance()
|
||||||
|
}
|
||||||
|
.onChange(of: appearanceModeRaw) { _ in
|
||||||
|
updateAppearance()
|
||||||
|
}
|
||||||
} label: {
|
} label: {
|
||||||
MenuBarLabel(appState: appState)
|
MenuBarLabel(appState: appState)
|
||||||
}
|
}
|
||||||
.menuBarExtraStyle(.window)
|
.menuBarExtraStyle(.window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateAppearance() {
|
||||||
|
let mode = AppearanceMode(rawValue: appearanceModeRaw) ?? .system
|
||||||
|
switch mode {
|
||||||
|
case .system:
|
||||||
|
NSApp.appearance = nil
|
||||||
|
case .light:
|
||||||
|
NSApp.appearance = NSAppearance(named: .aqua)
|
||||||
|
case .dark:
|
||||||
|
NSApp.appearance = NSAppearance(named: .darkAqua)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Menu Bar Label
|
// MARK: - Menu Bar Label
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,27 @@ import os.log
|
||||||
|
|
||||||
private let logger = Logger(subsystem: "com.mactorn", category: "AppState")
|
private let logger = Logger(subsystem: "com.mactorn", category: "AppState")
|
||||||
|
|
||||||
|
// MARK: - Appearance
|
||||||
|
enum AppearanceMode: String, CaseIterable {
|
||||||
|
case system = "System"
|
||||||
|
case light = "Light"
|
||||||
|
case dark = "Dark"
|
||||||
|
|
||||||
|
var colorScheme: ColorScheme? {
|
||||||
|
switch self {
|
||||||
|
case .system: return nil
|
||||||
|
case .light: return .light
|
||||||
|
case .dark: return .dark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
class AppState: ObservableObject {
|
class AppState: ObservableObject {
|
||||||
// MARK: - Persisted
|
// MARK: - Persisted
|
||||||
@AppStorage("apiKey") var apiKey: String = ""
|
@AppStorage("apiKey") var apiKey: String = ""
|
||||||
@AppStorage("refreshInterval") var refreshInterval: Int = 30
|
@AppStorage("refreshInterval") var refreshInterval: Int = 30
|
||||||
|
@AppStorage("appearanceMode") var appearanceMode: String = AppearanceMode.system.rawValue
|
||||||
|
|
||||||
// MARK: - Published State
|
// MARK: - Published State
|
||||||
@Published var data: TornResponse?
|
@Published var data: TornResponse?
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct AttacksView: View {
|
struct AttacksView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -39,9 +40,9 @@ struct AttacksView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.red.opacity(0.05))
|
.background(Color.red.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Recent Attacks
|
// Recent Attacks
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
@ -91,9 +92,9 @@ struct AttacksView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.orange.opacity(0.05))
|
.background(Color.orange.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
ActionButton(title: "Attack", icon: "bolt.fill", color: .red) {
|
ActionButton(title: "Attack", icon: "bolt.fill", color: .red) {
|
||||||
|
|
@ -134,10 +135,11 @@ struct AttacksView: View {
|
||||||
|
|
||||||
// MARK: - Stat Item
|
// MARK: - Stat Item
|
||||||
struct StatItem: View {
|
struct StatItem: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let label: String
|
let label: String
|
||||||
let value: String
|
let value: String
|
||||||
let color: Color
|
let color: Color
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 2) {
|
VStack(spacing: 2) {
|
||||||
Text(value)
|
Text(value)
|
||||||
|
|
@ -149,7 +151,7 @@ struct StatItem: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.background(color.opacity(0.1))
|
.background(color.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(4)
|
.cornerRadius(4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ChainView: View {
|
struct ChainView: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let chain: Chain
|
let chain: Chain
|
||||||
let fetchTime: Date
|
let fetchTime: Date
|
||||||
|
|
||||||
|
|
@ -25,7 +26,7 @@ struct ChainView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(color.opacity(0.1))
|
.background(color.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
} else if chain.isOnCooldown {
|
} else if chain.isOnCooldown {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct EventsView: View {
|
struct EventsView: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let events: [TornEvent]
|
let events: [TornEvent]
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -33,7 +34,7 @@ struct EventsView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(Color.blue.opacity(0.05))
|
.background(Color.blue.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ProgressBarView: View {
|
struct ProgressBarView: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let label: String
|
let label: String
|
||||||
let current: Int
|
let current: Int
|
||||||
let maximum: Int
|
let maximum: Int
|
||||||
|
|
@ -40,10 +41,10 @@ struct ProgressBarView: View {
|
||||||
ZStack(alignment: .leading) {
|
ZStack(alignment: .leading) {
|
||||||
// Background track
|
// Background track
|
||||||
RoundedRectangle(cornerRadius: 4)
|
RoundedRectangle(cornerRadius: 4)
|
||||||
.fill(Color.gray.opacity(0.3))
|
.fill(Color.gray.opacity(reduceTransparency ? 0.5 : 0.3))
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 4)
|
RoundedRectangle(cornerRadius: 4)
|
||||||
.stroke(color.opacity(0.3), lineWidth: 1)
|
.stroke(color.opacity(reduceTransparency ? 0.5 : 0.3), lineWidth: 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filled progress
|
// Filled progress
|
||||||
|
|
@ -51,13 +52,13 @@ struct ProgressBarView: View {
|
||||||
RoundedRectangle(cornerRadius: 4)
|
RoundedRectangle(cornerRadius: 4)
|
||||||
.fill(
|
.fill(
|
||||||
LinearGradient(
|
LinearGradient(
|
||||||
colors: [color, color.opacity(0.7)],
|
colors: [color, color.opacity(reduceTransparency ? 0.9 : 0.7)],
|
||||||
startPoint: .leading,
|
startPoint: .leading,
|
||||||
endPoint: .trailing
|
endPoint: .trailing
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.frame(width: max(4, geometry.size.width * progress))
|
.frame(width: max(4, geometry.size.width * progress))
|
||||||
.shadow(color: color.opacity(0.5), radius: 2, x: 0, y: 0)
|
.shadow(color: color.opacity(reduceTransparency ? 0.7 : 0.5), radius: 2, x: 0, y: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct StatusBadgesView: View {
|
struct StatusBadgesView: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let status: Status
|
let status: Status
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -18,10 +19,10 @@ struct StatusBadgesView: View {
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.background(Color.red.opacity(0.1))
|
.background(Color.red.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.isInJail {
|
if status.isInJail {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image(systemName: "lock.fill")
|
Image(systemName: "lock.fill")
|
||||||
|
|
@ -34,7 +35,7 @@ struct StatusBadgesView: View {
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.background(Color.orange.opacity(0.1))
|
.background(Color.orange.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ enum AppTab: String, CaseIterable {
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
@State private var showSettings = false
|
@State private var showSettings = false
|
||||||
@State private var currentTab: AppTab = .status
|
@State private var currentTab: AppTab = .status
|
||||||
|
|
||||||
|
|
@ -55,8 +56,8 @@ struct ContentView: View {
|
||||||
|
|
||||||
// Loading Overlay
|
// Loading Overlay
|
||||||
if appState.isLoading && appState.lastUpdated == nil {
|
if appState.isLoading && appState.lastUpdated == nil {
|
||||||
Color.black.opacity(0.4)
|
(reduceTransparency ? Color(.windowBackgroundColor) : Color.black.opacity(0.4))
|
||||||
.background(.ultraThinMaterial)
|
.background(reduceTransparency ? AnyShapeStyle(Color(.windowBackgroundColor)) : AnyShapeStyle(.ultraThinMaterial))
|
||||||
|
|
||||||
VStack(spacing: 12) {
|
VStack(spacing: 12) {
|
||||||
ProgressView()
|
ProgressView()
|
||||||
|
|
@ -106,7 +107,7 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(currentTab == tab ? Color.accentColor.opacity(0.2) : Color.clear)
|
.background(currentTab == tab ? Color.accentColor.opacity(reduceTransparency ? 0.3 : 0.2) : Color.clear)
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
.contentShape(Rectangle()) // Make entire area clickable
|
.contentShape(Rectangle()) // Make entire area clickable
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct CreditsView: View {
|
struct CreditsView: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
@Binding var showCredits: Bool
|
@Binding var showCredits: Bool
|
||||||
|
|
||||||
// MARK: - Developer
|
// MARK: - Developer
|
||||||
|
|
@ -107,7 +108,7 @@ struct CreditsView: View {
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Color.orange.opacity(0.1))
|
.background(Color.orange.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +140,7 @@ struct CreditsView: View {
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Color.secondary.opacity(0.1))
|
.background(Color.secondary.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +172,7 @@ struct CreditsView: View {
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Color.secondary.opacity(0.1))
|
.background(Color.secondary.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +200,7 @@ struct CreditsView: View {
|
||||||
}
|
}
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Color.secondary.opacity(0.1))
|
.background(Color.secondary.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct FactionView: View {
|
struct FactionView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -33,7 +34,7 @@ struct FactionView: View {
|
||||||
.foregroundColor(chainColor(faction.chain))
|
.foregroundColor(chainColor(faction.chain))
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(chainColor(faction.chain).opacity(0.1))
|
.background(chainColor(faction.chain).opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,9 +59,9 @@ struct FactionView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.blue.opacity(0.05))
|
.background(Color.blue.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Armory Quick Actions
|
// Armory Quick Actions
|
||||||
VStack(alignment: .leading, spacing: 8) {
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
@ -85,9 +86,9 @@ struct FactionView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.purple.opacity(0.05))
|
.background(Color.purple.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
ActionButton(title: "Faction", icon: "person.3.fill", color: .blue) {
|
ActionButton(title: "Faction", icon: "person.3.fill", color: .blue) {
|
||||||
|
|
@ -138,11 +139,12 @@ struct FactionView: View {
|
||||||
|
|
||||||
// MARK: - Armory Button
|
// MARK: - Armory Button
|
||||||
struct ArmoryButton: View {
|
struct ArmoryButton: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let title: String
|
let title: String
|
||||||
let icon: String
|
let icon: String
|
||||||
let color: Color
|
let color: Color
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
VStack(spacing: 2) {
|
VStack(spacing: 2) {
|
||||||
|
|
@ -153,7 +155,7 @@ struct ArmoryButton: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(color.opacity(0.15))
|
.background(color.opacity(reduceTransparency ? 0.4 : 0.15))
|
||||||
.foregroundColor(color)
|
.foregroundColor(color)
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct MoneyView: View {
|
struct MoneyView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -72,9 +73,9 @@ struct MoneyView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.green.opacity(0.05))
|
.background(Color.green.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
ActionButton(title: "Send Money", icon: "paperplane.fill", color: .blue) {
|
ActionButton(title: "Send Money", icon: "paperplane.fill", color: .blue) {
|
||||||
|
|
@ -112,11 +113,12 @@ struct MoneyView: View {
|
||||||
|
|
||||||
// MARK: - Action Button Component
|
// MARK: - Action Button Component
|
||||||
struct ActionButton: View {
|
struct ActionButton: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let title: String
|
let title: String
|
||||||
let icon: String
|
let icon: String
|
||||||
let color: Color
|
let color: Color
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
VStack(spacing: 4) {
|
VStack(spacing: 4) {
|
||||||
|
|
@ -127,7 +129,7 @@ struct ActionButton: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(color.opacity(0.1))
|
.background(color.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.foregroundColor(color)
|
.foregroundColor(color)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct PropertiesView: View {
|
struct PropertiesView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -58,6 +59,7 @@ struct PropertiesView: View {
|
||||||
|
|
||||||
// MARK: - Property Card
|
// MARK: - Property Card
|
||||||
struct PropertyCard: View {
|
struct PropertyCard: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let property: PropertyInfo
|
let property: PropertyInfo
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -72,7 +74,7 @@ struct PropertyCard: View {
|
||||||
.foregroundColor(.orange)
|
.foregroundColor(.orange)
|
||||||
.padding(.horizontal, 6)
|
.padding(.horizontal, 6)
|
||||||
.padding(.vertical, 2)
|
.padding(.vertical, 2)
|
||||||
.background(Color.orange.opacity(0.2))
|
.background(Color.orange.opacity(reduceTransparency ? 0.5 : 0.2))
|
||||||
.cornerRadius(4)
|
.cornerRadius(4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +114,7 @@ struct PropertyCard: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.brown.opacity(0.05))
|
.background(Color.brown.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import SwiftUI
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@AppStorage("appearanceMode") private var appearanceMode: String = AppearanceMode.system.rawValue
|
||||||
|
@AppStorage("reduceTransparency") private var reduceTransparency: Bool = false
|
||||||
@State private var inputKey: String = ""
|
@State private var inputKey: String = ""
|
||||||
@State private var showCredits: Bool = false
|
@State private var showCredits: Bool = false
|
||||||
|
|
||||||
|
|
@ -88,6 +90,30 @@ struct SettingsView: View {
|
||||||
))
|
))
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Appearance Mode
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "moon.circle")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.frame(width: 20)
|
||||||
|
|
||||||
|
Picker("Appearance", selection: $appearanceMode) {
|
||||||
|
ForEach(AppearanceMode.allCases, id: \.self) { mode in
|
||||||
|
Text(mode.rawValue).tag(mode.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pickerStyle(.segmented)
|
||||||
|
.labelsHidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce Transparency (Accessibility)
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "eye")
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.frame(width: 20)
|
||||||
|
Toggle("Reduce Transparency", isOn: $reduceTransparency)
|
||||||
|
.toggleStyle(.switch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
|
@ -116,16 +142,16 @@ struct SettingsView: View {
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
.background(Color.purple.opacity(0.15))
|
.background(Color.purple.opacity(reduceTransparency ? 0.4 : 0.15))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.background(Color.purple.opacity(0.05))
|
.background(Color.purple.opacity(reduceTransparency ? 0.25 : 0.05))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
|
|
||||||
// Update Section
|
// Update Section
|
||||||
if let update = appState.updateAvailable {
|
if let update = appState.updateAvailable {
|
||||||
VStack(spacing: 8) {
|
VStack(spacing: 8) {
|
||||||
|
|
@ -146,7 +172,7 @@ struct SettingsView: View {
|
||||||
}
|
}
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Color.green.opacity(0.1))
|
.background(Color.green.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct StatusView: View {
|
struct StatusView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -109,7 +110,7 @@ struct StatusView: View {
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(Color.blue.opacity(0.1))
|
.background(Color.blue.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
@ -150,7 +151,7 @@ struct StatusView: View {
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.background(Color.blue.opacity(0.1))
|
.background(Color.blue.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.transaction { $0.animation = nil }
|
.transaction { $0.animation = nil }
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +241,7 @@ struct StatusView: View {
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.padding(.horizontal, 6)
|
.padding(.horizontal, 6)
|
||||||
.background(Color.accentColor.opacity(0.1))
|
.background(Color.accentColor.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(4)
|
.cornerRadius(4)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import AppKit
|
||||||
// MARK: - Flying Status View (separate for proper live updates)
|
// MARK: - Flying Status View (separate for proper live updates)
|
||||||
struct FlyingStatusView: View {
|
struct FlyingStatusView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let destination: String
|
let destination: String
|
||||||
let timestamp: Int
|
let timestamp: Int
|
||||||
let departed: Int
|
let departed: Int
|
||||||
|
|
@ -60,7 +61,7 @@ struct FlyingStatusView: View {
|
||||||
GeometryReader { geometry in
|
GeometryReader { geometry in
|
||||||
ZStack(alignment: .leading) {
|
ZStack(alignment: .leading) {
|
||||||
RoundedRectangle(cornerRadius: 4)
|
RoundedRectangle(cornerRadius: 4)
|
||||||
.fill(Color.gray.opacity(0.2))
|
.fill(Color.gray.opacity(reduceTransparency ? 0.5 : 0.2))
|
||||||
.frame(height: 8)
|
.frame(height: 8)
|
||||||
|
|
||||||
RoundedRectangle(cornerRadius: 4)
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
|
@ -72,7 +73,7 @@ struct FlyingStatusView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.blue.opacity(0.1))
|
.background(Color.blue.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(12)
|
.cornerRadius(12)
|
||||||
.transaction { $0.animation = nil }
|
.transaction { $0.animation = nil }
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +81,7 @@ struct FlyingStatusView: View {
|
||||||
|
|
||||||
struct TravelView: View {
|
struct TravelView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
|
@ -164,7 +166,7 @@ struct TravelView: View {
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.orange.opacity(0.1))
|
.background(Color.orange.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(12)
|
.cornerRadius(12)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,7 +185,7 @@ struct TravelView: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.green.opacity(0.1))
|
.background(Color.green.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(12)
|
.cornerRadius(12)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +214,7 @@ struct TravelView: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 10)
|
.padding(.vertical, 10)
|
||||||
.background(Color.accentColor.opacity(0.1))
|
.background(Color.accentColor.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
@ -248,7 +250,7 @@ struct TravelView: View {
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(Color.accentColor.opacity(0.1))
|
.background(Color.accentColor.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
@ -283,7 +285,7 @@ struct TravelView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(Color.secondary.opacity(0.1))
|
.background(Color.secondary.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +314,7 @@ struct TravelView: View {
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(Color.accentColor.opacity(0.1))
|
.background(Color.accentColor.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
@ -329,7 +331,7 @@ struct TravelView: View {
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(Color.accentColor.opacity(0.1))
|
.background(Color.accentColor.opacity(reduceTransparency ? 0.2 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct WatchlistView: View {
|
struct WatchlistView: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
@State private var showAddItem = false
|
@State private var showAddItem = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -56,7 +57,7 @@ struct WatchlistView: View {
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
.background(Color.green.opacity(0.1))
|
.background(Color.green.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(4)
|
.cornerRadius(4)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
@ -64,10 +65,10 @@ struct WatchlistView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(Color.gray.opacity(0.1))
|
.background(Color.gray.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watchlist Items with Prices
|
// Watchlist Items with Prices
|
||||||
if appState.watchlistItems.isEmpty && !showAddItem {
|
if appState.watchlistItems.isEmpty && !showAddItem {
|
||||||
VStack(spacing: 8) {
|
VStack(spacing: 8) {
|
||||||
|
|
@ -132,6 +133,7 @@ struct WatchlistView: View {
|
||||||
|
|
||||||
// MARK: - Watchlist Price Row
|
// MARK: - Watchlist Price Row
|
||||||
struct WatchlistPriceRow: View {
|
struct WatchlistPriceRow: View {
|
||||||
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
||||||
let item: WatchlistItem
|
let item: WatchlistItem
|
||||||
let onOpen: () -> Void
|
let onOpen: () -> Void
|
||||||
let onRemove: () -> Void
|
let onRemove: () -> Void
|
||||||
|
|
@ -200,10 +202,10 @@ struct WatchlistPriceRow: View {
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background(Color.gray.opacity(0.1))
|
.background(Color.gray.opacity(reduceTransparency ? 0.4 : 0.1))
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func formatPrice(_ price: Int) -> String {
|
private func formatPrice(_ price: Int) -> String {
|
||||||
if price >= 1_000_000 {
|
if price >= 1_000_000 {
|
||||||
return String(format: "$%.1fM", Double(price) / 1_000_000)
|
return String(format: "$%.1fM", Double(price) / 1_000_000)
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -8,7 +8,9 @@ A native macOS menu bar app for monitoring your **Torn** game status.
|
||||||

|

|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="app.png?v=1.2" alt="MacTorn Screenshot" width="600">
|
<img src="app_light_1.png" alt="MacTorn Light Mode" width="320">
|
||||||
|
|
||||||
|
<img src="app_dark_1.png" alt="MacTorn Dark Mode" width="320">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
@ -57,6 +59,14 @@ A native macOS menu bar app for monitoring your **Torn** game status.
|
||||||
- **🚀 Launch at Login**: Start seamlessly with macOS.
|
- **🚀 Launch at Login**: Start seamlessly with macOS.
|
||||||
- **⚡️ Optimized Startup**: Non-blocking data fetching for instant UI responsiveness.
|
- **⚡️ Optimized Startup**: Non-blocking data fetching for instant UI responsiveness.
|
||||||
|
|
||||||
|
## Accessibility
|
||||||
|
|
||||||
|
MacTorn respects macOS accessibility settings:
|
||||||
|
|
||||||
|
- **Reduce Transparency**: When enabled in System Settings → Accessibility → Display, the app uses solid backgrounds instead of translucent materials for better readability
|
||||||
|
- **Light & Dark Mode**: Full support for both appearance modes with optimized contrast
|
||||||
|
- **Color-coded indicators**: Status bars and badges use distinct colors that work well in both modes
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Download the latest release from [Releases](https://github.com/pawelorzech/MacTorn/releases)
|
1. Download the latest release from [Releases](https://github.com/pawelorzech/MacTorn/releases)
|
||||||
|
|
|
||||||
BIN
app.png
BIN
app.png
Binary file not shown.
|
Before Width: | Height: | Size: 246 KiB |
BIN
app_dark_1.png
Normal file
BIN
app_dark_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 233 KiB |
BIN
app_light_1.png
Normal file
BIN
app_light_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 226 KiB |
Loading…
Reference in a new issue