|
@@ -53,6 +53,7 @@ class ViewController: NSViewController {
|
|
|
private weak var meetingsPrevDayButton: NSButton?
|
|
private weak var meetingsPrevDayButton: NSButton?
|
|
|
private weak var meetingsNextDayButton: NSButton?
|
|
private weak var meetingsNextDayButton: NSButton?
|
|
|
private weak var meetingsTodayButton: NSButton?
|
|
private weak var meetingsTodayButton: NSButton?
|
|
|
|
|
+ private weak var refreshMeetingsButton: NSButton?
|
|
|
private weak var homeSearchField: NSTextField?
|
|
private weak var homeSearchField: NSTextField?
|
|
|
private weak var homeSearchPill: NSView?
|
|
private weak var homeSearchPill: NSView?
|
|
|
private var allScheduledMeetings: [ScheduledMeeting] = []
|
|
private var allScheduledMeetings: [ScheduledMeeting] = []
|
|
@@ -266,9 +267,37 @@ class ViewController: NSViewController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@objc private func refreshMeetingsTapped() {
|
|
@objc private func refreshMeetingsTapped() {
|
|
|
|
|
+ Task { @MainActor in
|
|
|
|
|
+ self.animateMeetingsRefresh()
|
|
|
|
|
+ self.setMeetingsLoadingUI(true)
|
|
|
|
|
+ }
|
|
|
triggerMeetingsRefresh(force: true)
|
|
triggerMeetingsRefresh(force: true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @MainActor
|
|
|
|
|
+ private func setMeetingsLoadingUI(_ loading: Bool) {
|
|
|
|
|
+ refreshMeetingsButton?.isEnabled = loading == false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @MainActor
|
|
|
|
|
+ private func animateMeetingsRefresh() {
|
|
|
|
|
+ guard let stack = meetingsListStack, stack.arrangedSubviews.isEmpty == false else { return }
|
|
|
|
|
+ let views = stack.arrangedSubviews
|
|
|
|
|
+ let dimmed: CGFloat = 0.86
|
|
|
|
|
+
|
|
|
|
|
+ NSAnimationContext.runAnimationGroup { context in
|
|
|
|
|
+ context.duration = 0.07
|
|
|
|
|
+ context.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
|
|
|
+ views.forEach { $0.animator().alphaValue = dimmed }
|
|
|
|
|
+ } completionHandler: {
|
|
|
|
|
+ NSAnimationContext.runAnimationGroup { context in
|
|
|
|
|
+ context.duration = 0.08
|
|
|
|
|
+ context.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
|
|
|
+ views.forEach { $0.animator().alphaValue = 1.0 }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private func startMeetingsAutoRefresh() {
|
|
private func startMeetingsAutoRefresh() {
|
|
|
meetingsRefreshTimer?.invalidate()
|
|
meetingsRefreshTimer?.invalidate()
|
|
|
// Poll Zoom meetings periodically so newly scheduled meetings appear automatically.
|
|
// Poll Zoom meetings periodically so newly scheduled meetings appear automatically.
|
|
@@ -550,7 +579,15 @@ class ViewController: NSViewController {
|
|
|
private func loadScheduledMeetings() async {
|
|
private func loadScheduledMeetings() async {
|
|
|
if isLoadingMeetings { return }
|
|
if isLoadingMeetings { return }
|
|
|
isLoadingMeetings = true
|
|
isLoadingMeetings = true
|
|
|
- defer { isLoadingMeetings = false }
|
|
|
|
|
|
|
+ defer {
|
|
|
|
|
+ isLoadingMeetings = false
|
|
|
|
|
+ Task { @MainActor in
|
|
|
|
|
+ self.setMeetingsLoadingUI(false)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ await MainActor.run {
|
|
|
|
|
+ self.setMeetingsLoadingUI(true)
|
|
|
|
|
+ }
|
|
|
do {
|
|
do {
|
|
|
let zoomToken = try await zoomOAuth.validAccessToken(presentingWindow: view.window)
|
|
let zoomToken = try await zoomOAuth.validAccessToken(presentingWindow: view.window)
|
|
|
let zoomMeetings = try await fetchZoomScheduledMeetings(accessToken: zoomToken)
|
|
let zoomMeetings = try await fetchZoomScheduledMeetings(accessToken: zoomToken)
|
|
@@ -1101,6 +1138,7 @@ class ViewController: NSViewController {
|
|
|
refreshMeetingsButton.layer?.cornerRadius = 11
|
|
refreshMeetingsButton.layer?.cornerRadius = 11
|
|
|
refreshMeetingsButton.layer?.borderWidth = 1
|
|
refreshMeetingsButton.layer?.borderWidth = 1
|
|
|
refreshMeetingsButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
refreshMeetingsButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
|
|
|
+ self.refreshMeetingsButton = refreshMeetingsButton
|
|
|
|
|
|
|
|
let contentColumn = NSView()
|
|
let contentColumn = NSView()
|
|
|
contentColumn.translatesAutoresizingMaskIntoConstraints = false
|
|
contentColumn.translatesAutoresizingMaskIntoConstraints = false
|
|
@@ -1193,7 +1231,7 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 18),
|
|
panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 18),
|
|
|
panel.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
panel.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
|
- panel.widthAnchor.constraint(equalToConstant: 640),
|
|
|
|
|
|
|
+ panel.widthAnchor.constraint(equalToConstant: 610),
|
|
|
panel.leadingAnchor.constraint(greaterThanOrEqualTo: contentColumn.leadingAnchor, constant: 6),
|
|
panel.leadingAnchor.constraint(greaterThanOrEqualTo: contentColumn.leadingAnchor, constant: 6),
|
|
|
panel.trailingAnchor.constraint(lessThanOrEqualTo: contentColumn.trailingAnchor, constant: -6),
|
|
panel.trailingAnchor.constraint(lessThanOrEqualTo: contentColumn.trailingAnchor, constant: -6),
|
|
|
panel.heightAnchor.constraint(greaterThanOrEqualToConstant: 280),
|
|
panel.heightAnchor.constraint(greaterThanOrEqualToConstant: 280),
|