feat(main): add 'view statistics' to action long-press menu

- Add 'View Statistics' option to the context menu when long-pressing an action icon in the main tab
- Route the user directly to the independent Statistics tab upon selection
- Automatically apply the selected action as a filter when entering the Statistics tab, mirroring the 'View Records' behavior
This commit is contained in:
songyc macbook 2026-07-09 22:52:11 +09:00
parent 810e4d6373
commit ce3cb00fcc
5 changed files with 59 additions and 3 deletions

View File

@ -90,17 +90,30 @@ final class AppRouter {
/// ( nil )
var pendingHistoryActionID: PersistentIdentifier?
/// ( nil )
var pendingStatsActionID: PersistentIdentifier?
/// . .
var morePath: [AppTab] = []
/// . .
func openHistory(filtering actionID: PersistentIdentifier, visibleTabsRaw: String) {
pendingHistoryActionID = actionID
open(.history, visibleTabsRaw: visibleTabsRaw)
}
/// . .
func openStats(filtering actionID: PersistentIdentifier, visibleTabsRaw: String) {
pendingStatsActionID = actionID
open(.stats, visibleTabsRaw: visibleTabsRaw)
}
private func open(_ tab: AppTab, visibleTabsRaw: String) {
let visible = AppTab.visibleTabs(from: visibleTabsRaw)
if visible.contains(.history) {
tabSelection = AppTab.history.rawValue
if visible.contains(tab) {
tabSelection = tab.rawValue
} else {
morePath = [.history]
morePath = [tab]
tabSelection = AppTab.moreTabValue
}
}

View File

@ -591,6 +591,9 @@
},
"통계" : {
},
"통계 보기" : {
},
"특정 시각 지정" : {

View File

@ -99,6 +99,23 @@ struct MainView: View {
} message: { action in
Text("\(action.name) 행동을 삭제할까요? 기록도 함께 삭제됩니다.")
}
#if DEBUG
// : -openStatsFor "" / -openHistoryFor ""
.onAppear {
if let name = UserDefaults.standard.string(forKey: "openStatsFor"),
let action = actions.first(where: { $0.name == name }) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
router.openStats(filtering: action.persistentModelID, visibleTabsRaw: visibleTabsRaw)
}
}
if let name = UserDefaults.standard.string(forKey: "openHistoryFor"),
let action = actions.first(where: { $0.name == name }) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
router.openHistory(filtering: action.persistentModelID, visibleTabsRaw: visibleTabsRaw)
}
}
}
#endif
}
// MARK:
@ -189,6 +206,15 @@ struct MainView: View {
} label: {
Label("기록 확인", systemImage: "list.bullet.rectangle")
}
Button {
//
router.openStats(
filtering: action.persistentModelID,
visibleTabsRaw: visibleTabsRaw
)
} label: {
Label("통계 보기", systemImage: "chart.xyaxis.line")
}
Button {
recordsAction = action
} label: {

View File

@ -13,6 +13,7 @@ import SwiftData
import Charts
struct StatsTabView: View {
@Environment(AppRouter.self) private var router
@Query private var sessions: [TimeSession]
@Query private var entries: [CountEntry]
@Query(sort: \Tag.sortOrder) private var tags: [Tag]
@ -112,6 +113,7 @@ struct StatsTabView: View {
)
}
.onAppear {
consumePendingFilter()
#if DEBUG
// : -excludeActions "," , -statShowFilter YES
if let raw = UserDefaults.standard.string(forKey: "excludeActions") {
@ -125,6 +127,18 @@ struct StatsTabView: View {
}
#endif
}
.onChange(of: router.pendingStatsActionID) {
consumePendingFilter()
}
}
/// ' ' ( )
private func consumePendingFilter() {
guard let id = router.pendingStatsActionID else { return }
//
excludedActionIDs = Set(allActions.map(\.persistentModelID)).subtracting([id])
anchorDayKey = math.dayKey(for: .now)
router.pendingStatsActionID = nil
}
// MARK: