Skip to content

Commit 59c0904

Browse files
Add custom menu bar options and localization updates
- Introduced a new custom menu bar format in AppModel, allowing users to toggle the display of the Nepal flag and the Bikram Sambat year. - Updated SettingsView to include toggles for the new custom options, enhancing user control over the menu bar display. - Added corresponding localization strings for the custom menu bar settings in both English and Nepali. - Implemented unit tests to ensure the correct functionality and persistence of the custom menu bar settings.
1 parent 709a52e commit 59c0904

6 files changed

Lines changed: 75 additions & 3 deletions

File tree

Sources/SajiloApp/Core/Foundation/AppLanguage.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ enum L10n {
9999
static let launchAtLogin = LocalizedStringResource("settings.launch-at-login", bundle: .sajiloResources)
100100
static let showDockIcon = LocalizedStringResource("settings.show-dock-icon", bundle: .sajiloResources)
101101
static let menuBar = LocalizedStringResource("settings.menu-bar", bundle: .sajiloResources)
102+
static let menuBarCustom = LocalizedStringResource("settings.menu-bar-custom", bundle: .sajiloResources)
103+
static let menuBarShowFlag = LocalizedStringResource("settings.menu-bar-show-flag", bundle: .sajiloResources)
104+
static let menuBarShowYear = LocalizedStringResource("settings.menu-bar-show-year", bundle: .sajiloResources)
102105
static let modules = LocalizedStringResource("settings.modules", bundle: .sajiloResources)
103106
static let weatherLocation = LocalizedStringResource("settings.weather-location", bundle: .sajiloResources)
104107
static let forexFavourites = LocalizedStringResource("settings.forex-favourites", bundle: .sajiloResources)

Sources/SajiloApp/Features/AppModel.swift

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ final class AppModel {
1111
case nepaliFlag
1212
case englishShort
1313
case numeric
14+
case custom
1415

1516
var id: String { rawValue }
1617

@@ -24,15 +25,18 @@ final class AppModel {
2425
switch self {
2526
case .nepaliShort: return "\(day) \(date.nepaliMonthName)"
2627
case .nepaliLong: return "\(day) \(date.nepaliMonthName) \(year)"
27-
case .nepaliFlag: return "🇳🇵 \(day) \(date.nepaliMonthName)"
28+
case .nepaliFlag: return "🇳🇵 \(day) \(date.nepaliMonthName) \(year)"
2829
case .englishShort: return "\(date.day) \(date.englishMonthName)"
2930
case .numeric: return numerals.slashedDate(date)
31+
case .custom: return "\(day) \(date.nepaliMonthName) \(year)"
3032
}
3133
}
3234
}
3335

3436
private enum DefaultsKey {
3537
static let menuBarFormat = "menuBarFormat"
38+
static let customMenuBarShowsFlag = "customMenuBarShowsFlag"
39+
static let customMenuBarShowsYear = "customMenuBarShowsYear"
3640
static let appLanguage = "appLanguage"
3741
static let numeralStyle = "numeralStyle"
3842
static let weatherEnabled = "weatherEnabled"
@@ -60,6 +64,16 @@ final class AppModel {
6064
didSet { defaults.set(selectedMenuBarFormat.rawValue, forKey: DefaultsKey.menuBarFormat) }
6165
}
6266

67+
/// The Custom menu-bar option starts with the full Nepali date, then lets
68+
/// people keep or remove the two pieces that matter most at a glance.
69+
var customMenuBarShowsFlag: Bool {
70+
didSet { defaults.set(customMenuBarShowsFlag, forKey: DefaultsKey.customMenuBarShowsFlag) }
71+
}
72+
73+
var customMenuBarShowsYear: Bool {
74+
didSet { defaults.set(customMenuBarShowsYear, forKey: DefaultsKey.customMenuBarShowsYear) }
75+
}
76+
6377
var appLanguage: AppLanguage {
6478
didSet { defaults.set(appLanguage.rawValue, forKey: DefaultsKey.appLanguage) }
6579
}
@@ -247,7 +261,21 @@ final class AppModel {
247261
}
248262

249263
var menuBarTitle: String {
250-
selectedMenuBarFormat.title(for: today, numerals: numeralStyle)
264+
menuBarTitle(for: selectedMenuBarFormat)
265+
}
266+
267+
func menuBarTitle(for format: MenuBarFormat) -> String {
268+
guard format == .custom else {
269+
return format.title(for: today, numerals: numeralStyle)
270+
}
271+
272+
let day = numeralStyle.string(from: today.day)
273+
let year = numeralStyle.string(from: today.year)
274+
var parts: [String] = []
275+
if customMenuBarShowsFlag { parts.append("🇳🇵") }
276+
parts.append("\(day) \(today.nepaliMonthName)")
277+
if customMenuBarShowsYear { parts.append(year) }
278+
return parts.joined(separator: " ")
251279
}
252280

253281
var visibleCards: [DashboardCard] {
@@ -322,6 +350,8 @@ final class AppModel {
322350

323351
selectedMenuBarFormat = defaults.string(forKey: DefaultsKey.menuBarFormat)
324352
.flatMap(MenuBarFormat.init(rawValue:)) ?? .nepaliShort
353+
customMenuBarShowsFlag = defaults.object(forKey: DefaultsKey.customMenuBarShowsFlag) as? Bool ?? true
354+
customMenuBarShowsYear = defaults.object(forKey: DefaultsKey.customMenuBarShowsYear) as? Bool ?? true
325355
appLanguage = defaults.string(forKey: DefaultsKey.appLanguage)
326356
.flatMap(AppLanguage.init(rawValue:)) ?? .mixed
327357
numeralStyle = defaults.string(forKey: DefaultsKey.numeralStyle)

Sources/SajiloApp/Features/Settings/SettingsView.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,18 @@ struct SettingsView: View {
7474
// picker previews exactly what appears in the menu bar.
7575
Picker(L10n.display, selection: $model.selectedMenuBarFormat) {
7676
ForEach(AppModel.MenuBarFormat.allCases) { format in
77-
Text(verbatim: format.title(for: model.today)).tag(format)
77+
if format == .custom {
78+
Text(L10n.menuBarCustom).tag(format)
79+
} else {
80+
Text(verbatim: model.menuBarTitle(for: format)).tag(format)
81+
}
7882
}
7983
}
84+
85+
if model.selectedMenuBarFormat == .custom {
86+
Toggle(L10n.menuBarShowFlag, isOn: $model.customMenuBarShowsFlag)
87+
Toggle(L10n.menuBarShowYear, isOn: $model.customMenuBarShowsYear)
88+
}
8089
}
8190

8291
SettingsSection(L10n.modules) {

Sources/SajiloApp/Resources/en.lproj/Localizable.strings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
"settings.launch-at-login" = "Launch at login";
9393
"settings.launch-unavailable-note" = "Move Sajilo to your Applications folder to enable this.";
9494
"settings.menu-bar" = "Menu bar";
95+
"settings.menu-bar-custom" = "Custom…";
96+
"settings.menu-bar-show-flag" = "Show Nepal flag";
97+
"settings.menu-bar-show-year" = "Show BS year";
9598
"settings.modules" = "Modules";
9699
"settings.numerals" = "Numerals";
97100
"settings.rates-source" = "Rates source";

Sources/SajiloApp/Resources/ne.lproj/Localizable.strings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
"settings.launch-at-login" = "लगइनमा सुरु गर्नुहोस्";
9393
"settings.launch-unavailable-note" = "यो सुविधा चलाउन Sajilo लाई तपाईंको Applications फोल्डरमा सार्नुहोस्।";
9494
"settings.menu-bar" = "मेनु बार";
95+
"settings.menu-bar-custom" = "अनुकूलन…";
96+
"settings.menu-bar-show-flag" = "नेपालको झण्डा देखाउनुहोस्";
97+
"settings.menu-bar-show-year" = "वि.सं. वर्ष देखाउनुहोस्";
9598
"settings.modules" = "मोड्युलहरू";
9699
"settings.numerals" = "अङ्कहरू";
97100
"settings.rates-source" = "दर स्रोत";

Tests/SajiloAppTests/NumeralStyleTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ struct NumeralStyleTests {
6464
#expect(model.menuBarTitle == NumeralStyle.devanagari.slashedDate(model.today))
6565
}
6666

67+
@Test func flagFormatIncludesTheBikramSambatYear() {
68+
let model = makeModel()
69+
model.selectedMenuBarFormat = .nepaliFlag
70+
71+
#expect(model.menuBarTitle.hasPrefix("🇳🇵 "))
72+
#expect(model.menuBarTitle.contains("२०८३"))
73+
}
74+
75+
@Test func customMenuBarFormatPersistsItsFlagAndYearChoices() {
76+
let defaults = makeDefaults()
77+
let model = makeModel(defaults: defaults)
78+
model.selectedMenuBarFormat = .custom
79+
model.customMenuBarShowsFlag = false
80+
model.customMenuBarShowsYear = true
81+
82+
#expect(model.menuBarTitle.contains("🇳🇵") == false)
83+
#expect(model.menuBarTitle.contains("२०८३"))
84+
85+
let restored = makeModel(defaults: defaults)
86+
#expect(restored.selectedMenuBarFormat == .custom)
87+
#expect(restored.customMenuBarShowsFlag == false)
88+
#expect(restored.customMenuBarShowsYear)
89+
}
90+
6791
/// `englishShort` was already Latin by definition; the preference must not
6892
/// turn its month name into digits or otherwise disturb it.
6993
@Test func englishShortFormatIsUnaffected() {

0 commit comments

Comments
 (0)