From 740731209fde098181e6d6830687c91a3638ff85 Mon Sep 17 00:00:00 2001 From: Carlos Enumo Date: Sat, 27 May 2023 13:51:14 +0100 Subject: [PATCH] Fix not being able to select custom date format (#132) --- Calendr.xcodeproj/project.pbxproj | 4 +-- .../GeneralSettingsViewController.swift | 28 +++++++++---------- Calendr/Settings/SettingsViewModel.swift | 19 +++++++++---- CalendrTests/SettingsViewModelTests.swift | 18 ++++++------ 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/Calendr.xcodeproj/project.pbxproj b/Calendr.xcodeproj/project.pbxproj index a66c3e5e..6b7d4b66 100644 --- a/Calendr.xcodeproj/project.pbxproj +++ b/Calendr.xcodeproj/project.pbxproj @@ -1242,7 +1242,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.9.5; + MARKETING_VERSION = 1.9.6; PRODUCT_BUNDLE_IDENTIFIER = br.paker.Calendr; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Calendr/Config/Calendr-Bridging-Header.h"; @@ -1268,7 +1268,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.9.5; + MARKETING_VERSION = 1.9.6; PRODUCT_BUNDLE_IDENTIFIER = br.paker.Calendr; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Calendr/Config/Calendr-Bridging-Header.h"; diff --git a/Calendr/Settings/GeneralSettingsViewController.swift b/Calendr/Settings/GeneralSettingsViewController.swift index 8408025f..fbe074b0 100644 --- a/Calendr/Settings/GeneralSettingsViewController.swift +++ b/Calendr/Settings/GeneralSettingsViewController.swift @@ -278,27 +278,25 @@ class GeneralSettingsViewController: NSViewController { private func setUpDateFormat() { - let dateFormatStyle = dateFormatDropdown.rx.controlProperty( - getter: { (dropdown: NSPopUpButton) -> DateStyle in - DateStyle(rawValue: UInt(dropdown.indexOfSelectedItem + 1)) ?? .none - }, - setter: { (dropdown: NSPopUpButton, style: DateStyle) in - dropdown.selectItem(at: (style.isCustom ? dropdown.numberOfItems : Int(style.rawValue)) - 1) - } + let dateFormatControl = dateFormatDropdown.rx.controlProperty( + getter: \.indexOfSelectedItem, + setter: { $0.selectItem(at: $1) } ) - dateFormatStyle - .skip(1) - .bind(to: viewModel.statusItemDateStyleObserver) - .disposed(by: disposeBag) + Observable.combineLatest( + viewModel.dateStyleOptions, dateFormatControl.skip(1) + ) + .map { $0[$1].style } + .bind(to: viewModel.statusItemDateStyleObserver) + .disposed(by: disposeBag) Observable.combineLatest( viewModel.dateStyleOptions, viewModel.statusItemDateStyle ) - .bind { [dateFormatDropdown] options, dateStyle in - dateFormatDropdown.removeAllItems() - dateFormatDropdown.addItems(withTitles: options) - dateFormatStyle.onNext(dateStyle) + .bind { [dropdown = dateFormatDropdown] options, dateStyle in + dropdown.removeAllItems() + dropdown.addItems(withTitles: options.map(\.title)) + dropdown.selectItem(at: dateStyle.isCustom ? dropdown.numberOfItems - 1 : options.firstIndex(where: { $0.style == dateStyle }) ?? 0) } .disposed(by: disposeBag) diff --git a/Calendr/Settings/SettingsViewModel.swift b/Calendr/Settings/SettingsViewModel.swift index fc682325..e799a23f 100644 --- a/Calendr/Settings/SettingsViewModel.swift +++ b/Calendr/Settings/SettingsViewModel.swift @@ -15,6 +15,11 @@ extension DateStyle { var isCustom: Bool { !Self.options.contains(self) } } +struct DateStyleOption: Equatable { + let style: DateStyle + let title: String +} + typealias PopoverMaterial = NSVisualEffectView.Material extension PopoverMaterial { @@ -90,7 +95,7 @@ class SettingsViewModel: StatusItemSettings, NextEventSettings, CalendarSettings let showStatusItemDate: Observable let showStatusItemBackground: Observable let statusItemDateStyle: Observable - let dateStyleOptions: Observable<[String]> + let dateStyleOptions: Observable<[DateStyleOption]> let statusItemDateFormat: Observable let dateFormatPlaceholder = "E d MMM YYYY" let isDateFormatInputVisible: Observable @@ -194,14 +199,16 @@ class SettingsViewModel: StatusItemSettings, NextEventSettings, CalendarSettings dateStyleOptions = calendarObservable .map { calendar in let dateFormatter = DateFormatter(calendar: calendar) - var options: [String] = [] + var options: [DateStyleOption] = [] - for i: UInt in DateStyle.options.map(\.rawValue) { - dateFormatter.dateStyle = .init(rawValue: i) ?? .none - options.append(dateFormatter.string(from: dateProvider.now)) + for option in DateStyle.options { + dateFormatter.dateStyle = option + let title = dateFormatter.string(from: dateProvider.now) + guard !options.contains(where: { $0.title == title }) else { continue } + options.append(.init(style: option, title: title)) } - options.append("\(Strings.Settings.MenuBar.dateFormatCustom)...") + options.append(.init(style: .none, title: "\(Strings.Settings.MenuBar.dateFormatCustom)...")) return options } diff --git a/CalendrTests/SettingsViewModelTests.swift b/CalendrTests/SettingsViewModelTests.swift index ff95607f..1ea661e5 100644 --- a/CalendrTests/SettingsViewModelTests.swift +++ b/CalendrTests/SettingsViewModelTests.swift @@ -183,18 +183,18 @@ class SettingsViewModelTests: XCTestCase { dateProvider.m_calendar.locale = Locale(identifier: "en_US") - var options: [String]? + var options: [DateStyleOption]? viewModel.dateStyleOptions .bind { options = $0 } .disposed(by: disposeBag) XCTAssertEqual(options, [ - "1/1/21", - "Jan 1, 2021", - "January 1, 2021", - "Friday, January 1, 2021", - "Custom..." + .init(style: .short, title: "1/1/21"), + .init(style: .medium, title: "Jan 1, 2021"), + .init(style: .long, title: "January 1, 2021"), + .init(style: .full, title: "Friday, January 1, 2021"), + .init(style: .none, title: "Custom...") ]) } @@ -202,19 +202,19 @@ class SettingsViewModelTests: XCTestCase { dateProvider.m_calendar.locale = Locale(identifier: "en_US") - var options: [String]? + var options: [DateStyleOption]? viewModel.dateStyleOptions .bind { options = $0 } .disposed(by: disposeBag) - XCTAssertEqual(options?.first, "1/1/21") + XCTAssertEqual(options?.first, .init(style: .short, title: "1/1/21")) dateProvider.m_calendar.locale = Locale(identifier: "en_GB") notificationCenter.post(name: NSLocale.currentLocaleDidChangeNotification, object: nil) - XCTAssertEqual(options?.first, "01/01/2021") + XCTAssertEqual(options?.first, .init(style: .short, title: "01/01/2021")) } func testDateStyleSelected() {