feat: add reordering to floating radial menu and fix weekly timetable step

Radial menu icon order (iPhone floating nav only):
- Settings → 내비게이션 gains a '반원 메뉴 순서 편집' link (shown only when the
  radial style is selected) that opens a drag-to-reorder list of all 7 tabs.
- Order is stored device-local via @AppStorage(SettingsKeys.radialTabOrder)
  (not CloudKit-synced); RadialMenu reads it through AppTab.radialOrder(from:),
  which always yields the full tab set and appends any missing/unknown value in
  default spec order — so partial or legacy strings can never drop a tab.
- iPad/Mac sidebars and the watch target are untouched (they never read the key).

History timetable date step:
- The date header </> buttons now jump by a full week (7 days) when the
  timetable is in '일주일' view, and by 1 day otherwise (list / daily timetable).
- The calendar popover and '오늘' still set the date directly, so those paths and
  record loading are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
This commit is contained in:
songyc macbook 2026-07-12 09:13:20 +09:00
parent 8f2b5fab93
commit a02e06a9df
5 changed files with 73 additions and 3 deletions

View File

@ -222,6 +222,22 @@ enum AppTab: String, CaseIterable, Identifiable {
return tabs.isEmpty ? [.main] : Array(tabs.prefix(TabBarConfig.maxVisible))
}
/// .
/// : (: ) () .
static func radialOrder(from raw: String) -> [AppTab] {
var result: [AppTab] = []
var seen: Set<AppTab> = []
for part in raw.split(separator: ",") {
if let tab = AppTab(rawValue: String(part)), seen.insert(tab).inserted {
result.append(tab)
}
}
for tab in AppTab.allCases where !seen.contains(tab) {
result.append(tab)
}
return result
}
@ViewBuilder
var rootView: some View {
switch self {

View File

@ -293,8 +293,12 @@ struct HistoryView: View {
}
}
private func moveDay(_ delta: Int) {
selectedDayKey = math.calendar.date(byAdding: .day, value: delta, to: selectedDayKey)!
/// .
/// '' (7) / .
/// (· , / )
private func moveDay(_ direction: Int) {
let step = (mode == .timetable && timetableWeekly) ? 7 : 1
selectedDayKey = math.calendar.date(byAdding: .day, value: direction * step, to: selectedDayKey)!
}
// MARK: ( )

View File

@ -65,6 +65,9 @@ struct RadialMenu: View {
/// AppTab.rawValue ( tabSelection )
@Binding var selection: String
/// ( , )
@AppStorage(SettingsKeys.radialTabOrder) private var radialOrderRaw = ""
//
private let fabSize: CGFloat = 62
private let itemSize: CGFloat = 52
@ -74,7 +77,8 @@ struct RadialMenu: View {
/// ( )
private let labelOffset: CGFloat = 40
private var tabs: [AppTab] { AppTab.allCases }
/// ( )
private var tabs: [AppTab] { AppTab.radialOrder(from: radialOrderRaw) }
private var currentTab: AppTab {
AppTab(rawValue: selection) ?? .main

View File

@ -70,6 +70,14 @@ struct SettingsView: View {
Text(style.label).tag(style.rawValue)
}
}
//
if navStyleRaw == NavStyle.radial.rawValue {
NavigationLink {
RadialOrderView()
} label: {
Label("반원 메뉴 순서 편집", systemImage: "arrow.up.arrow.down")
}
}
} header: {
Text("내비게이션")
} footer: {
@ -279,6 +287,42 @@ struct SettingsView: View {
}
}
// MARK: - () (iPhone )
/// .
/// () , iPad·Mac .
struct RadialOrderView: View {
@AppStorage(SettingsKeys.radialTabOrder) private var radialOrderRaw = ""
@State private var order: [AppTab] = []
var body: some View {
List {
Section {
ForEach(order) { tab in
HStack(spacing: 12) {
Image(systemName: tab.symbol)
.foregroundStyle(AppTheme.green)
.frame(width: 28)
Text(tab.label)
}
}
.onMove { source, destination in
order.move(fromOffsets: source, toOffset: destination)
radialOrderRaw = order.map(\.rawValue).joined(separator: ",")
}
} footer: {
Text("반원 메뉴를 펼쳤을 때 왼쪽 끝에서 오른쪽 끝으로 이 순서대로 아이콘이 배치돼요. 손잡이를 끌어 순서를 바꾸세요.")
}
}
.environment(\.editMode, .constant(.active))
.scrollContentBackground(.hidden)
.background(AppTheme.background)
.navigationTitle("반원 메뉴 순서")
.navigationBarTitleDisplayMode(.inline)
.onAppear { order = AppTab.radialOrder(from: radialOrderRaw) }
}
}
// MARK: -
struct PremiumView: View {

View File

@ -29,6 +29,8 @@ enum SettingsKeys {
static let goalCardStyle = "settings.goalCardStyle"
/// iPhone . NavStyle rawValue ("tabBar" | "radial"). ()
static let navStyle = "settings.navStyle"
/// () . AppTab rawValue . ()
static let radialTabOrder = "settings.radialTabOrder"
}
/// iPhone (iPad·Mac , )