Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ For next releases info look here: <https://github.com/leits/MeetingBar/releases>
* Fix readability of the statusbar text in multi-screen setups (#354)
* Detect hidden menubar icon (#429)
* Added feature to snooze the notification
* Meetings without a meeting links can now be displayed in fullscreen notifications. A new setting has been added to control that behaviour.
* Preferences changes:
* Added a section "Notification"
* Added a new parameter related to full screen notification that you can disable to receives notification for meetings without links (Only for meetings with a link)
* In the fullscreen notification, don't show the Meeting Link button if there is no meeting link.


* Fix crash due to meeting attendees without an email address (#460)

## Version 3.10.0
Expand Down
15 changes: 6 additions & 9 deletions MeetingBar/ActionsOnEventStart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,12 @@ class ActionsOnEventStart: NSObject {
}
//

if let nextEvent = getNextEvent(events: app.statusBarItem.events, linkRequired: true) {
let now = Date()
let fullscreenNotificationMeetingLinkOnly = Defaults[.fullscreenNotificationMeetingLinkOnly]

if let nextEvent = getNextEvent(events: app.statusBarItem.events, linkRequired: fullscreenNotificationMeetingLinkOnly) {
let now = Date()
let startEndRange = nextEvent.startDate ... nextEvent.endDate

let timeInterval = nextEvent.startDate.timeIntervalSince(now)

let allDayCandidate = nextEvent.isAllDay && startEndRange.contains(now)

/*
Expand All @@ -65,9 +64,9 @@ class ActionsOnEventStart: NSObject {
* ------------------------
*/
let actionTimeForFullscreenNotification = Double(Defaults[.fullscreenNotificationTime].rawValue)
let nonAlldayCandidateForFullscreenNotification = (timeInterval > -15 && timeInterval < actionTimeForFullscreenNotification)
let nonAllDayCandidateForFullscreenNotification = (timeInterval > -15 && timeInterval < actionTimeForFullscreenNotification)

Check warning

Code scanning / Tailor (reported by Codacy)

Initializer expression should not be enclosed within parentheses Warning

Initializer expression should not be enclosed within parentheses

if fullscreenNotificationActive && (nonAlldayCandidateForFullscreenNotification || allDayCandidate) {
if fullscreenNotificationActive && (nonAllDayCandidateForFullscreenNotification || allDayCandidate) {
var events = Defaults[.processedEventsForFullscreenNotification]

let matchedEvent = events.first { $0.id == nextEvent.ID }
Expand All @@ -76,9 +75,7 @@ class ActionsOnEventStart: NSObject {
// we will remove the the current event from the scheduled events, so that we can run the script again ->
// this is an edge case when the event was already notified for, but scheduled for a later time.
if matchedEvent == nil || matchedEvent?.lastModifiedDate != nextEvent.lastModifiedDate {
if nextEvent.meetingLink != nil {
app.openFullscreenNotificationWindow(event: nextEvent)
}
app.openFullscreenNotificationWindow(event: nextEvent)

// update the executed events
if matchedEvent != nil {
Expand Down
1 change: 1 addition & 0 deletions MeetingBar/Extensions/DefaultsKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extension Defaults.Keys {
static let endOfEventNotificationTime = Key<TimeBeforeEventEnd>("endOfEventNotificationTime", default: .atEnd)

static let fullscreenNotification = Key<Bool>("fullscreenNotification", default: false)
static let fullscreenNotificationMeetingLinkOnly = Key<Bool>("fullscreenNotificationMeetingLinkOnly", default: false)
static let fullscreenNotificationTime = Key<TimeBeforeEvent>("fullscreenNotificationTime", default: .atStart)
static let processedEventsForFullscreenNotification = Key<[ProcessedEvent]>("processedEventsForFullscreenNotification", default: [])

Expand Down
6 changes: 3 additions & 3 deletions MeetingBar/Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,17 +254,17 @@ func openLinkFromClipboard() {
}
}

func generateFakeEvent() -> MBEvent {
func generateFakeEvent(includeMeetingLink: Bool) -> MBEvent {
let calendar = MBCalendar(title: "Fake calendar", ID: "fake_cal", source: nil, email: nil, color: .black)

let event = MBEvent(
ID: "test_event",
lastModifiedDate: nil,
title: "Test event",
title: includeMeetingLink ? "Test Event (with Meeting link)" : "Test Event (without Meeting link)",
status: .confirmed,
notes: nil,
location: nil,
url: URL(string: "https://zoom.us/j/5551112222")!,
url: includeMeetingLink ? URL(string: "https://zoom.us/j/5551112222")! : nil,
organizer: nil,
startDate: Calendar.current.date(byAdding: .minute, value: 3, to: Date())!,
endDate: Calendar.current.date(byAdding: .minute, value: 33, to: Date())!,
Expand Down
2 changes: 0 additions & 2 deletions MeetingBar/MeetingBar.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.usernotifications.time-sensitive</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,10 @@

// MARK: - Shared

"preferences_notifications_section_title" = "Notifications";
"shared_send_notification_toggle" = "Send a system notification";
"shared_fullscreen_notification_toggle" = "Show a fullscreen notification";
"shared_fullscreen_notification_meeting_link_only_toggle" = "Only for meetings with a link";
"shared_send_notification_no_alert_style_tip" = "⚠️ Your macOS notification settings for MeetingBar are not set to alert. Do so if you want persistent notifications.";
"shared_send_notification_disabled_tip" = "⚠️ Your macOS notification settings for MeetingBar are off. Turn on notifications in the macOS system settings to keep track of meetings.";
"shared_automatic_event_join_toggle" = "Automatically join next event meeting";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@

// MARK: - Shared

"preferences_notifications_section_title" = "Notifications";
"shared_send_notification_toggle" = "Envoyer une notification système";
"shared_fullscreen_notification_toggle" = "Affiche une notification plein écran";
"shared_fullscreen_notification_meeting_link_only_toggle" = "Uniquement pour les évènement avec des liens de réunion";
"access_screen_access_granted_click_ok_title" = "Cliquez sur « OK » dans la fenêtre popup de macOS.";
"access_screen_access_screen_access_denied_go_to_title" = "Allez dans les";
"access_screen_access_denied_checkbox_title" = "et sélectionnez une case à cocher près de MeetingBar.";
Expand Down
5 changes: 5 additions & 0 deletions MeetingBar/Views/Changelog/Changelog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ struct ChangelogView: View {
Text("🌍 Translation into Slovak and Dutch")
}
}
if compareVersions("4.10.0", lastRevisedVersionInChangelog) {
Section(header: Text("Version 4.10")) {
Text("🖥️ Meetings without a meeting links can now be displayed in fullscreen notifications.")
}
}
}
}.listStyle(SidebarListStyle())
Button("general_close".loco(), action: close)
Expand Down
21 changes: 13 additions & 8 deletions MeetingBar/Views/FullscreenNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,33 @@ struct FullscreenNotification: View {
Rectangle.semiOpaqueWindow()
VStack {
HStack {
Image(nsImage: getIconForMeetingService(event.meetingLink?.service))
.resizable().frame(width: 25, height: 25)
if event.meetingLink != nil {
Image(nsImage: getIconForMeetingService(event.meetingLink?.service))
.resizable().frame(width: 25, height: 25)
}
Text(event.title).font(.title)
}
VStack(spacing: 10) {
Text(getEventDateString(event))
}.padding(15)

// display location of the event, very useful if you
// have a lot of meetings in a building with a lot of meeting rooms
if let location = event.location {
VStack(spacing: 10) {
Text(location)
}.padding(15)
}

HStack(spacing: 30) {
Button(action: dismiss) {
Text("general_close".loco()).padding(.vertical, 5).padding(.horizontal, 20)
}
Button(action: joinEvent) {
Text("notifications_meetingbar_join_event_action".loco()).padding(.vertical, 5).padding(.horizontal, 25)
}.background(Color.accentColor).cornerRadius(5)
if event.meetingLink != nil {
Button(action: joinEvent) {
Text("notifications_meetingbar_join_event_action".loco()).padding(.vertical, 5).padding(.horizontal, 25)
}.background(Color.accentColor).cornerRadius(5)
}
}
}
}
Expand Down Expand Up @@ -81,5 +85,6 @@ struct VisualEffect: NSViewRepresentable {
}

#Preview {
FullscreenNotification(event: generateFakeEvent(), window: nil)
FullscreenNotification(event: generateFakeEvent(includeMeetingLink: true), window: nil)
FullscreenNotification(event: generateFakeEvent(includeMeetingLink: false), window: nil)
}
38 changes: 25 additions & 13 deletions MeetingBar/Views/Preferences/GeneralTab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ struct GeneralTab: View {
Section {
LaunchAtLoginANDPreferredLanguagePicker()
Divider()
JoinEventNotificationPicker()
FullscreenNotificationPicker()
NotificationsSection()
Divider()
}
Section {
Expand All @@ -30,25 +29,38 @@ struct GeneralTab: View {
}
}

struct NotificationsSection: View {
var body: some View {
Text("preferences_notifications_section_title".loco()).font(.headline).bold()
Section {
JoinEventNotificationPicker()
FullscreenNotificationPicker()
}.padding(.leading, 30)
}
}

struct ShortcutsSection: View {
@State var showingModal = false

var body: some View {
HStack {
Text("preferences_general_shortcut_create_meeting".loco())
KeyboardShortcuts.Recorder(for: .createMeetingShortcut)
Text("preferences_general_option_shortcuts".loco()).font(.headline).bold()
Section {
HStack {
Text("preferences_general_shortcut_create_meeting".loco())
KeyboardShortcuts.Recorder(for: .createMeetingShortcut)

Text("preferences_general_shortcut_join_next".loco())
KeyboardShortcuts.Recorder(for: .joinEventShortcut)
Text("preferences_general_shortcut_join_next".loco())
KeyboardShortcuts.Recorder(for: .joinEventShortcut)

Spacer()
Spacer()

Button(action: { self.showingModal.toggle() }) {
Text("preferences_general_all_shortcut".loco())
}.sheet(isPresented: $showingModal) {
ShortcutsModal()
Button(action: { self.showingModal.toggle() }) {
Text("preferences_general_all_shortcut".loco())
}.sheet(isPresented: $showingModal) {
ShortcutsModal()
}
}
}
}.padding(.leading, 30)
}
}

Expand Down
36 changes: 22 additions & 14 deletions MeetingBar/Views/Shared.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,23 @@ struct AutomaticEventJoinPicker: View {

struct FullscreenNotificationPicker: View {
@Default(.fullscreenNotification) var fullscreenNotification
@Default(.fullscreenNotificationMeetingLinkOnly) var fullscreenNotificationMeetingLinkOnly
@Default(.fullscreenNotificationTime) var fullscreenNotificationTime

var body: some View {
HStack {
Toggle("shared_fullscreen_notification_toggle".loco(), isOn: $fullscreenNotification)
Picker("", selection: $fullscreenNotificationTime) {
Text("general_when_event_starts".loco()).tag(TimeBeforeEvent.atStart)
Text("general_one_minute_before".loco()).tag(TimeBeforeEvent.minuteBefore)
Text("general_three_minute_before".loco()).tag(TimeBeforeEvent.threeMinuteBefore)
Text("general_five_minute_before".loco()).tag(TimeBeforeEvent.fiveMinuteBefore)
}.frame(width: 220, alignment: .leading).labelsHidden().disabled(!fullscreenNotification)
VStack(alignment: .leading, spacing: 15) {
HStack {
Toggle("shared_fullscreen_notification_toggle".loco(), isOn: $fullscreenNotification)
Picker("", selection: $fullscreenNotificationTime) {
Text("general_when_event_starts".loco()).tag(TimeBeforeEvent.atStart)
Text("general_one_minute_before".loco()).tag(TimeBeforeEvent.minuteBefore)
Text("general_three_minute_before".loco()).tag(TimeBeforeEvent.threeMinuteBefore)
Text("general_five_minute_before".loco()).tag(TimeBeforeEvent.fiveMinuteBefore)
}.frame(width: 220, alignment: .leading).labelsHidden().disabled(!fullscreenNotification)
}
Section {
Toggle("shared_fullscreen_notification_meeting_link_only_toggle".loco(), isOn: $fullscreenNotificationMeetingLinkOnly).disabled(!fullscreenNotification)
}.padding(.leading, 30)
}
}
}
Expand All @@ -74,13 +80,15 @@ struct JoinEventNotificationPicker: View {
}.frame(width: 220, alignment: .leading).labelsHidden().disabled(!joinEventNotification)
}

if noAlertStyle, !disabled, joinEventNotification {
Text("shared_send_notification_no_alert_style_tip".loco()).foregroundColor(.gray).font(.system(size: 12))
}
Section {
if noAlertStyle, !disabled, joinEventNotification {
Text("shared_send_notification_no_alert_style_tip".loco()).foregroundColor(.gray).font(.system(size: 12))
}

if disabled, joinEventNotification {
Text("shared_send_notification_disabled_tip".loco()).foregroundColor(.gray).font(.system(size: 12))
}
if disabled, joinEventNotification {
Text("shared_send_notification_disabled_tip".loco()).foregroundColor(.gray).font(.system(size: 12))
}
}.padding(.leading, 25)
}
}
struct endEventNotificationPicker: View {
Expand Down