Skip to content

Commit

Permalink
Open Calendar app at the selected date
Browse files Browse the repository at this point in the history
  • Loading branch information
pakerwreah committed Feb 20, 2023
1 parent eef3aa4 commit f2d14b1
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 8 deletions.
8 changes: 8 additions & 0 deletions Calendr/Calendar/CalendarCellView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CalendarCellView: NSView {
private let viewModel: Observable<CalendarCellViewModel>
private let hoverObserver: AnyObserver<Date?>
private let clickObserver: AnyObserver<Date>
private let doubleClickObserver: AnyObserver<Date>
private let calendarScaling: Observable<Double>

private let label = Label()
Expand All @@ -25,12 +26,14 @@ class CalendarCellView: NSView {
viewModel: Observable<CalendarCellViewModel>,
hoverObserver: AnyObserver<Date?>,
clickObserver: AnyObserver<Date>,
doubleClickObserver: AnyObserver<Date>,
calendarScaling: Observable<Double>
) {

self.viewModel = viewModel
self.hoverObserver = hoverObserver
self.clickObserver = clickObserver
self.doubleClickObserver = doubleClickObserver
self.calendarScaling = calendarScaling

super.init(frame: .zero)
Expand Down Expand Up @@ -143,6 +146,11 @@ class CalendarCellView: NSView {
.bind(to: clickObserver)
.disposed(by: disposeBag)

rx.doubleClick
.withLatestFrom(viewModel.map(\.date))
.bind(to: doubleClickObserver)
.disposed(by: disposeBag)

rx.mouseEntered
.withLatestFrom(viewModel.map(\.date))
.bind(to: hoverObserver)
Expand Down
6 changes: 5 additions & 1 deletion Calendr/Calendar/CalendarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ class CalendarView: NSView {
private let viewModel: CalendarViewModel
private let hoverObserver: AnyObserver<Date?>
private let clickObserver: AnyObserver<Date>
private let doubleClickObserver: AnyObserver<Date>

private let gridView = NSGridView(numberOfColumns: 8, rows: 7)

init(
viewModel: CalendarViewModel,
hoverObserver: AnyObserver<Date?>,
clickObserver: AnyObserver<Date>
clickObserver: AnyObserver<Date>,
doubleClickObserver: AnyObserver<Date>
) {

self.viewModel = viewModel
self.hoverObserver = hoverObserver
self.clickObserver = clickObserver
self.doubleClickObserver = doubleClickObserver

super.init(frame: .zero)

Expand Down Expand Up @@ -145,6 +148,7 @@ class CalendarView: NSView {
viewModel: cellViewModel,
hoverObserver: hoverObserver,
clickObserver: clickObserver,
doubleClickObserver: doubleClickObserver,
calendarScaling: viewModel.calendarScaling
)
gridView.cell(atColumnIndex: 1 + day % 7, rowIndex: 1 + day / 7).contentView = cellView
Expand Down
4 changes: 4 additions & 0 deletions Calendr/Config/Calendr.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
<true/>
<key>com.apple.security.personal-information.calendars</key>
<true/>
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
<string>com.apple.ical</string>
</array>
</dict>
</plist>
2 changes: 2 additions & 0 deletions Calendr/Config/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@
<string>NSApplication</string>
<key>NSRemindersUsageDescription</key>
<string>Calendr needs access to display your reminders.</string>
<key>NSAppleEventsUsageDescription</key>
<string>Calendr needs access to open Calendar app at the selected date.</string>
</dict>
</plist>
1 change: 1 addition & 0 deletions Calendr/Extensions/NSGestureRecognizer+Rx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ private class GestureProxy {
extension Reactive where Base: NSView {

var click: Observable<Void> { click { _ in } }
var doubleClick: Observable<Void> { click { $0.numberOfClicksRequired = 2 } }

func click<T: NSClickGestureRecognizer> (_ configure: @escaping (T) -> Void) -> Observable<Void> {
gesture(configure)
Expand Down
66 changes: 60 additions & 6 deletions Calendr/Main/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class MainViewController: NSViewController, NSPopoverDelegate {
private let disposeBag = DisposeBag()
private var popoverDisposeBag = DisposeBag()
private let dateClick = PublishSubject<Date>()
private let dateDoubleClick = PublishSubject<Date>()
private let initialDate: BehaviorSubject<Date>
private let selectedDate = PublishSubject<Date>()
private let isShowingDetails = BehaviorSubject<Bool>(value: false)
Expand Down Expand Up @@ -127,7 +128,8 @@ class MainViewController: NSViewController, NSPopoverDelegate {
calendarView = CalendarView(
viewModel: calendarViewModel,
hoverObserver: hoverObserver,
clickObserver: dateClick.asObserver()
clickObserver: dateClick.asObserver(),
doubleClickObserver: dateDoubleClick.asObserver()
)

let eventListEventsObservable = calendarViewModel.focusedDateEventsObservable
Expand Down Expand Up @@ -317,12 +319,20 @@ class MainViewController: NSViewController, NSPopoverDelegate {
}
.disposed(by: disposeBag)

calendarBtn.rx.tap.bind { [workspace] in
if let appUrl = workspace.urlForApplication(toOpen: URL(string: "webcal://")!) {
workspace.open(appUrl)
dateDoubleClick
.observe(on: ConcurrentDispatchQueueScheduler(qos: .userInteractive))
.bind { [weak self] date in
self?.openCalendar(at: date, mode: .day)
}
}
.disposed(by: disposeBag)
.disposed(by: disposeBag)

calendarBtn.rx.tap
.withLatestFrom(selectedDate)
.observe(on: ConcurrentDispatchQueueScheduler(qos: .userInteractive))
.bind { [weak self] date in
self?.openCalendar(at: date, mode: .month)
}
.disposed(by: disposeBag)

searchInput.rx.text
.skipNil()
Expand Down Expand Up @@ -651,6 +661,30 @@ class MainViewController: NSViewController, NSPopoverDelegate {

return dateSelector
}

// MARK: - Scripts

private enum CalendarViewMode: String {
case day
case month
}

private func openCalendar(at date: Date, mode: CalendarViewMode) {
do {
let dateString = DateFormatter().with(style: .full).string(from: date)
try runScript("""
tell application "Calendar"
switch view to \(mode) view
view calendar at date ("\(dateString)")
end tell
""")
} catch {
debugPrint("Open Calendar script failed, fallback to workspace method")
if let appUrl = workspace.urlForApplication(toOpen: URL(string: "webcal://")!) {
workspace.open(appUrl)
}
}
}
}

private enum Constants {
Expand All @@ -659,3 +693,23 @@ private enum Constants {
static let margin: CGFloat = 8
}
}

// MARK: - Apple Script

private enum ScriptError: Error {
case source
case compile
case execute
}

private func runScript(_ source: String) throws {
guard let script = NSAppleScript(source: source) else {
throw ScriptError.source
}
guard script.compileAndReturnError(nil) else {
throw ScriptError.compile
}
if script.executeAndReturnError(nil).description.isEmpty {
throw ScriptError.execute
}
}
3 changes: 2 additions & 1 deletion Calendr/Previews/CalendarViewPreview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ struct CalendarViewPreview: PreviewProvider {
notificationCenter: notificationCenter
),
hoverObserver: hovered.asObserver(),
clickObserver: selected.asObserver()
clickObserver: selected.asObserver(),
doubleClickObserver: .dummy()
)
.preview()
.fixedSize()
Expand Down

0 comments on commit f2d14b1

Please sign in to comment.