Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Do Not Disturb #50

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
40 changes: 26 additions & 14 deletions src/Tomighty/Base.lproj/PreferencesWindow.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1421" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="box content view" minToolsVersion="7.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
<capability name="stacking Non-gravity area distributions on NSStackView" minToolsVersion="7.0" minSystemVersion="10.11"/>
Expand All @@ -11,6 +11,7 @@
<customObject id="-2" userLabel="File's Owner" customClass="TYPreferencesWindowController">
<connections>
<outlet property="check_continuous_mode" destination="K00-WD-P1n" id="dew-jz-0dY"/>
<outlet property="check_enable_do_not_disturb_during_pomodoro" destination="hm5-HW-XLi" id="Euw-1g-Jsf"/>
<outlet property="check_play_sound_when_timer_goes_off" destination="4gP-n3-o9H" id="FUX-Fi-uco"/>
<outlet property="check_play_sound_when_timer_starts" destination="UEf-gI-pZ6" id="VdU-XK-1aG"/>
<outlet property="check_play_ticktock_sound_during_break" destination="n8X-6J-yb1" id="fEo-Gf-VN3"/>
Expand All @@ -31,7 +32,7 @@
<window title="Tomighty Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" frameAutosaveName="tomighty.window.preferences" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<rect key="contentRect" x="196" y="240" width="393" height="253"/>
<rect key="screenRect" x="0.0" y="0.0" width="2048" height="1129"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="393" height="253"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
Expand Down Expand Up @@ -267,8 +268,8 @@
<rect key="frame" x="10" y="33" width="347" height="191"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ay4-lu-bRj">
<rect key="frame" x="53" y="80" width="179" height="17"/>
<textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ay4-lu-bRj">
<rect key="frame" x="50" y="64" width="179" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="175" id="dZm-qd-6Yg"/>
</constraints>
Expand All @@ -278,8 +279,8 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box autoresizesSubviews="NO" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="lBK-YY-ePX">
<rect key="frame" x="52" y="13" width="242" height="74"/>
<box autoresizesSubviews="NO" misplaced="YES" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="lBK-YY-ePX">
<rect key="frame" x="49" y="-2" width="242" height="74"/>
<view key="contentView" id="Xg6-Cb-Sav">
<rect key="frame" x="1" y="1" width="240" height="58"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
Expand Down Expand Up @@ -316,8 +317,8 @@
</constraints>
</view>
</box>
<button translatesAutoresizingMaskIntoConstraints="NO" id="UEf-gI-pZ6">
<rect key="frame" x="48" y="154" width="227" height="18"/>
<button misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UEf-gI-pZ6">
<rect key="frame" x="50" y="160" width="227" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="223" id="OBn-h1-2ac"/>
<constraint firstAttribute="height" constant="14" id="OUQ-u1-yKM"/>
Expand All @@ -330,8 +331,8 @@
<action selector="save_play_sound_when_timer_starts:" target="-2" id="R6Y-Rf-af0"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="4gP-n3-o9H">
<rect key="frame" x="48" y="134" width="244" height="18"/>
<button misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4gP-n3-o9H">
<rect key="frame" x="50" y="140" width="244" height="18"/>
<constraints>
<constraint firstAttribute="height" constant="14" id="Zw4-ug-gct"/>
</constraints>
Expand All @@ -343,8 +344,8 @@
<action selector="save_play_sound_when_timer_goes_off:" target="-2" id="DmH-Qw-rWX"/>
</connections>
</button>
<button translatesAutoresizingMaskIntoConstraints="NO" id="Nlo-52-gcU">
<rect key="frame" x="48" y="114" width="251" height="18"/>
<button misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Nlo-52-gcU">
<rect key="frame" x="50" y="120" width="251" height="18"/>
<buttonCell key="cell" type="check" title="Show notifications when timers go off" bezelStyle="regularSquare" imagePosition="left" inset="2" id="Bzh-st-EPg">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -353,6 +354,17 @@
<action selector="save_show_notifications:" target="-2" id="xXF-j5-KHh"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hm5-HW-XLi">
<rect key="frame" x="50" y="94" width="347" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable Do Not Disturb during Pomodoro" bezelStyle="regularSquare" imagePosition="left" inset="2" id="9VL-Kp-dRg">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
<connections>
<action selector="save_enable_do_not_disturb_during_pomodoro:" target="-2" id="I5m-LS-Hh9"/>
</connections>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstItem="4gP-n3-o9H" firstAttribute="top" secondItem="UEf-gI-pZ6" secondAttribute="bottom" constant="6" symbolic="YES" id="7L1-bm-QDu"/>
Expand Down
83 changes: 83 additions & 0 deletions src/Tomighty/Core/Agent/TYUserInterfaceAgent.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,36 @@ - (void)updateAppUiInResponseToEventsFrom:(id <TYEventBus>)eventBus
[eventBus subscribeTo:POMODORO_START subscriber:^(id eventData) {
[ui switchToPomodoroState];
[self dispatchNewNotification:@"Pomodoro started"];

if ([preferences getInt:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
1 * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
turnDoNotDisturbOn();
});

}
}];

[eventBus subscribeTo:POMODORO_COMPLETE subscriber:^(id eventData) {

if ([preferences getInt:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO]) {
turnDoNotDisturbOff();
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
1 * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
[self dispatchNewNotification:@"Pomodoro completed"];
});

}];

[eventBus subscribeTo:TIMER_STOP subscriber:^(id eventData) {
if ([preferences getInt:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO]) {
turnDoNotDisturbOff();
}
[ui switchToIdleState];
}];

Expand Down Expand Up @@ -84,4 +111,60 @@ - (void)updateAppUiInResponseToEventsFrom:(id <TYEventBus>)eventBus
}];
}

///
/// This block of code for turning Do Not Disturb on and off
/// is directly from https://stackoverflow.com/a/36385778/518130
///
void turnDoNotDisturbOn(void)
{
// The trick is to set DND time range from 00:00 (0 minutes) to 23:59 (1439 minutes),
// so it will always be on
CFPreferencesSetValue(CFSTR("dndStart"), (__bridge CFPropertyListRef)(@(0.0f)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("dndEnd"), (__bridge CFPropertyListRef)(@(1440.f)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("doNotDisturb"), (__bridge CFPropertyListRef)(@(YES)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

// Notify all the related daemons that we have changed Do Not Disturb preferences
commitDoNotDisturbChanges();
}


void turnDoNotDisturbOff()
{
CFPreferencesSetValue(CFSTR("dndStart"), NULL,
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("dndEnd"), NULL,
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

CFPreferencesSetValue(CFSTR("doNotDisturb"), (__bridge CFPropertyListRef)(@(NO)),
CFSTR("com.apple.notificationcenterui"),
kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

commitDoNotDisturbChanges();
}

void commitDoNotDisturbChanges(void)
{
/// XXX: I'm using kCFPreferencesCurrentUser placeholder here which means that this code must
/// be run under regular user's account (not root/admin). If you're going to run this code
/// from a privileged helper, use kCFPreferencesAnyUser in order to toggle DND for all users
/// or drop privileges and use kCFPreferencesCurrentUser.
CFPreferencesSynchronize(CFSTR("com.apple.notificationcenterui"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
[[NSDistributedNotificationCenter defaultCenter] postNotificationName: @"com.apple.notificationcenterui.dndprefs_changed"
object: nil userInfo: nil
deliverImmediately: YES];
}



@end
1 change: 1 addition & 0 deletions src/Tomighty/Core/Preferences/TYPreferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern NSString * const PREF_HOTKEY_START;
extern NSString * const PREF_HOTKEY_STOP;
extern NSString * const PREF_CONTINUOUS_MODE;
extern NSString * const PREF_ENABLE_NOTIFICATIONS;
extern NSString * const PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO;

@protocol TYPreferences <NSObject>

Expand Down
3 changes: 3 additions & 0 deletions src/Tomighty/Core/Preferences/TYUserDefaultsPreferences.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
NSString * const PREF_HOTKEY_START = @"org.tomighty.hotkey.start";
NSString * const PREF_HOTKEY_STOP = @"org.tomighty.hotkey.stop";
NSString * const PREF_ENABLE_NOTIFICATIONS = @"org.tomighty.enable_notifications";
NSString * const PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO = @"org.tomighty.enable_do_not_disturb_during_pomodoro";


@implementation TYUserDefaultsPreferences
{
Expand All @@ -51,6 +53,7 @@ - (id)initWith:(id <TYEventBus>)anEventBus
[defaultValues setObject:[NSNumber numberWithInt:true] forKey:PREF_PLAY_TICKTOCK_SOUND_DURING_BREAK];
[defaultValues setObject:[NSNumber numberWithInt:true] forKey:PREF_CONTINUOUS_MODE];
[defaultValues setObject:[NSNumber numberWithInt:false] forKey:PREF_ENABLE_NOTIFICATIONS];
[defaultValues setObject:[NSNumber numberWithInt:false] forKey:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO];
[defaultValues setObject:[NSNumber numberWithInt:PREF_STATUS_ICON_TIME_FORMAT_NONE] forKey:PREF_STATUS_ICON_TIME_FORMAT];
[defaultValues setObject:@"^⌘P" forKey:PREF_HOTKEY_START];
[defaultValues setObject:@"^⌘S" forKey:PREF_HOTKEY_STOP];
Expand Down
2 changes: 2 additions & 0 deletions src/Tomighty/Core/UI/TYPreferencesWindowController.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
@property (weak) IBOutlet NSButton *check_play_ticktock_sound_during_pomodoro;
@property (weak) IBOutlet NSButton *check_play_ticktock_sound_during_break;
@property (weak) IBOutlet NSButton *check_show_notifications;
@property (weak) IBOutlet NSButton *check_enable_do_not_disturb_during_pomodoro;
@property (weak) IBOutlet NSButton *check_continuous_mode;
@property (weak) IBOutlet NSPopUpButton *popup_status_icon_time_format;
@property (weak) IBOutlet TYHotkeyControl *text_hotkey_start;
Expand All @@ -40,5 +41,6 @@
- (IBAction)save_hotkey_start:(id)sender;
- (IBAction)save_hotkey_stop:(id)sender;
- (IBAction)save_show_notifications:(id)sender;
- (IBAction)save_enable_do_not_disturb_during_pomodoro:(id)sender;

@end
5 changes: 5 additions & 0 deletions src/Tomighty/Core/UI/TYPreferencesWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ - (void)windowDidLoad
[self.check_play_ticktock_sound_during_pomodoro setState:[preferences getInt:PREF_PLAY_TICKTOCK_SOUND_DURING_POMODORO]];
[self.check_play_ticktock_sound_during_break setState:[preferences getInt:PREF_PLAY_TICKTOCK_SOUND_DURING_BREAK]];
[self.check_show_notifications setState:[preferences getInt:PREF_ENABLE_NOTIFICATIONS]];
[self.check_enable_do_not_disturb_during_pomodoro setState:[preferences getInt:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO]];
[self.check_continuous_mode setState:[preferences getInt:PREF_CONTINUOUS_MODE]];
[self.popup_status_icon_time_format selectItemAtIndex:[preferences getInt:PREF_STATUS_ICON_TIME_FORMAT]];
[self.text_hotkey_start
Expand Down Expand Up @@ -90,6 +91,10 @@ - (IBAction)save_show_notifications:(id)sender {
[preferences setInt:PREF_ENABLE_NOTIFICATIONS value:(int)[self.check_show_notifications state]];
}

- (IBAction)save_enable_do_not_disturb_during_pomodoro:(id)sender {
[preferences setInt:PREF_ENABLE_DO_NOT_DISTURB_DURING_POMODORO value:(int)[self.check_enable_do_not_disturb_during_pomodoro state]];
}

- (IBAction)save_continuous_mode:(id)sender {
[preferences setInt:PREF_CONTINUOUS_MODE value:(int)[self.check_continuous_mode state]];
}
Expand Down