|
|
@@ -265,6 +265,10 @@ class ViewController: NSViewController {
|
|
|
// Reserved for future titlebar control actions.
|
|
|
}
|
|
|
|
|
|
+ @objc private func refreshMeetingsTapped() {
|
|
|
+ triggerMeetingsRefresh(force: true)
|
|
|
+ }
|
|
|
+
|
|
|
private func startMeetingsAutoRefresh() {
|
|
|
meetingsRefreshTimer?.invalidate()
|
|
|
// Poll Zoom meetings periodically so newly scheduled meetings appear automatically.
|
|
|
@@ -1079,15 +1083,24 @@ class ViewController: NSViewController {
|
|
|
// Keep meeting cards pinned to the top of the scroll content.
|
|
|
meetingsStack.setContentHuggingPriority(.required, for: .vertical)
|
|
|
meetingsStack.setContentCompressionResistancePriority(.required, for: .vertical)
|
|
|
- let openRecordings = NSButton(title: "Open recordings", target: nil, action: nil)
|
|
|
- openRecordings.isBordered = false
|
|
|
- openRecordings.font = .systemFont(ofSize: 14, weight: .semibold)
|
|
|
- openRecordings.contentTintColor = primaryText
|
|
|
- openRecordings.wantsLayer = true
|
|
|
- openRecordings.layer?.backgroundColor = NSColor(calibratedRed: 36 / 255, green: 39 / 255, blue: 46 / 255, alpha: 1).cgColor
|
|
|
- openRecordings.layer?.cornerRadius = 11
|
|
|
- openRecordings.layer?.borderWidth = 1
|
|
|
- openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
|
+ let refreshMeetingsButton = NSButton(title: "Refresh", target: self, action: #selector(refreshMeetingsTapped))
|
|
|
+ refreshMeetingsButton.isBordered = false
|
|
|
+ refreshMeetingsButton.font = .systemFont(ofSize: 14, weight: .semibold)
|
|
|
+ refreshMeetingsButton.contentTintColor = primaryText
|
|
|
+ let refreshSymbolConfig = NSImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
|
|
|
+ if let base = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh"),
|
|
|
+ let image = base.withSymbolConfiguration(refreshSymbolConfig) {
|
|
|
+ image.isTemplate = true
|
|
|
+ refreshMeetingsButton.image = image
|
|
|
+ refreshMeetingsButton.imagePosition = .imageLeading
|
|
|
+ refreshMeetingsButton.imageHugsTitle = true
|
|
|
+ refreshMeetingsButton.imageScaling = .scaleNone
|
|
|
+ }
|
|
|
+ refreshMeetingsButton.wantsLayer = true
|
|
|
+ refreshMeetingsButton.layer?.backgroundColor = NSColor(calibratedRed: 36 / 255, green: 39 / 255, blue: 46 / 255, alpha: 1).cgColor
|
|
|
+ refreshMeetingsButton.layer?.cornerRadius = 11
|
|
|
+ refreshMeetingsButton.layer?.borderWidth = 1
|
|
|
+ refreshMeetingsButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
|
|
|
|
let contentColumn = NSView()
|
|
|
contentColumn.translatesAutoresizingMaskIntoConstraints = false
|
|
|
@@ -1107,7 +1120,7 @@ class ViewController: NSViewController {
|
|
|
[searchIcon, searchField, searchHintLabel].forEach {
|
|
|
searchPill.addSubview($0)
|
|
|
}
|
|
|
- [welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, meetingsDayNav, noMeeting, meetingsScrollView, openRecordings].forEach {
|
|
|
+ [welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, meetingsDayNav, noMeeting, meetingsScrollView, refreshMeetingsButton].forEach {
|
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
|
contentColumn.addSubview($0)
|
|
|
}
|
|
|
@@ -1199,7 +1212,7 @@ class ViewController: NSViewController {
|
|
|
meetingsScrollView.topAnchor.constraint(equalTo: panelHeader.bottomAnchor, constant: 12),
|
|
|
meetingsScrollView.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
|
|
meetingsScrollView.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
|
|
- meetingsScrollView.bottomAnchor.constraint(equalTo: openRecordings.topAnchor, constant: -14),
|
|
|
+ meetingsScrollView.bottomAnchor.constraint(equalTo: refreshMeetingsButton.topAnchor, constant: -14),
|
|
|
|
|
|
meetingsDocument.widthAnchor.constraint(equalTo: meetingsScrollView.contentView.widthAnchor),
|
|
|
meetingsStack.topAnchor.constraint(equalTo: meetingsDocument.topAnchor),
|
|
|
@@ -1207,10 +1220,10 @@ class ViewController: NSViewController {
|
|
|
meetingsStack.trailingAnchor.constraint(equalTo: meetingsDocument.trailingAnchor),
|
|
|
meetingsStack.bottomAnchor.constraint(lessThanOrEqualTo: meetingsDocument.bottomAnchor),
|
|
|
|
|
|
- openRecordings.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
|
|
- openRecordings.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
|
|
- openRecordings.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
|
|
|
- openRecordings.heightAnchor.constraint(equalToConstant: 40)
|
|
|
+ refreshMeetingsButton.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
|
|
+ refreshMeetingsButton.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
|
|
+ refreshMeetingsButton.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
|
|
|
+ refreshMeetingsButton.heightAnchor.constraint(equalToConstant: 40)
|
|
|
])
|
|
|
|
|
|
timeLabel = timeTitle
|