Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Toki.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
33D11CD525F8DC18EAB150D1 /* UsagePanelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F34221431C1218B054EAF3 /* UsagePanelViewModel.swift */; };
33D1AB9365F472C13FAC1FE5 /* UsageFormattingBehaviorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F867C95AD0DC1B5DED21C8A7 /* UsageFormattingBehaviorTests.swift */; };
35FB64B954404993C8B925FE /* PanelSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B2DEB3544111BFB20E87AA /* PanelSettingsView.swift */; };
37574A88A40596F8ACA78336 /* PanelTabReorderingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C12A0936724E30F198A0DF8 /* PanelTabReorderingTests.swift */; };
38F5784499477C55CF4303AE /* TokiSyncProtocol in Frameworks */ = {isa = PBXBuildFile; productRef = 3790A5ED47430EC6E53ACB95 /* TokiSyncProtocol */; };
3935A7DF30080C290DF60818 /* RemoteHubClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B03817C34A0165DBDAA6B1C1 /* RemoteHubClient.swift */; };
3ACF65E76AEE66A70EE9A125 /* LocalUsageReaderRegistryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFF0A0D8A54BCA7B3B1D5403 /* LocalUsageReaderRegistryTests.swift */; };
Expand Down Expand Up @@ -104,6 +105,7 @@
A594034C3E62690D54E87A87 /* UsagePeriodTotals.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA514E3EE586C1B3306B7B1F /* UsagePeriodTotals.swift */; };
A6A853AAB2BFFCC2C76B4C9E /* RemoteSyncTransportTestSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4BF69189BDE750B3BE66C4E /* RemoteSyncTransportTestSupport.swift */; };
A6C48427C457CFE820BF1F22 /* SecurityAuditSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68C8E69152F69E73C1E2223B /* SecurityAuditSources.swift */; };
ABA12EC64F68C266F2F2B12C /* PanelTabReordering.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72334C214A37CFD41E9248F5 /* PanelTabReordering.swift */; };
ACD47B7DF15BF86DE361B181 /* SecurityAuditFileDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90462ED4796DF8430B218A31 /* SecurityAuditFileDiscovery.swift */; };
AEFCAD47092D4DA5C27342A6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BB2D1DD657FD734F8EC731D /* libsqlite3.tbd */; };
AF4E8FA1A1E2763EE9CE39E5 /* MenuBarUsageSummaryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D982ED98F3C2AFC2321DD5 /* MenuBarUsageSummaryController.swift */; };
Expand All @@ -117,6 +119,7 @@
BBBA1E0981491A3D5D6000B8 /* GJCReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62EA09E68E4376A474428CB6 /* GJCReaderTests.swift */; };
BFA649180FEA64FB81ABE332 /* UsageServiceActiveTimeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3971E00801C71BA0662D329 /* UsageServiceActiveTimeTests.swift */; };
C0DC30052F0DC7DA43384C92 /* SecurityAuditScannerRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79410B9DB64140E6924887DB /* SecurityAuditScannerRuleTests.swift */; };
C137A93A24E33EB8C8A7B0F8 /* PanelTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C2B5EEA5616B27CACD283D9 /* PanelTab.swift */; };
C17C7313C12364A09D303F7D /* PanelStatComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAAA589FDAB3639AB37F055 /* PanelStatComponents.swift */; };
C36760D5F31645546E54DD9F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1DA65F57500D6F6BB7793AD /* Assets.xcassets */; };
C51D063F04218FF9A6A23A0F /* SecurityAuditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360CAF6769074C64EB0F300 /* SecurityAuditViewModel.swift */; };
Expand Down Expand Up @@ -146,6 +149,7 @@
E5FF669CC57F9472B0ECC364 /* ActivityMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1BA3C46F1641ED01FE347AD /* ActivityMonitor.swift */; };
E6BEA6D7A66A6F0F186C7443 /* PanelPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEFA10FD73480C5807AA39E /* PanelPalette.swift */; };
E71545EEA12908D204F6C4B3 /* HermesPricingRefreshTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BE1C427456BB8200627AEE4 /* HermesPricingRefreshTests.swift */; };
EDBFAEE93BF57893E5932ABC /* UsagePanelTabOrderSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F6125209D344A90AD123B1 /* UsagePanelTabOrderSettingsTests.swift */; };
F33BD3A41CA4185BA5D78D99 /* RemotePricingCatalogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 710D8EB8263EC4B8E8E34B63 /* RemotePricingCatalogTests.swift */; };
F3611A5CE3B2AB9CB5ED9354 /* TokiUsageReaders in Frameworks */ = {isa = PBXBuildFile; productRef = F4BE0251B7B4E79530DD4D78 /* TokiUsageReaders */; };
F55183F1A32D854F0D81E015 /* SecurityAuditSQLiteIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0D1C68FBAE1FD7A594D933 /* SecurityAuditSQLiteIntegrationTests.swift */; };
Expand Down Expand Up @@ -242,6 +246,7 @@
6F267D78A56BD31B18AD02D1 /* RemoteSyncSettingsError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSyncSettingsError.swift; sourceTree = "<group>"; };
710D8EB8263EC4B8E8E34B63 /* RemotePricingCatalogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePricingCatalogTests.swift; sourceTree = "<group>"; };
72156DB6C230C46DE726889F /* UsageReportBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsageReportBuilder.swift; sourceTree = "<group>"; };
72334C214A37CFD41E9248F5 /* PanelTabReordering.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelTabReordering.swift; sourceTree = "<group>"; };
744538423BE5FD3B64B2E8A0 /* CodexReaderBehaviorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodexReaderBehaviorTests.swift; sourceTree = "<group>"; };
754DFBAADC9EFDF744D1150B /* PanelOverviewViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelOverviewViews.swift; sourceTree = "<group>"; };
783228D3069ECDC7545872CE /* RemoteSyncTransportRegressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSyncTransportRegressionTests.swift; sourceTree = "<group>"; };
Expand All @@ -261,16 +266,19 @@
88D8D5F0DE02692D3F73D6E4 /* RemoteSyncSettingsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSyncSettingsViewModelTests.swift; sourceTree = "<group>"; };
89124F350B8FD3F935D973AE /* RemoteUsageReaderTestSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteUsageReaderTestSupport.swift; sourceTree = "<group>"; };
8B5FAD8A81645F8C02AC6D46 /* RemotePricingCatalog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePricingCatalog.swift; sourceTree = "<group>"; };
8C12A0936724E30F198A0DF8 /* PanelTabReorderingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelTabReorderingTests.swift; sourceTree = "<group>"; };
90462ED4796DF8430B218A31 /* SecurityAuditFileDiscovery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAuditFileDiscovery.swift; sourceTree = "<group>"; };
913CCF13950428ECD3F610B8 /* rabbit_run_00.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rabbit_run_00.png; sourceTree = "<group>"; };
91D9A34521436540EE5B9A97 /* RemoteSnapshotModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSnapshotModels.swift; sourceTree = "<group>"; };
95C4DD5CE6E1BD400FEDC0A7 /* RemoteSyncSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSyncSettingsView.swift; sourceTree = "<group>"; };
9BA9245A62D27EB82C373D8A /* SecurityAuditScannerCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAuditScannerCacheTests.swift; sourceTree = "<group>"; };
9C2B5EEA5616B27CACD283D9 /* PanelTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelTab.swift; sourceTree = "<group>"; };
9CDFEBDB8BE38FBD5C551702 /* UsagePanelSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsagePanelSettingsTests.swift; sourceTree = "<group>"; };
9F0D700BB18FFF007E749E42 /* rabbit_run_04.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rabbit_run_04.png; sourceTree = "<group>"; };
9FEFA10FD73480C5807AA39E /* PanelPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelPalette.swift; sourceTree = "<group>"; };
A169A412590D629F7E46349A /* rabbit_run_05.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rabbit_run_05.png; sourceTree = "<group>"; };
A2648C9A747404CF8E5E81E0 /* CursorReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CursorReaderTests.swift; sourceTree = "<group>"; };
A2F6125209D344A90AD123B1 /* UsagePanelTabOrderSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsagePanelTabOrderSettingsTests.swift; sourceTree = "<group>"; };
A3BCD6B222FAE20E8AD17A13 /* SecurityAuditScannerTestSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAuditScannerTestSupport.swift; sourceTree = "<group>"; };
A4692734D41D5DC621C0BF7F /* CodexReaderTestSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodexReaderTestSupport.swift; sourceTree = "<group>"; };
A935D97F072BD30BEA608E73 /* TokiTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TokiTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -516,7 +524,9 @@
FE17F5F5B7894E90A1DEB3BB /* PanelSourceExportViews.swift */,
6BAAA589FDAB3639AB37F055 /* PanelStatComponents.swift */,
6C7BC82ACA2362A5775D0BDD /* PanelSupportViews.swift */,
9C2B5EEA5616B27CACD283D9 /* PanelTab.swift */,
2093913FA9BA770A4DD27B38 /* PanelTabBarView.swift */,
72334C214A37CFD41E9248F5 /* PanelTabReordering.swift */,
5A99E233235E7ED7777321F8 /* ProjectTimelineBreakdown.swift */,
6F267D78A56BD31B18AD02D1 /* RemoteSyncSettingsError.swift */,
95C4DD5CE6E1BD400FEDC0A7 /* RemoteSyncSettingsView.swift */,
Expand Down Expand Up @@ -614,6 +624,7 @@
5C9C1A5B27CF3EDA7779FCB1 /* ModelPricingBehaviorTests.swift */,
B60EB0929925CB9634708D25 /* OpenClawReaderTests.swift */,
3E3CFF960ADBCDC716F649D6 /* PanelHeroComparisonContentTests.swift */,
8C12A0936724E30F198A0DF8 /* PanelTabReorderingTests.swift */,
0ED2530F4E6EEF1D2BC72036 /* PanelUXBehaviorTests.swift */,
B4C3B0595A6C521B237BC8AE /* ProjectTimelineBreakdownTests.swift */,
36330D960147799B00A54231 /* RemotePricingCatalogReviewRegressionTests.swift */,
Expand Down Expand Up @@ -649,6 +660,7 @@
F867C95AD0DC1B5DED21C8A7 /* UsageFormattingBehaviorTests.swift */,
282A1BF7C0245EB113DE2BA8 /* UsageOriginAggregationTests.swift */,
9CDFEBDB8BE38FBD5C551702 /* UsagePanelSettingsTests.swift */,
A2F6125209D344A90AD123B1 /* UsagePanelTabOrderSettingsTests.swift */,
249A8147031075DB2B206742 /* UsageProjectTimelineReportTests.swift */,
D3971E00801C71BA0662D329 /* UsageServiceActiveTimeTests.swift */,
3542FE2DBB444D4843D16F5D /* UsageServiceBehaviorTests.swift */,
Expand Down Expand Up @@ -797,7 +809,9 @@
A4E7B277C7C7934B83760AA3 /* PanelSourceExportViews.swift in Sources */,
C17C7313C12364A09D303F7D /* PanelStatComponents.swift in Sources */,
CB2B57AF9540E6D529CCFF0F /* PanelSupportViews.swift in Sources */,
C137A93A24E33EB8C8A7B0F8 /* PanelTab.swift in Sources */,
984208087B7A16E1F1DE4D02 /* PanelTabBarView.swift in Sources */,
ABA12EC64F68C266F2F2B12C /* PanelTabReordering.swift in Sources */,
1CEB7251F4D5C4E54A0374BC /* ProjectTimelineBreakdown.swift in Sources */,
9A4B70065BCD2F79537DC64C /* ReaderFetchResult.swift in Sources */,
3935A7DF30080C290DF60818 /* RemoteHubClient.swift in Sources */,
Expand Down Expand Up @@ -869,6 +883,7 @@
473D552178FAD36261BEDE30 /* ModelPricingBehaviorTests.swift in Sources */,
9C02E53188EBB7673B1E3539 /* OpenClawReaderTests.swift in Sources */,
DC20285289381D0340F0AEEB /* PanelHeroComparisonContentTests.swift in Sources */,
37574A88A40596F8ACA78336 /* PanelTabReorderingTests.swift in Sources */,
6D753446EBD2D0C4D34CB728 /* PanelUXBehaviorTests.swift in Sources */,
8918E8E69CD59B38BB1E369C /* ProjectTimelineBreakdownTests.swift in Sources */,
4816D8234A1D5A401100A330 /* RemotePricingCatalogReviewRegressionTests.swift in Sources */,
Expand Down Expand Up @@ -904,6 +919,7 @@
33D1AB9365F472C13FAC1FE5 /* UsageFormattingBehaviorTests.swift in Sources */,
590115D0DD0770D8AE1E99F2 /* UsageOriginAggregationTests.swift in Sources */,
7391DCBFFC4ED63D5D5E8B3F /* UsagePanelSettingsTests.swift in Sources */,
EDBFAEE93BF57893E5932ABC /* UsagePanelTabOrderSettingsTests.swift in Sources */,
CF177959CFC6AFC2D6B57957 /* UsageProjectTimelineReportTests.swift in Sources */,
BFA649180FEA64FB81ABE332 /* UsageServiceActiveTimeTests.swift in Sources */,
8694BE0464F0F026D52C8A33 /* UsageServiceBehaviorTests.swift in Sources */,
Expand Down
19 changes: 19 additions & 0 deletions Toki/Features/UsagePanel/PanelSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct PanelSettingsView: View {
set: { settings.setShowsMenuBarCost($0) }))
autoUpdatePricingToggle
launchAtLoginToggle
resetTabOrderRow
if let errorMessage = launchAtLogin.errorMessage {
Text(errorMessage)
.font(.system(size: 10, weight: .medium))
Expand Down Expand Up @@ -132,6 +133,24 @@ struct PanelSettingsView: View {
.opacity(launchAtLogin.isUpdating ? 0.5 : 1)
}

private var resetTabOrderRow: some View {
HStack(spacing: 8) {
Text("Tab order")
.font(.system(size: 12))
.foregroundColor(Color.white.opacity(0.74))
Spacer(minLength: 0)
Button("Reset") {
settings.resetTabOrder()
}
.buttonStyle(.plain)
.font(.system(size: 11, weight: .semibold))
.foregroundColor(Color.white.opacity(settings.isUsingDefaultTabOrder ? 0.3 : 0.7))
.disabled(settings.isUsingDefaultTabOrder)
}
.padding(.horizontal, 10)
.padding(.vertical, 7)
}

private var divider: some View {
Rectangle()
.fill(Color.white.opacity(0.07))
Expand Down
68 changes: 68 additions & 0 deletions Toki/Features/UsagePanel/PanelTab.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import SwiftUI

/// Case names are the raw values persisted with the user's tab order, so
/// renaming a case invalidates a stored order. `UsagePanelSettings` falls back
/// to the declared order for values it no longer recognizes.
enum PanelTab: String, CaseIterable, Hashable, Identifiable {
case overview
case projects
case byModel
case sources
case workTime
case hourly

var id: Self {
self
}

var title: String {
switch self {
case .overview:
"Overview"
case .projects:
"Projects"
case .byModel:
"Models"
case .sources:
"Sources"
case .workTime:
"Time"
case .hourly:
"Hourly"
}
}

var systemImage: String {
switch self {
case .overview:
"chart.pie.fill"
case .projects:
"folder.fill"
case .byModel:
"cpu"
case .sources:
"tray.full.fill"
case .workTime:
"clock.fill"
case .hourly:
"chart.bar.fill"
}
}

var accentColor: Color {
switch self {
case .overview:
Color(red: 0.55, green: 0.45, blue: 1.0)
case .projects:
Color(red: 0.40, green: 0.68, blue: 1.0)
case .byModel:
Color(red: 0.42, green: 0.84, blue: 0.70)
case .sources:
Color(red: 1.0, green: 0.66, blue: 0.36)
case .workTime:
Color(red: 0.95, green: 0.52, blue: 0.70)
case .hourly:
Color(red: 0.75, green: 0.70, blue: 1.0)
}
}
}
Loading
Loading