├── .gitignore ├── .vscode └── tasks.json ├── LICENSE.md ├── Makefile ├── README.md ├── SleeperCore.plist ├── SleeperCoreLegacy.plist ├── SleeperUI.plist ├── assets ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── banner.png ├── banner.psd ├── icon.png ├── icon.psd ├── noun_Alarm Clock_2891329.png ├── noun_Arrow Share_1624620.png ├── noun_Night_602944.png └── open_in-highres.png ├── build_release.sh ├── common ├── SLAlarmPrefs.h ├── SLAlarmPrefs.m ├── SLAutoSetManager.h ├── SLAutoSetManager.m ├── SLCommonHeaders.h ├── SLCompatibilityHelper.h ├── SLCompatibilityHelper.m ├── SLLocalizedStrings.h ├── SLPrefsManager.h ├── SLPrefsManager.m ├── SLSkipAlarmAlertItem.h ├── SLSkipAlarmAlertItem.xm └── SLSpringBoard.x ├── control ├── control_BigBoss ├── control_Havoc ├── core ├── SLMTAlarm.x ├── SLMTAlarmManager.x ├── SLMTAlarmStorage.x ├── SLMTUserNotificationCenter.x ├── SLSBDashBoardLockScreenEnvironment.x └── SLSBLockScreenViewControllerBase.x ├── core_legacy ├── SLAlarmManager.x ├── SLSBApplication.x ├── SLSBClockDataProvider.x ├── SLSBLockScreenManager.x ├── SLSBLockScreenViewController.x ├── SLSBLockScreenViewControllerBase.x ├── SLUNLocalNotificationClient.x └── SLUNSNotificationSchedulingService.x ├── holiday_gen.py ├── layout ├── DEBIAN │ ├── postinst │ └── postrm └── Library │ └── Application Support │ └── Sleeper.bundle │ ├── ar.lproj │ └── Localizable.strings │ ├── ar_holidays.plist │ ├── at_holidays.plist │ ├── au_holidays.plist │ ├── aw_holidays.plist │ ├── be_holidays.plist │ ├── bg_holidays.plist │ ├── br_holidays.plist │ ├── by_holidays.plist │ ├── ca.lproj │ └── Localizable.strings │ ├── ca_holidays.plist │ ├── ch_holidays.plist │ ├── checkmark.png │ ├── checkmark@2x.png │ ├── checkmark@3x.png │ ├── cn_holidays.plist │ ├── co_holidays.plist │ ├── cs.lproj │ └── Localizable.strings │ ├── cz_holidays.plist │ ├── da.lproj │ └── Localizable.strings │ ├── de.lproj │ └── Localizable.strings │ ├── de_holidays.plist │ ├── dk_holidays.plist │ ├── do_holidays.plist │ ├── ee_holidays.plist │ ├── eg_holidays.plist │ ├── el.lproj │ └── Localizable.strings │ ├── en.lproj │ └── Localizable.strings │ ├── es.lproj │ └── Localizable.strings │ ├── es_holidays.plist │ ├── fi.lproj │ └── Localizable.strings │ ├── fi_holidays.plist │ ├── fr.lproj │ └── Localizable.strings │ ├── fra_holidays.plist │ ├── he.lproj │ └── Localizable.strings │ ├── hk_holidays.plist │ ├── hr_holidays.plist │ ├── hu.lproj │ └── Localizable.strings │ ├── hu_holidays.plist │ ├── icon.png │ ├── id.lproj │ └── Localizable.strings │ ├── ie_holidays.plist │ ├── il_holidays.plist │ ├── ind_holidays.plist │ ├── is_holidays.plist │ ├── it.lproj │ └── Localizable.strings │ ├── it_holidays.plist │ ├── ja.lproj │ └── Localizable.strings │ ├── jp_holidays.plist │ ├── ke_holidays.plist │ ├── ko.lproj │ └── Localizable.strings │ ├── kr_holidays.plist │ ├── la.lproj │ └── Localizable.strings │ ├── lt_holidays.plist │ ├── lu_holidays.plist │ ├── ma_holidays.plist │ ├── ms.lproj │ └── Localizable.strings │ ├── mx_holidays.plist │ ├── nb.lproj │ └── Localizable.strings │ ├── ng_holidays.plist │ ├── ni_holidays.plist │ ├── nl.lproj │ └── Localizable.strings │ ├── nl_holidays.plist │ ├── no_holidays.plist │ ├── nz_holidays.plist │ ├── open_in.png │ ├── open_in@2x.png │ ├── open_in@3x.png │ ├── pe_holidays.plist │ ├── pl.lproj │ └── Localizable.strings │ ├── pl_holidays.plist │ ├── pt.lproj │ └── Localizable.strings │ ├── pt_PT.lproj │ └── Localizable.strings │ ├── pt_holidays.plist │ ├── py_holidays.plist │ ├── ro.lproj │ └── Localizable.strings │ ├── rs_holidays.plist │ ├── ru.lproj │ └── Localizable.strings │ ├── ru_holidays.plist │ ├── se_holidays.plist │ ├── sg_holidays.plist │ ├── si_holidays.plist │ ├── sk_holidays.plist │ ├── sv.lproj │ └── Localizable.strings │ ├── tr.lproj │ └── Localizable.strings │ ├── tr_holidays.plist │ ├── tw_holidays.plist │ ├── ua_holidays.plist │ ├── uk_holidays.plist │ ├── us_holidays.plist │ ├── vi.lproj │ └── Localizable.strings │ ├── vn_holidays.plist │ ├── za_holidays.plist │ ├── zh_CN.lproj │ └── Localizable.strings │ └── zh_TW.lproj │ └── Localizable.strings ├── localized_helper.py └── ui ├── SLEditAlarmViewController.xm ├── SLHKSHQuickScheduleOverrideViewController.xm ├── SLMTAAlarmEditViewController.xm ├── SLMTABedtimeOptionsViewController.x ├── SLMTABedtimeViewController.x ├── SLMTASleepDetailViewController.x ├── SLMTASleepOptionsViewController.x ├── SLMTSleepAlarmOptionsController.x ├── SLMTSleepAlarmViewController.x ├── SLUserInterfaceHeaders.h └── custom ├── SLAutoSetOptionsTableViewController.h ├── SLAutoSetOptionsTableViewController.m ├── SLEditDateTimeViewController.h ├── SLEditDateTimeViewController.m ├── SLHolidaySelectionTableViewController.h ├── SLHolidaySelectionTableViewController.m ├── SLPartialModalPresentationController.h ├── SLPartialModalPresentationController.m ├── SLPickerTableViewController.h ├── SLPickerTableViewController.m ├── SLSkipDatesViewController.h ├── SLSkipDatesViewController.m ├── SLSkipTimeViewController.h ├── SLSkipTimeViewController.m ├── SLSnoozeTimeViewController.h └── SLSnoozeTimeViewController.m /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | .DS_Store 3 | packages 4 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "install", 8 | "type": "shell", 9 | "command": "make package install", 10 | "group": "build", 11 | "problemMatcher": [] 12 | }, 13 | { 14 | "label": "build", 15 | "type": "shell", 16 | "command": "make package", 17 | "group": { 18 | "kind": "build", 19 | "isDefault": true 20 | }, 21 | "problemMatcher": [] 22 | }, 23 | { 24 | "label": "clean", 25 | "type": "shell", 26 | "command": "make clean", 27 | "group": "build", 28 | "problemMatcher": [] 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET=iphone:clang:14.5:8.0 2 | ARCHS=armv7 arm64 arm64e 3 | 4 | PACKAGE_VERSION=$(THEOS_PACKAGE_BASE_VERSION) 5 | 6 | include $(THEOS)/makefiles/common.mk 7 | 8 | LIBRARY_NAME = libSleeper 9 | TWEAK_NAME = SleeperCore SleeperCoreLegacy SleeperUI 10 | 11 | libSleeper_FILES = $(wildcard common/*.m) $(wildcard common/*.xm ) $(wildcard common/*.x) 12 | libSleeper_PRIVATE_FRAMEWORKS = MobileTimer 13 | libSleeper_OBJCFLAGS = -fobjc-arc 14 | libSleeper_LDFLAGS = -lsubstrate 15 | 16 | SleeperCore_FILES = $(wildcard core/*.x) 17 | SleeperCore_LIBRARIES = Sleeper 18 | SleeperCore_OBJCFLAGS = -fobjc-arc 19 | SleeperCore_LDFLAGS = -L$(THEOS_OBJ_DIR) 20 | 21 | SleeperCoreLegacy_FILES = $(wildcard core_legacy/*.x) 22 | SleeperCoreLegacy_LIBRARIES = Sleeper 23 | SleeperCoreLegacy_OBJCFLAGS = -fobjc-arc 24 | SleeperCoreLegacy_LDFLAGS = -L$(THEOS_OBJ_DIR) 25 | 26 | SleeperUI_FILES = $(wildcard ui/*.x) $(wildcard ui/*.xm) $(wildcard ui/custom/*.m) 27 | SleeperUI_LIBRARIES = Sleeper 28 | SleeperUI_OBJCFLAGS = -fobjc-arc 29 | SleeperUI_LDFLAGS = -L$(THEOS_OBJ_DIR) 30 | 31 | include $(THEOS_MAKE_PATH)/library.mk 32 | include $(THEOS_MAKE_PATH)/tweak.mk 33 | 34 | after-install:: 35 | install.exec "killall -9 MobileTimer; killall -9 mobiletimerd; killall -9 SpringBoard;" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This package is for iOS 8 - iOS 14 jailbreaks. For iOS 15+ and rootless jailbreak compatibility, please see [SleeperX](https://havoc.app/package/sleeperx).** 2 | 3 | Sleeper is a tweak designed to give you more functionality around your stock iOS alarms. The goal of Sleeper is to allow you to sleep more using the stock iOS alarms. 4 | 5 | * Change the snooze time of the alarm 6 | * Using a system prompt upon unlocking the device, optionally skip an alarm within a particular set time 7 | * Skip an alarm completely by specifying a specific date or holiday 8 | * Auto-set: Configure alarms to automatically update based on the sunrise or sunset time 9 | * Supports both standalone alarms as well as the Bedtime Alarm introduced with iOS 10 10 | * Compatible with iOS 8 - iOS 14 (note: the auto-set feature is only supported on iOS 10+) 11 | * Compatible with iPhones, iPads, and iPod Touches 12 | 13 | ## *Snooze Time* 14 | 15 | Editing or creating a new alarm will now show a new option: Snooze Time. Entering this view will allow you specify the hours, minutes, and seconds you'd like your alarm to perform the snooze. This interface was designed to integrate seamlessly with the stock iOS Clock application. 16 | 17 | ## *Skipping* 18 | 19 | Use the Skip Toggle to enable or disable the ability to skip the particular alarm. Skipping an alarm can be achieved via a prompt that is displayed upon unlocking the device within a specific period of time or by specifying a particular date/holiday to skip. 20 | 21 | **Skip Time** 22 | 23 | Skip Time is the threshold that is used to determine if you will be prompted to skip the given alarm. The prompt to skip an eligible alarm will show up after unlocking the device. As an example, if you have an alarm set to go off at 8:00am and your Skip Time is 30 minutes, then if you unlock the device between 7:30am and 8:00am, you will be asked if you'd like to skip that alarm. Only one prompt will be shown each time the device is unlocked; the earliest alarm that can be skipped is what will be shown. This feature can be very useful if you frequently find yourself waking up before an alarm is going to go off. 24 | 25 | **Skip Dates / Away Dates** 26 | 27 | The Skip Dates interface allows you to pick specific dates and/or holidays in which the particular alarm will be completely skipped/silenced. Know you'll be taking a vacation or a day off from work? Add that date to your alarm so you can sleep in on those days. Do you work on Thanksgiving or Christmas? Probably not, so be sure to add those holidays to the selected holidays for your alarm. This prevents you from having to remember to turn off an alarm when you don't need to wake up early. 28 | 29 | ## *Auto-Set (iOS 10+)* 30 | 31 | You can use the auto-set feature to automatically update alarms based on the sunrise/sunset times. To use this feature, please ensure that you have the Weather application installed with a valid location set. Once enabled, the alarms will automatically update periodically to adjust to the sunrise/sunset times based on the first location you configured in the Weather application. 32 | 33 | ## *Source Code* 34 | 35 | [This project is open source.](https://github.com/joshuaseltzer/Sleeper) -------------------------------------------------------------------------------- /SleeperCore.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.apple.springboard 10 | com.apple.mobiletimer 11 | 12 | Executables 13 | 14 | mobiletimerd 15 | 16 | CoreFoundationVersion 17 | 18 | 1500 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SleeperCoreLegacy.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.apple.springboard 10 | com.apple.mobiletimer 11 | 12 | CoreFoundationVersion 13 | 14 | 1100 15 | 1400 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /SleeperUI.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.apple.mobiletimer 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/1.png -------------------------------------------------------------------------------- /assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/2.png -------------------------------------------------------------------------------- /assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/3.png -------------------------------------------------------------------------------- /assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/4.png -------------------------------------------------------------------------------- /assets/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/5.png -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/banner.png -------------------------------------------------------------------------------- /assets/banner.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/banner.psd -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/icon.png -------------------------------------------------------------------------------- /assets/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/icon.psd -------------------------------------------------------------------------------- /assets/noun_Alarm Clock_2891329.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/noun_Alarm Clock_2891329.png -------------------------------------------------------------------------------- /assets/noun_Arrow Share_1624620.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/noun_Arrow Share_1624620.png -------------------------------------------------------------------------------- /assets/noun_Night_602944.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/noun_Night_602944.png -------------------------------------------------------------------------------- /assets/open_in-highres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/assets/open_in-highres.png -------------------------------------------------------------------------------- /build_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use the Xcode 11 toolchain to ensure arm64e compatibility on iOS 12 and iOS 13 4 | export PREFIX=$THEOS/toolchain/Xcode11.xctoolchain/usr/bin/ 5 | 6 | # move the default development and Havoc control files temporarily 7 | mv -n control control_dev 8 | mv -n control_Havoc control 9 | 10 | # build the Havoc package 11 | make clean 12 | make package FINALPACKAGE=1 13 | 14 | # return the Havoc control file to the original name, and prep the BigBoss control file for build 15 | mv -n control control_Havoc 16 | mv -n control_BigBoss control 17 | 18 | # build the BigBoss package 19 | make clean 20 | make package FINALPACKAGE=1 21 | 22 | # return the BigBoss and development control files back to their original states 23 | mv -n control control_BigBoss 24 | mv -n control_dev control -------------------------------------------------------------------------------- /common/SLAlarmPrefs.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLAlarmPrefs.h 3 | // Object which includes Sleeper preferences for a specific alarm. 4 | // 5 | // Created by Joshua Seltzer on 2/21/17. 6 | // 7 | // 8 | 9 | #import 10 | 11 | // enum that defines the rows countries that are available to choose from for the holiday selection 12 | typedef enum SLHolidayCountry : NSInteger { 13 | kSLHolidayCountryArgentina, 14 | kSLHolidayCountryAruba, 15 | kSLHolidayCountryAustralia, 16 | kSLHolidayCountryAustria, 17 | kSLHolidayCountryBelarus, 18 | kSLHolidayCountryBelgium, 19 | kSLHolidayCountryBrazil, 20 | kSLHolidayCountryBulgaria, 21 | kSLHolidayCountryCanada, 22 | kSLHolidayCountryChina, 23 | kSLHolidayCountryColombia, 24 | kSLHolidayCountryCroatia, 25 | kSLHolidayCountryCzechia, 26 | kSLHolidayCountryDenmark, 27 | kSLHolidayCountryDominicanRepublic, 28 | kSLHolidayCountryEgypt, 29 | kSLHolidayCountryEstonia, 30 | kSLHolidayCountryFinland, 31 | kSLHolidayCountryFrance, 32 | kSLHolidayCountryGermany, 33 | kSLHolidayCountryHongKong, 34 | kSLHolidayCountryHungary, 35 | kSLHolidayCountryIceland, 36 | kSLHolidayCountryIndia, 37 | kSLHolidayCountryIreland, 38 | kSLHolidayCountryIsrael, 39 | kSLHolidayCountryItaly, 40 | kSLHolidayCountryJapan, 41 | kSLHolidayCountryKenya, 42 | kSLHolidayCountryKorea, 43 | kSLHolidayCountryLithuania, 44 | kSLHolidayCountryLuxembourg, 45 | kSLHolidayCountryMexico, 46 | kSLHolidayCountryMorocco, 47 | kSLHolidayCountryNetherlands, 48 | kSLHolidayCountryNewZealand, 49 | kSLHolidayCountryNicaragua, 50 | kSLHolidayCountryNigeria, 51 | kSLHolidayCountryNorway, 52 | kSLHolidayCountryParaguay, 53 | kSLHolidayCountryPeru, 54 | kSLHolidayCountryPoland, 55 | kSLHolidayCountryPortugal, 56 | kSLHolidayCountryRussia, 57 | kSLHolidayCountrySerbia, 58 | kSLHolidayCountrySingapore, 59 | kSLHolidayCountrySlovakia, 60 | kSLHolidayCountrySlovenia, 61 | kSLHolidayCountrySouthAfrica, 62 | kSLHolidayCountrySpain, 63 | kSLHolidayCountrySweden, 64 | kSLHolidayCountrySwitzerland, 65 | kSLHolidayCountryTaiwan, 66 | kSLHolidayCountryTurkey, 67 | kSLHolidayCountryUkraine, 68 | kSLHolidayCountryUnitedKingdom, 69 | kSLHolidayCountryUnitedStates, 70 | kSLHolidayCountryVietnam, 71 | kSLHolidayCountryNumCountries 72 | } SLHolidayCountry; 73 | 74 | // enum to define the different options that can be returned for the alarm's skip activation 75 | typedef enum SLSkipActivatedStatus : NSInteger { 76 | kSLSkipActivatedStatusUnknown, 77 | kSLSkipActivatedStatusActivated, 78 | kSLSkipActivatedStatusDisabled 79 | } SLSkipActivatedStatus; 80 | 81 | // enum to define the options for whether or not an alarm has the auto-set option enabled 82 | typedef enum SLAutoSetOption : NSInteger { 83 | kSLAutoSetOptionOff, 84 | kSLAutoSetOptionSunrise, 85 | kSLAutoSetOptionSunset 86 | } SLAutoSetOption; 87 | 88 | // enum to define the offset options for the auto-set feature when it is enabled 89 | typedef enum SLAutoSetOffsetOption : NSInteger { 90 | kSLAutoSetOffsetOptionOff, 91 | kSLAutoSetOffsetOptionBefore, 92 | kSLAutoSetOffsetOptionAfter 93 | } SLAutoSetOffsetOption; 94 | 95 | // constants that define the default values 96 | static NSInteger const kSLDefaultSnoozeHour = 0; 97 | static NSInteger const kSLDefaultSnoozeMinute = 9; 98 | static NSInteger const kSLDefaultSnoozeSecond = 0; 99 | static BOOL const kSLDefaultSkipEnabled = NO; 100 | static NSInteger const kSLDefaultSkipHour = 0; 101 | static NSInteger const kSLDefaultSkipMinute = 30; 102 | static NSInteger const kSLDefaultSkipSecond = 0; 103 | static NSInteger const kSLDefaultSkipActivatedStatus = kSLSkipActivatedStatusUnknown; 104 | static NSInteger const kSLDefaultAutoSetOption = kSLAutoSetOptionOff; 105 | static NSInteger const kSLDefaultAutoSetOffsetOption = kSLAutoSetOffsetOptionOff; 106 | static NSInteger const kSLDefaultAutoSetOffsetHour = 1; 107 | static NSInteger const kSLDefaultAutoSetOffsetMinute = 0; 108 | 109 | // Sleeper preferences specific to an alarm 110 | @interface SLAlarmPrefs : NSObject 111 | 112 | // custom initialization that creates a new alarm prefs object with the given alarm Id 113 | // and default preferences 114 | - (instancetype)initWithAlarmId:(NSString *)alarmId; 115 | 116 | // returns the total number of selected holidays to be skipped for the given alarm 117 | - (NSInteger)totalSelectedHolidays; 118 | 119 | // returns a customized string that indicates the total number of selected skip dates and/or holidays 120 | - (NSString *)totalSelectedDatesString; 121 | 122 | // determines whether or not this alarm should be skipped today 123 | - (BOOL)shouldSkipToday; 124 | 125 | // determines whether or not the alarm should be skipped on a given date 126 | - (BOOL)shouldSkipOnDate:(NSDate *)date; 127 | 128 | // returns an explanation of why a given alarm will be skipped 129 | - (NSString *)skipReasonExplanation; 130 | 131 | // returns an explanation regarding the use of the auto-set option 132 | - (NSString *)autoSetExplanation; 133 | 134 | // alarm Id associated with this preference object 135 | @property (nonatomic, strong) NSString *alarmId; 136 | 137 | // the snooze hour 138 | @property (nonatomic) NSInteger snoozeTimeHour; 139 | 140 | // the snooze minute 141 | @property (nonatomic) NSInteger snoozeTimeMinute; 142 | 143 | // the snooze second 144 | @property (nonatomic) NSInteger snoozeTimeSecond; 145 | 146 | // whether or not skip is enabled 147 | @property (nonatomic) BOOL skipEnabled; 148 | 149 | // the skip hour 150 | @property (nonatomic) NSInteger skipTimeHour; 151 | 152 | // the skip minute 153 | @property (nonatomic) NSInteger skipTimeMinute; 154 | 155 | // the skip second 156 | @property (nonatomic) NSInteger skipTimeSecond; 157 | 158 | // the skip activation status 159 | @property (nonatomic) SLSkipActivatedStatus skipActivationStatus; 160 | 161 | // the auto-set option 162 | @property (nonatomic) SLAutoSetOption autoSetOption; 163 | 164 | // the auto-set offset option 165 | @property (nonatomic) SLAutoSetOffsetOption autoSetOffsetOption; 166 | 167 | // the auto-set offset hour 168 | @property (nonatomic) NSInteger autoSetOffsetHour; 169 | 170 | // the auto-set offset minute 171 | @property (nonatomic) NSInteger autoSetOffsetMinute; 172 | 173 | // an array of NSDate objects that represent the custom skip dates for this alarm 174 | @property (nonatomic, strong) NSArray *customSkipDates; 175 | 176 | // a dictionary containing additional dictionaries that correspond to the selected holidays per country 177 | @property (nonatomic, strong) NSDictionary *holidaySkipDates; 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /common/SLAutoSetManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLAutoSetManager.h 3 | // A singleton object that will be used to manage the auto-set feature. 4 | // 5 | // Created by Joshua Seltzer on 6/27/20. 6 | // Copyright (c) 2020 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SLAlarmPrefs.h" 11 | 12 | // the notification key that will be fired when the auto-set options are updated for a specific alarm 13 | static NSString *const kSLAutoSetOptionsUpdatedNotification = @"SLAutoSetOptionsUpdated"; 14 | 15 | // the location object that will be associated with a forecast model 16 | @interface WFLocation : NSObject 17 | 18 | // the time zone that is associated with the location 19 | @property (nonatomic, copy) NSTimeZone *timeZone; 20 | 21 | @end 22 | 23 | // an object which contains information about the current forecast 24 | @interface WAForecastModel : NSObject 25 | 26 | // the sunrise and sunset times for this forecast 27 | @property (nonatomic, retain) NSDate *sunrise; 28 | @property (nonatomic, retain) NSDate *sunset; 29 | 30 | // the location object associated with the forecast model 31 | @property (nonatomic, retain) WFLocation *location; 32 | 33 | @end 34 | 35 | // preferences object that will be used to request the model 36 | @interface WeatherPreferences : NSObject 37 | 38 | // the shared preferences that will be utilized to get updates from the today model 39 | + (id)sharedPreferences; 40 | 41 | @end 42 | 43 | // the today model which will be used to provide us with the sunrise/sunset times 44 | @interface WATodayModel : NSObject 45 | 46 | // returns a WATodayAutoupdatingLocationModel instance that can be used to monitor changes to the today model 47 | + (id)autoupdatingLocationModelWithPreferences:(WeatherPreferences *)weatherPreferences 48 | effectiveBundleIdentifier:(NSString *)bundleIdentifier; 49 | 50 | // the forecast model that is associated with this today model 51 | @property (nonatomic, retain) WAForecastModel *forecastModel; 52 | 53 | @end 54 | 55 | // manager that will be used to automatically update alarms based on the user preferences 56 | @interface SLAutoSetManager : NSObject 57 | 58 | // return a singleton instance of this manager 59 | + (instancetype)sharedInstance; 60 | 61 | // routine to update to a single alarm object that has updated auto-set settings 62 | - (void)updateAutoSetAlarm:(NSDictionary *)alarmDict; 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /common/SLCommonHeaders.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLUserInterfaceHeaders.h 3 | // Contains all interfaces that are shared among the various components. 4 | // 5 | // Created by Joshua Seltzer on 2/15/20. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | // iOS 8 / iOS 9: the notification that gets fired when the user decides to snooze an alarm 17 | @interface UIConcreteLocalNotification : UILocalNotification 18 | 19 | // returns a date for a given notification that will happen after a date in a given time zone 20 | - (NSDate *)nextFireDateAfterDate:(NSDate *)date localTimeZone:(NSTimeZone *)timeZone; 21 | 22 | @end 23 | 24 | // legacy notification trigger object which is a subclass of a standard notification trigger 25 | @interface UNLegacyNotificationTrigger : UNNotificationTrigger 26 | 27 | // returns a date for a given notification that will happen after a date in a given time zone 28 | - (NSDate *)_nextTriggerDateAfterDate:(NSDate *)date withRequestedDate:(NSDate *)requestedDate defaultTimeZone:(NSTimeZone *)timeZone; 29 | 30 | @end 31 | 32 | // additional details/content associated with a notification request 33 | @interface UNNotificationContent (Private) 34 | 35 | // iOS 10: determines whether or not the notification is from a snooze notification 36 | - (BOOL)isFromSnooze; 37 | 38 | @end 39 | 40 | // iOS 10 / iOS 11: the notification record object that gets fired when the user snoozes the alarm 41 | @interface UNSNotificationRecord : NSObject 42 | 43 | // user information attached to this notification record 44 | @property (nonatomic, copy) NSDictionary *userInfo; 45 | 46 | // the trigger date for the notification 47 | @property (nonatomic, copy) NSDate *triggerDate; 48 | 49 | // sets the trigger date for this notification 50 | - (void)setTriggerDate:(NSDate *)date; 51 | 52 | // returns whether or not this notification record is from a snooze action 53 | - (BOOL)isFromSnooze; 54 | 55 | @end 56 | 57 | // iOS 8 - iOS 11: the alarm object that contains all of the information about the alarm 58 | @interface Alarm : NSObject 59 | 60 | // iOS 8: the alarm Id corresponding to the alarm object 61 | @property (readonly) NSString *alarmId; 62 | 63 | // iOS 9 / iOS 10 / iOS 11: the alarm Id corresponding to the alarm object 64 | @property (nonatomic, retain) NSString *alarmID; 65 | 66 | // the display title of the alarm 67 | @property (readonly, nonatomic) NSString *uiTitle; 68 | 69 | // tells us if the given notification object was generated from a snooze notification (iOS 8 / iOS 9) 70 | + (BOOL)isSnoozeNotification:(UIConcreteLocalNotification *)notification; 71 | 72 | // returns the next date that this alarm will fire 73 | - (NSDate *)nextFireDate; 74 | 75 | // simulates when an alarm gets fired 76 | - (void)handleAlarmFired:(UIConcreteLocalNotification *)notification; 77 | 78 | // iOS 10 / iOS 11: determines whether or not the alarm is the sleep/bedtime alarm 79 | - (BOOL)isSleepAlarm; 80 | 81 | // updates the hour property of the alarm 82 | - (void)setHour:(NSUInteger)hour; 83 | 84 | // updates the minute property of the alarm 85 | - (void)setMinute:(NSUInteger)minute; 86 | 87 | // whether or not the alarm is active 88 | - (BOOL)isActive; 89 | 90 | // populates the editing proxy for the alarm 91 | - (void)prepareEditingProxy; 92 | 93 | // returns the editing proxy for this alarm 94 | - (Alarm *)editingProxy; 95 | 96 | // applies any changes to the editing proxy to the alarm itself 97 | - (void)applyChangesFromEditingProxy; 98 | 99 | @end 100 | 101 | // iOS 8 - iOS 11: manager that governs all alarms on the system 102 | @interface AlarmManager : NSObject 103 | 104 | // iOS 10 / iOS 11: the special sleep alarm (i.e. Bedtime alarm) 105 | @property (nonatomic, readonly) Alarm *sleepAlarm; 106 | 107 | // the shared alarm manager 108 | + (id)sharedManager; 109 | 110 | // loads the alarms on the system in the manager object 111 | - (void)loadAlarms; 112 | 113 | // simulates when an alarm gets fired 114 | - (void)handleNotificationFired:(UIConcreteLocalNotification *)notification; 115 | 116 | // returns an alarm object from a given alarm Id 117 | - (Alarm *)alarmWithId:(NSString *)alarmId; 118 | 119 | // updates a given alarm 120 | - (void)updateAlarm:(Alarm *)alarm active:(BOOL)active; 121 | 122 | @end 123 | 124 | // iOS 12+: the alarm object 125 | @interface MTAlarm : NSObject 126 | 127 | // the title of the alarm 128 | @property (readonly, nonatomic) NSString *displayTitle; 129 | 130 | // signifies whether or not this alarm is snozoed 131 | @property (readonly, nonatomic, getter=isSnoozed) BOOL snoozed; 132 | 133 | // updates the hour property of the alarm 134 | - (void)setHour:(NSInteger)hour; 135 | 136 | // updates the minute property of the alarm 137 | - (void)setMinute:(NSInteger)minute; 138 | 139 | // returns a string representation of the alarm Id 140 | - (NSString *)alarmIDString; 141 | 142 | // returns the next fire date for the alarm given a start date 143 | - (NSDate *)nextFireDateAfterDate:(NSDate *)date includeBedtimeNotification:(BOOL)includeBedtimeNotification; 144 | 145 | // indicates whether or not this is the special Bedtime / sleep alarm 146 | - (BOOL)isSleepAlarm; 147 | 148 | @end 149 | 150 | // custom interface for added properties 151 | @interface MTAlarm (Sleeper) 152 | 153 | // flag which indicates whether or not the alarm was updated by this tweak or not 154 | @property (nonatomic, assign) BOOL SLWasUpdatedBySleeper; 155 | 156 | @end 157 | 158 | // iOS 12+: an extension to the MTAlarm interface indicating an editable alarm 159 | @interface MTMutableAlarm : MTAlarm 160 | @end 161 | 162 | // iOS 12+: the data source corresponding to a particular alarm 163 | @interface MTAlarmDataSource : NSObject 164 | 165 | // the sleep alarm that corresponds to the alarm data source object 166 | @property (retain, nonatomic) MTAlarm *sleepAlarm; 167 | 168 | @end 169 | 170 | // manager that governs all alarms on the system (iOS 12 - iOS 14) 171 | @interface MTAlarmManager : NSObject 172 | 173 | // invoked when an alarm is saved 174 | - (id)updateAlarm:(MTMutableAlarm *)mutableAlarm; 175 | 176 | // returns an array of MTAlarm objects for the given date and 177 | - (NSArray *)nextAlarmsForDateSync:(NSDate *)date maxCount:(int)maxCount includeSleepAlarm:(BOOL)includeSleepAlarm includeBedtimeNotification:(BOOL)includeBedtimeNotification; 178 | 179 | // returns an alarm object given the corresponding alarm Id string 180 | - (MTAlarm *)alarmWithIDString:(NSString *)alarmId; 181 | 182 | @end 183 | 184 | // iOS 8 - iOS 11: data provider which lets us know which alarms have notifications scheduled 185 | @interface SBClockDataProvider : NSObject 186 | 187 | // the shared instance of the clock data provider 188 | + (id)sharedInstance; 189 | 190 | // iOS 8: return all scheduled notifications that are held by the clock data provider 191 | - (NSArray *)_scheduledNotifications; 192 | 193 | // returns an alarm Id for a given notification 194 | - (NSString *)_alarmIDFromNotification:(UIConcreteLocalNotification *)notification; 195 | 196 | // iOS 10 / iOS 11: returns an alarm Id for a given notification request 197 | - (NSString *)_alarmIDFromNotificationRequest:(UNNotificationRequest *)notificationRequest; 198 | 199 | // lets us know whether or not a given notification is an alarm notification 200 | // iOS 8 / iOS 9: argument is a UIConcreteLocalNotification object 201 | // iOS 10 / iOS 11: argument is a UNNotification object 202 | - (BOOL)_isAlarmNotification:(id)notification; 203 | 204 | // iOS 10 / iOS 11: whether or not a given notification request is an alarm notification 205 | - (BOOL)_isAlarmNotificationRequest:(UNNotificationRequest *)notificationRequest; 206 | 207 | // iOS 8 / iOS 9: invoked when an alarm alert (i.e. bulletin) is about to be displayed 208 | - (void)_publishBulletinForLocalNotification:(UIConcreteLocalNotification *)notification; 209 | 210 | // iOS 10 / iOS 11: invoked when an alarm alert (i.e. bulletin) is about to be displayed 211 | - (void)_publishBulletinForNotification:(id)notification; 212 | 213 | @end 214 | 215 | // iOS 9 / iOS 10 / iOS 11: manages the notifications for clocks and alarms 216 | @interface SBClockNotificationManager : NSObject 217 | 218 | // the shared instance of the notification manager 219 | + (id)sharedInstance; 220 | 221 | // iOS 9: returns the array of scheduled local notifications 222 | - (NSArray *)scheduledLocalNotifications; 223 | 224 | // iOS 10 / iOS 11: returns pending notification request objects in the completion handler 225 | - (void)getPendingNotificationRequestsWithCompletionHandler:(void (^)(NSArray *requests))completionHandler; 226 | 227 | @end -------------------------------------------------------------------------------- /common/SLCompatibilityHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLCompatibilityHelper.h 3 | // Functions that are used to maintain system compatibility between different iOS versions. 4 | // 5 | // Created by Joshua Seltzer on 10/14/15. 6 | // 7 | // 8 | 9 | #import "SLCommonHeaders.h" 10 | 11 | // define the core foundation version numbers if they have not already been defined 12 | // http://iphonedevwiki.net/index.php/CoreFoundation.framework 13 | #ifndef kCFCoreFoundationVersionNumber_iOS_8_0 14 | #define kCFCoreFoundationVersionNumber_iOS_8_0 1100.00 15 | #endif 16 | 17 | #ifndef kCFCoreFoundationVersionNumber_iOS_9_0 18 | #define kCFCoreFoundationVersionNumber_iOS_9_0 1200.00 19 | #endif 20 | 21 | #ifndef kCFCoreFoundationVersionNumber_iOS_10_0 22 | #define kCFCoreFoundationVersionNumber_iOS_10_0 1300.00 23 | #endif 24 | 25 | #ifndef kCFCoreFoundationVersionNumber_iOS_11_0 26 | #define kCFCoreFoundationVersionNumber_iOS_11_0 1400.00 27 | #endif 28 | 29 | #ifndef kCFCoreFoundationVersionNumber_iOS_12_0 30 | #define kCFCoreFoundationVersionNumber_iOS_12_0 1500.00 31 | #endif 32 | 33 | #ifndef kCFCoreFoundationVersionNumber_iOS_13_0 34 | #define kCFCoreFoundationVersionNumber_iOS_13_0 1600.00 35 | #endif 36 | 37 | #ifndef kCFCoreFoundationVersionNumber_iOS_14_0 38 | #define kCFCoreFoundationVersionNumber_iOS_14_0 1700.00 39 | #endif 40 | 41 | // create definitions for the different versions of iOS that are supported by Sleeper 42 | #define kSLSystemVersioniOS14 kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_0 43 | #define kSLSystemVersioniOS13 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_14_0) 44 | #define kSLSystemVersioniOS12 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_13_0) 45 | #define kSLSystemVersioniOS11 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_11_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_12_0) 46 | #define kSLSystemVersioniOS10 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_10_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_11_0) 47 | #define kSLSystemVersioniOS9 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_9_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_10_0) 48 | #define kSLSystemVersioniOS8 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_9_0) 49 | 50 | // interface for version compatibility functions throughout the application 51 | @interface SLCompatibilityHelper : NSObject 52 | 53 | // iOS 8 / iOS 9: modifies a snooze UIConcreteLocalNotification object with the selected snooze time (if applicable) 54 | + (void)modifySnoozeNotificationForLocalNotification:(UIConcreteLocalNotification *)localNotification; 55 | 56 | // iOS 10 / iOS 11: modifies a snooze UNSNotificationRecord object with the selected snooze time (if applicable) 57 | + (void)modifySnoozeNotificationForNotificationRecord:(UNSNotificationRecord *)notificationRecord; 58 | 59 | // Returns a modified NSDate object with an appropriately modified snooze time for a given alarm Id and original date 60 | // Returns nil if no modified snooze date is available 61 | + (NSDate *)modifiedSnoozeDateForAlarmId:(NSString *)alarmId withOriginalDate:(NSDate *)originalDate; 62 | 63 | // iOS 8 / iOS 9: Returns the next skippable alarm local notification. If there is no skippable notification found, return nil. 64 | + (UIConcreteLocalNotification *)nextSkippableAlarmLocalNotification; 65 | 66 | // iOS 10 / iOS 11: Returns the next skippable alarm notification request given an array of notification requests. 67 | // If there is no skippable notification found, return nil. 68 | + (UNNotificationRequest *)nextSkippableAlarmNotificationRequestForNotificationRequests:(NSArray *)notificationRequests; 69 | 70 | // returns whether or not an alarm is skippable based on the alarm Id 71 | + (BOOL)isAlarmSkippableForAlarmId:(NSString *)alarmId withNextFireDate:(NSDate *)nextFireDate; 72 | 73 | // returns a valid alarm Id for a given alarm 74 | + (NSString *)alarmIdForAlarm:(Alarm *)alarm; 75 | 76 | // returns the appropriate title string for a given Alarm object 77 | + (NSString *)alarmTitleForAlarm:(Alarm *)alarm; 78 | 79 | // returns the appropriate title string for a given MTAlarm object 80 | + (NSString *)alarmTitleForMTAlarm:(MTAlarm *)alarm; 81 | 82 | // returns the picker view's background color, which will depend on the iOS version 83 | + (UIColor *)pickerViewBackgroundColor; 84 | 85 | // returns the color of the standard labels used throughout the tweak 86 | + (UIColor *)defaultLabelColor; 87 | 88 | // returns the color of the destructive labels used throughout the tweak 89 | + (UIColor *)destructiveLabelColor; 90 | 91 | // iOS 13: returns the background color used for cells used in the various views 92 | + (UIColor *)tableViewCellBackgroundColor; 93 | 94 | // iOS 10, iOS 11, iOS 12, iOS 13: returns the cell selection background color for cells 95 | + (UIColor *)tableViewCellSelectedBackgroundColor; 96 | 97 | // modifies an alert controller's subviews appropriately if necessary for the current version of iOS 98 | + (void)updateSubviewsForAlertController:(UIAlertController *)alertController; 99 | 100 | // uses the appearance API to modify the look and feel of a UIAlertController's various views for the current version of iOS 101 | + (void)updateDefaultUIAlertControllerAppearance; 102 | 103 | // returns the checkmark image used to indicate selection throughout the UI 104 | + (UIImage *)checkmarkImage; 105 | 106 | // returns the "open in" image 107 | + (UIImage *)openInImage; 108 | 109 | // returns whether or not the device is even capable of using the auto-set feature (requires iOS 10 and iPhone device) 110 | + (BOOL)canHaveAutoSet; 111 | 112 | // returns whether or not the device is in a state that can use the auto-set feature 113 | + (BOOL)canEnableAutoSet; 114 | 115 | // navigates the user to the Weather application 116 | + (void)openWeatherApplication; 117 | 118 | // Updates the given alarms (represented as SLAlarmPref dictionaries) with the base hour and base minute. 119 | // The implementation of updating the alarms will differ depending on which iOS is currently running. 120 | + (void)updateAlarms:(NSArray *)alarms withBaseHour:(NSInteger)baseHour withBaseMinute:(NSInteger)baseMinute; 121 | 122 | // returns an NSBundle object corresponding to the SleepHealthUI Private Framework 123 | + (NSBundle *)sleepHealthUIBundle; 124 | 125 | // returns the internally used alarm ID for the new "Wake Up" alarm (iOS 14) 126 | + (NSString *)wakeUpAlarmId; 127 | 128 | @end -------------------------------------------------------------------------------- /common/SLPrefsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLPrefsManager.h 3 | // The preferences manager for the tweak. 4 | // 5 | // Created by Joshua Seltzer on 12/8/14. 6 | // Copyright (c) 2014 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SLAlarmPrefs.h" 11 | 12 | // the bundle path which includes some custom preference files needed for the tweak 13 | #define kSLSleeperBundle [NSBundle bundleWithPath:@"/Library/Application Support/Sleeper.bundle"] 14 | 15 | // define the bundle identifier for the tweak 16 | static NSString *const kSLBundleIdentifier = @"com.joshuaseltzer.sleeper"; 17 | 18 | // constant keys for the values we are going to add to the preferences file 19 | static NSString *const kSLAlarmsKey = @"Alarms"; 20 | static NSString *const kSLAlarmIdKey = @"alarmId"; 21 | static NSString *const kSLSnoozeHourKey = @"snoozeTimeHour"; 22 | static NSString *const kSLSnoozeMinuteKey = @"snoozeTimeMinute"; 23 | static NSString *const kSLSnoozeSecondKey = @"snoozeTimeSecond"; 24 | static NSString *const kSLSkipEnabledKey = @"skipEnabled"; 25 | static NSString *const kSLSkipHourKey = @"skipTimeHour"; 26 | static NSString *const kSLSkipMinuteKey = @"skipTimeMinute"; 27 | static NSString *const kSLSkipSecondKey = @"skipTimeSecond"; 28 | static NSString *const kSLSkipActivatedStatusKey = @"skipActivatedStatus"; 29 | static NSString *const kSLSkipDatesKey = @"skipDates"; 30 | static NSString *const kSLHolidaySkipDatesKey = @"holidaySkipDates"; 31 | static NSString *const kSLCustomSkipDatesKey = @"customSkipDates"; 32 | static NSString *const kSLCustomSkipDateStringsKey = @"customSkipDateStrings"; 33 | static NSString *const kSLHolidayHolidaysKey = @"holidays"; 34 | static NSString *const kSLHolidayNameKey = @"name"; 35 | static NSString *const kSLHolidayDatesKey = @"dates"; 36 | static NSString *const kSLAutoSetOptionKey = @"autoSetOption"; 37 | static NSString *const kSLAutoSetOffsetOptionKey = @"autoSetOffsetOption"; 38 | static NSString *const kSLAutoSetOffsetHourKey = @"autoSetOffsetHour"; 39 | static NSString *const kSLAutoSetOffsetMinuteKey = @"autoSetOffsetMinute"; 40 | 41 | // define the key that will be used in the notification sent to observers when auto-set alarms are updated 42 | static NSString *const kSLUpdatedAutoSetAlarmNotificationKey = @"updatedAutoSetAlarm"; 43 | 44 | @class SLAlarmPrefs; 45 | 46 | // manager that manages the retrieval, saving, and deleting of custom snooze times 47 | @interface SLPrefsManager : NSObject 48 | 49 | // returns the date formatter for converting to and from saving to the plist 50 | + (NSDateFormatter *)plistDateFormatter; 51 | 52 | // Return an SLAlarmPrefs object with alarm information for a given alarm Id. Return nil if no alarm is found. 53 | + (SLAlarmPrefs *)alarmPrefsForAlarmId:(NSString *)alarmId; 54 | 55 | // returns whether or not the preferences file contains preferences for an alarm with the given alarm Id 56 | + (BOOL)prefsContainAlarmWithAlarmId:(NSString *)alarmId; 57 | 58 | // save the specific alarm preferences object 59 | + (void)saveAlarmPrefs:(SLAlarmPrefs *)alarmPrefs; 60 | 61 | // save the skip activation status for a given alarm 62 | + (void)setSkipActivatedStatusForAlarmId:(NSString *)alarmId 63 | skipActivatedStatus:(SLSkipActivatedStatus)skipActivatedStatus; 64 | 65 | // delete an alarm from our settings 66 | + (void)deleteAlarmForAlarmId:(NSString *)alarmId; 67 | 68 | // Provides the caller with a dictionary containing all of the auto-set alarms using the auto-set option as the key for the dictionary. 69 | // The value for each key will be an array containing dictionaries with the alarm information. 70 | // Returns nil when no auto-set alarms exist. 71 | + (NSDictionary *)allAutoSetAlarms; 72 | 73 | // Returns a dictionary that corresponds to the default holiday source for the given holiday resource name. 74 | // This function will also remove any passed dates. 75 | + (NSDictionary *)holidayResourceForResourceName:(NSString *)resourceName; 76 | 77 | // Returns the first available skip date for the given holiday name and country. This function will not take into consideration any passed dates. 78 | + (NSDate *)firstSkipDateForHolidayName:(NSString *)holidayName inHolidayCountry:(SLHolidayCountry)holidayCountry; 79 | 80 | // returns a corresponding country code for any given country 81 | + (NSString *)countryCodeForHolidayCountry:(SLHolidayCountry)country; 82 | 83 | // returns a string that corresponds to the resource name for a given holiday country 84 | + (NSString *)resourceNameForHolidayCountry:(SLHolidayCountry)country; 85 | 86 | // returns a string that corresponds to the resource name for a given country code 87 | + (NSString *)resourceNameForCountryCode:(NSString *)countryCode; 88 | 89 | // returns the localized, friendly name to be displayed for the given country 90 | + (NSString *)friendlyNameForHolidayCountry:(SLHolidayCountry)country; 91 | 92 | // returns the localized, friendly name to be displayed for an auto-set option 93 | + (NSString *)friendlyNameForAutoSetOption:(SLAutoSetOption)autoSetOption; 94 | 95 | // returns the localized, friendly name to be displayed for an auto-set offset option 96 | + (NSString *)friendlyNameForAutoSetOffsetOption:(SLAutoSetOffsetOption)autoSetOffsetOption; 97 | 98 | // Returns a string that represents a date that is going to be skipped. If showRelativeString is enabled, 99 | // a relative string is shown instead (i.e. Today, Tomorrow) 100 | + (NSString *)skipDateStringForDate:(NSDate *)date showRelativeString:(BOOL)showRelativeString; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /common/SLSkipAlarmAlertItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLSkipAlarmAlertItem.h 3 | // Custom system alert item to ask the user if he or she would like to skip a given alarm. 4 | // 5 | // Created by Joshua Seltzer on 8/9/15. 6 | // 7 | // 8 | 9 | #import "SLCommonHeaders.h" 10 | 11 | // a system alert item 12 | @interface SBAlertItem : NSObject 13 | 14 | // the alert controlelr object that corresponds to this alert item 15 | - (UIAlertController *)alertController; 16 | 17 | // allows us to set up the alert view or alert controller 18 | - (void)configure:(BOOL)configure requirePasscodeForActions:(BOOL)requirePasscode; 19 | 20 | // dismisses the alert item 21 | - (void)dismiss; 22 | 23 | @end 24 | 25 | // the controller responsible for activating and displaying system alert items 26 | @interface SBAlertItemsController : UIViewController 27 | 28 | // the shared instance of this controller 29 | + (id)sharedInstance; 30 | 31 | // activates/displays an alert item to the user 32 | - (void)activateAlertItem:(SBAlertItem *)alertItem animated:(BOOL)animated; 33 | 34 | // Returns whether or not the alert items controller contains an alert of a given class. We will utilize this method 35 | // to ensure that only a single SLSkipAlarmAlertItem is being shown at once. 36 | - (BOOL)hasAlertOfClass:(Class)alertClass; 37 | 38 | @end 39 | 40 | // system alert for skipping alarms 41 | @interface SLSkipAlarmAlertItem : SBAlertItem 42 | 43 | // create a new alert item with a given title, alarmId, and next fire date 44 | - (id)initWithTitle:(NSString *)title alarmId:(NSString *)alarmId nextFireDate:(NSDate *)nextFireDate; 45 | 46 | @end -------------------------------------------------------------------------------- /common/SLSkipAlarmAlertItem.xm: -------------------------------------------------------------------------------- 1 | // 2 | // SLSkipAlarmAlertItem.xm 3 | // Custom system alert item to ask the user if he or she would like to skip a given alarm. 4 | // 5 | // Created by Joshua Seltzer on 8/9/15. 6 | // 7 | // 8 | 9 | #import "SLSkipAlarmAlertItem.h" 10 | #import "SLPrefsManager.h" 11 | #import "SLLocalizedStrings.h" 12 | #import "SLCompatibilityHelper.h" 13 | 14 | // private interface definition to define some properties 15 | @interface SLSkipAlarmAlertItem (Sleeper) 16 | 17 | @property (nonatomic, retain) NSString *SLTitle; 18 | @property (nonatomic, retain) NSString *SLAlarmId; 19 | @property (nonatomic, retain) NSDate *SLAlertFireDate; 20 | 21 | @end 22 | 23 | // keep a single static instance of the date formatter that will be used to display the time to the user 24 | static NSDateFormatter *sSLSAlertDateFormatter; 25 | 26 | %subclass SLSkipAlarmAlertItem : SBAlertItem 27 | 28 | // the title associated with this alert 29 | %property (nonatomic, retain) NSString *SLTitle; 30 | 31 | // the alarmId associated with the alarm being displayed in this alert 32 | %property (nonatomic, retain) NSString *SLAlarmId; 33 | 34 | // the fire date for the alarm in this alert 35 | %property (nonatomic, retain) NSDate *SLAlertFireDate; 36 | 37 | // create a new alert item with a given title, alarmId, and next fire date 38 | %new 39 | - (id)initWithTitle:(NSString *)title alarmId:(NSString *)alarmId nextFireDate:(NSDate *)nextFireDate 40 | { 41 | self = [self init]; 42 | if (self) { 43 | self.SLTitle = title; 44 | self.SLAlarmId = alarmId; 45 | self.SLAlertFireDate = nextFireDate; 46 | 47 | // create the date formatter object once since date formatters are expensive 48 | static dispatch_once_t once; 49 | dispatch_once(&once, ^{ 50 | sSLSAlertDateFormatter = [[NSDateFormatter alloc] init]; 51 | sSLSAlertDateFormatter.dateFormat = @"h:mm a"; 52 | }); 53 | } 54 | return self; 55 | } 56 | 57 | - (void)dealloc 58 | { 59 | // clear out some properties associated with this alert 60 | self.SLTitle = nil; 61 | self.SLAlarmId = nil; 62 | self.SLAlertFireDate = nil; 63 | 64 | %orig; 65 | } 66 | 67 | // configure the alert with the alarm properties 68 | - (void)configure:(BOOL)configure requirePasscodeForActions:(BOOL)requirePasscode 69 | { 70 | %orig; 71 | 72 | // customize the alert controller 73 | self.alertController.title = kSLSkipAlarmString; 74 | self.alertController.message = kSLSkipQuestionString(self.SLTitle, [sSLSAlertDateFormatter stringFromDate:self.SLAlertFireDate]); 75 | 76 | // add yes, no, and cancel actions to the alert controller 77 | UIAlertAction *yesAction = [UIAlertAction actionWithTitle:kSLYesString 78 | style:UIAlertActionStyleDestructive 79 | handler:^(UIAlertAction * _Nonnull action) { 80 | // save the alarm's skip activation state to our preferences 81 | [SLPrefsManager setSkipActivatedStatusForAlarmId:self.SLAlarmId 82 | skipActivatedStatus:kSLSkipActivatedStatusActivated]; 83 | [self dismiss]; 84 | }]; 85 | UIAlertAction *noAction = [UIAlertAction actionWithTitle:kSLNoString 86 | style:UIAlertActionStyleDefault 87 | handler:^(UIAlertAction * _Nonnull action) { 88 | // save the alarm's skip activation state to our preferences 89 | [SLPrefsManager setSkipActivatedStatusForAlarmId:self.SLAlarmId 90 | skipActivatedStatus:kSLSkipActivatedStatusDisabled]; 91 | [self dismiss]; 92 | }]; 93 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:kSLCancelString 94 | style:UIAlertActionStyleCancel 95 | handler:^(UIAlertAction * _Nonnull action) { 96 | [self dismiss]; 97 | }]; 98 | 99 | // add the actions to the alert controller 100 | [self.alertController addAction:yesAction]; 101 | [self.alertController addAction:noAction]; 102 | [self.alertController addAction:cancelAction]; 103 | 104 | // if the alert still exists, be sure to dismiss the alert just before the alarm will fire 105 | __weak typeof(self) weakSelf = self; 106 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(([self.SLAlertFireDate timeIntervalSinceDate:[NSDate date]] - 1.0f) * NSEC_PER_SEC)); 107 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 108 | // if the alert still exists, then automatically dismiss the alert 109 | if (weakSelf) { 110 | [weakSelf dismiss]; 111 | } 112 | }); 113 | } 114 | 115 | // do no allow the alert to be shown during an emergency call 116 | - (BOOL)shouldShowInEmergencyCall 117 | { 118 | return NO; 119 | } 120 | 121 | // do not allow the alert to be shown on the lock screen 122 | - (BOOL)shouldShowInLockScreen 123 | { 124 | return NO; 125 | } 126 | 127 | // do not allow the alert to be shown in Apple CarPlay 128 | - (BOOL)allowInCar 129 | { 130 | return NO; 131 | } 132 | 133 | // do not allow the alert to be shown during setup 134 | - (BOOL)allowInSetup 135 | { 136 | return NO; 137 | } 138 | 139 | // always return YES so that the alert is automatically dismissed if the user locks the phone 140 | - (BOOL)dismissOnLock 141 | { 142 | return YES; 143 | } 144 | 145 | %end 146 | -------------------------------------------------------------------------------- /common/SLSpringBoard.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSpringBoard.x 3 | // Hooks into the SpringBoard application to run our singleton process that will potentially monitor changes to timers. 4 | // 5 | // Created by Joshua Seltzer on 7/2/2020. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | #import "../common/SLCompatibilityHelper.h" 12 | #import "../common/SLAutoSetManager.h" 13 | 14 | %hook SpringBoard 15 | 16 | // called whenever an auto-set alarm needs to be updated 17 | %new 18 | - (void)SLAutoSetOptionsUpdated:(NSNotification *)notification 19 | { 20 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 21 | // notify the auto-set manager that an alarm has updated auto-set options 22 | [[SLAutoSetManager sharedInstance] updateAutoSetAlarm:[notification userInfo]]; 23 | }); 24 | } 25 | 26 | - (void)applicationDidFinishLaunching:(UIApplication *)application 27 | { 28 | %orig; 29 | 30 | // create the auto-set manager instance to potentially monitor changes to alarms 31 | [SLAutoSetManager sharedInstance]; 32 | 33 | // observe changes from the auto-set manager to update alarms with updated auto-set options 34 | [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(SLAutoSetOptionsUpdated:) name:kSLAutoSetOptionsUpdatedNotification object:nil]; 35 | } 36 | 37 | %end 38 | 39 | %ctor { 40 | // only initialize this file for particular versions 41 | if ([SLCompatibilityHelper canHaveAutoSet]) { 42 | %init(); 43 | } 44 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: org.packix.sleeper 2 | Name: Sleeper (iOS 8-14) 3 | Depends: mobilesubstrate, firmware (>=8.0), firmware (<<15.0) 4 | Version: 7.0.5 5 | Architecture: iphoneos-arm 6 | Conflicts: org.thebigboss.sleeper 7 | Replaces: org.thebigboss.sleeper 8 | Description: Set custom snooze times and skip alarms with the Clock app using Sleeper! 9 | Maintainer: Joshua Seltzer 10 | Author: Joshua Seltzer 11 | Section: Tweaks 12 | Icon: file:///Library/Application%20Support/Sleeper.bundle/icon.png 13 | -------------------------------------------------------------------------------- /control_BigBoss: -------------------------------------------------------------------------------- 1 | Package: org.thebigboss.sleeper 2 | Name: Sleeper (Legacy) (iOS 8-14) 3 | Depends: mobilesubstrate, firmware (>=8.0), firmware (<<15.0) 4 | Version: 7.0.5 5 | Architecture: iphoneos-arm 6 | Conflicts: org.packix.sleeper 7 | Description: Set custom snooze times and skip alarms with the Clock app using Sleeper! 8 | Maintainer: Joshua Seltzer 9 | Author: Joshua Seltzer 10 | Section: Tweaks 11 | Icon: file:///Library/Application%20Support/Sleeper.bundle/icon.png 12 | -------------------------------------------------------------------------------- /control_Havoc: -------------------------------------------------------------------------------- 1 | Package: org.packix.sleeper 2 | Name: Sleeper (iOS 8-14) 3 | Depends: mobilesubstrate, firmware (>=8.0), firmware (<<15.0) 4 | Version: 7.0.5 5 | Architecture: iphoneos-arm 6 | Conflicts: org.thebigboss.sleeper 7 | Replaces: org.thebigboss.sleeper 8 | Description: Set custom snooze times and skip alarms with the Clock app using Sleeper! 9 | Maintainer: Joshua Seltzer 10 | Author: Joshua Seltzer 11 | Section: Tweaks 12 | Icon: file:///Library/Application%20Support/Sleeper.bundle/icon.png 13 | -------------------------------------------------------------------------------- /core/SLMTAlarm.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTAlarm.x 3 | // The alarm object used for iOS 12+. 4 | // 5 | // Created by Joshua Seltzer on 7/30/2020. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | #import "../common/SLPrefsManager.h" 11 | 12 | %hook MTAlarm 13 | 14 | // flag which indicates whether or not the alarm was updated by this tweak or not 15 | %property (nonatomic, assign) BOOL SLWasUpdatedBySleeper; 16 | 17 | %end 18 | 19 | %ctor { 20 | // only initialize this file for particular versions 21 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13 || kSLSystemVersioniOS12) { 22 | %init(); 23 | } 24 | } -------------------------------------------------------------------------------- /core/SLMTAlarmManager.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTAlarmManager.x 3 | // Modify Apple's internal class for managing alarms (iOS 12 and iOS 13). 4 | // 5 | // Created by Joshua Seltzer on 3/16/2019. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | #import "../common/SLPrefsManager.h" 11 | 12 | // alarm manager used in modern versions of iOS 13 | %hook MTAlarmManager 14 | 15 | - (id)removeAlarm:(MTMutableAlarm *)alarm 16 | { 17 | // delete the attributes for this given alarm 18 | [SLPrefsManager deleteAlarmForAlarmId:[alarm alarmIDString]]; 19 | 20 | return %orig; 21 | } 22 | 23 | - (id)updateAlarm:(MTMutableAlarm *)alarm 24 | { 25 | // proceed to potentially update the alarm's Sleeper preferences if the update wasn't initiated by the tweak itself 26 | if (!alarm.SLWasUpdatedBySleeper) { 27 | // check if we have alarm preferences for this alarm 28 | NSString *alarmId = [alarm alarmIDString]; 29 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 30 | if (alarmPrefs && alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 31 | // reset the skip activation status for this alarm 32 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 33 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 34 | } else if (!alarmPrefs) { 35 | alarmPrefs = [[SLAlarmPrefs alloc] initWithAlarmId:alarmId]; 36 | [SLPrefsManager saveAlarmPrefs:alarmPrefs]; 37 | } 38 | } 39 | 40 | return %orig; 41 | } 42 | 43 | %end 44 | 45 | %ctor { 46 | // only initialize this file for particular versions 47 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13 || kSLSystemVersioniOS12) { 48 | %init(); 49 | } 50 | } -------------------------------------------------------------------------------- /core/SLMTAlarmStorage.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTAlarmStorage.x 3 | // Handles the modification of the snooze time for alarms on iOS 12 and iOS 13. 4 | // 5 | // Created by Joshua Seltzer on 3/20/2019. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | 11 | @interface MTAlarmStorage : NSObject 12 | 13 | // returns the currently active Sleep (i.e. "Wake Up") alarm (iOS 14) 14 | - (MTAlarm *)activeSleepAlarm; 15 | 16 | @end 17 | 18 | %hook MTAlarmStorage 19 | 20 | // invoked when an alarm is snoozed 21 | - (void)snoozeAlarmWithIdentifier:(NSString *)alarmId snoozeDate:(NSDate *)snoozeDate snoozeAction:(int)snoozeAction withCompletion:(id)completionHandler source:(id)source 22 | { 23 | // on iOS 14, the alarm ID for the "Wake Up" alarm might not be the same 24 | NSString *sleeperAlarmId = alarmId; 25 | if (kSLSystemVersioniOS14 && [[[self activeSleepAlarm] alarmIDString] isEqualToString:alarmId]) { 26 | sleeperAlarmId = [SLCompatibilityHelper wakeUpAlarmId]; 27 | } 28 | 29 | // check to see if a modified snooze date is available for this alarm 30 | NSDate *modifiedSnoozeDate = [SLCompatibilityHelper modifiedSnoozeDateForAlarmId:sleeperAlarmId withOriginalDate:snoozeDate]; 31 | if (modifiedSnoozeDate) { 32 | %orig(alarmId, modifiedSnoozeDate, snoozeAction, completionHandler, source); 33 | } else { 34 | %orig; 35 | } 36 | } 37 | 38 | %end 39 | 40 | %ctor { 41 | // only initialize this file for particular versions 42 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13 || kSLSystemVersioniOS12) { 43 | %init(); 44 | } 45 | } -------------------------------------------------------------------------------- /core/SLMTUserNotificationCenter.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTUserNotificationCenter.x 3 | // Handles the posting of notifications for a scheduled alarm (iOS 12, iOS 13). 4 | // 5 | // Created by Joshua Seltzer on 3/20/2019. 6 | // 7 | // 8 | 9 | #import "../common/SLPrefsManager.h" 10 | #import "../common/SLAlarmPrefs.h" 11 | #import "../common/SLCompatibilityHelper.h" 12 | 13 | // trigger object which signifies why an alarm was fired 14 | @interface MTTrigger : NSObject 15 | 16 | // signifies whether or not this trigger is for an alert 17 | @property (readonly, nonatomic) BOOL isForAlert; 18 | 19 | // signifies whether or not this trigger is from snooze 20 | @property (readonly, nonatomic) BOOL isForSnooze; 21 | 22 | @end 23 | 24 | // protocol defining a schedulable object 25 | @protocol MTScheduleable 26 | 27 | // the identifier for the scheduleable object, which is the alarm Id in this case 28 | - (NSString *)identifier; 29 | 30 | @end 31 | 32 | // the scheduled object that will be fired when a notification is about to be posted 33 | @interface MTScheduledObject : NSObject 34 | 35 | // the trigger that invoked this scheduled object 36 | @property (copy, nonatomic) MTTrigger *trigger; 37 | 38 | // the schedulable object, which in this case is an MTAlarm object 39 | @property (copy, nonatomic) id scheduleable; 40 | 41 | @end 42 | 43 | %hook MTUserNotificationCenter 44 | 45 | // Invoked whenever the content for a scheduled alarm notification is going to be created. Override this function 46 | // to potentially set no content for the notification if we are to skip the alarm. 47 | + (void)_setSpecificContent:(UNMutableNotificationContent *)notificationContent forScheduledAlarm:(MTScheduledObject *)scheduledObject 48 | { 49 | // check to see if the alarm's trigger is an alert (as opposed to a snooze alert or snooze countdown) 50 | if (scheduledObject.trigger.isForAlert && !scheduledObject.trigger.isForSnooze && scheduledObject.scheduleable != nil) { 51 | // get the identifier for the scheduled object, which is in fact the alarm Id 52 | NSString *alarmId = [scheduledObject.scheduleable identifier]; 53 | 54 | // on iOS 14, the alarm ID for the "Wake Up" alarm might not be the same 55 | NSString *sleeperAlarmId = alarmId; 56 | if (kSLSystemVersioniOS14 && [(MTAlarm *)scheduledObject.scheduleable isSleepAlarm]) { 57 | sleeperAlarmId = [SLCompatibilityHelper wakeUpAlarmId]; 58 | } 59 | 60 | // get the sleeper alarm preferences for this alarm 61 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:sleeperAlarmId]; 62 | if (alarmPrefs) { 63 | // only activate the actual alarm if we should not be skipping this alarm 64 | if (![alarmPrefs shouldSkipToday]) { 65 | %orig; 66 | } 67 | 68 | // save the alarm's skip activation state to unknown for this alarm 69 | if (alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 70 | [SLPrefsManager setSkipActivatedStatusForAlarmId:sleeperAlarmId 71 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 72 | } 73 | } else { 74 | %orig; 75 | } 76 | } else { 77 | %orig; 78 | } 79 | } 80 | 81 | %end 82 | 83 | %ctor { 84 | // only initialize this file for particular versions 85 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13 || kSLSystemVersioniOS12) { 86 | %init(); 87 | } 88 | } -------------------------------------------------------------------------------- /core/SLSBDashBoardLockScreenEnvironment.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBDashBoardLockScreenEnvironment.x 3 | // Hooks into this class allow for actions to be performed upon unlocking the device (iOS 13+). 4 | // 5 | // Created by Joshua Seltzer on 11/17/19. 6 | // 7 | // 8 | 9 | #import "../common/SLSkipAlarmAlertItem.h" 10 | #import "../common/SLAlarmPrefs.h" 11 | #import "../common/SLCompatibilityHelper.h" 12 | 13 | %hook SBDashBoardLockScreenEnvironment 14 | 15 | // iOS 13+: override to display a pop up allowing the user to skip an alarm 16 | - (void)prepareForUIUnlock 17 | { 18 | %orig; 19 | 20 | // check first to see if an existing skip alarm alert is being shown 21 | SBAlertItemsController *alertItemsController = (SBAlertItemsController *)[objc_getClass("SBAlertItemsController") sharedInstance]; 22 | if (![alertItemsController hasAlertOfClass:objc_getClass("SLSkipAlarmAlertItem")]) { 23 | // get dates for today and tomorrow so we can properly determine if any of those alarms need to be skipped 24 | NSDate *today = [NSDate date]; 25 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 26 | dateComponents.day = 1; 27 | NSCalendar *calendar = [NSCalendar currentCalendar]; 28 | NSDate *tomorrow = [calendar dateByAddingComponents:dateComponents toDate:[calendar startOfDayForDate:today] options:0]; 29 | 30 | // get the list of next alarms for today and tomorrow from the alarm manager 31 | MTAlarmManager *alarmManager = [[objc_getClass("MTAlarmManager") alloc] init]; 32 | NSArray *nextAlarmsToday = [alarmManager nextAlarmsForDateSync:today maxCount:500 includeSleepAlarm:YES includeBedtimeNotification:NO]; 33 | NSArray *nextAlarmsTomorrow = [alarmManager nextAlarmsForDateSync:tomorrow maxCount:500 includeSleepAlarm:YES includeBedtimeNotification:NO]; 34 | NSArray *nextAlarms = [[NSOrderedSet orderedSetWithArray:[nextAlarmsToday arrayByAddingObjectsFromArray:nextAlarmsTomorrow]] array]; 35 | 36 | // Iterate through the MTAlarm (and MTMutableAlarm) objects to see if any are skippable. The alarm objects should already be sorted. 37 | NSString *alarmTitle = nil; 38 | NSString *sleeperAlarmId = nil; 39 | NSDate *nextFireDate = nil; 40 | BOOL foundSkippableAlarm = NO; 41 | for (MTAlarm *alarm in nextAlarms) { 42 | // check first if this alarm is being snoozed 43 | if (!alarm.snoozed) { 44 | // on iOS 14, the alarm ID for the "Wake Up" alarm might not be the same 45 | sleeperAlarmId = [alarm alarmIDString]; 46 | if (kSLSystemVersioniOS14 && [alarm isSleepAlarm]) { 47 | sleeperAlarmId = [SLCompatibilityHelper wakeUpAlarmId]; 48 | } 49 | 50 | // check to see if this alarm is actually skippable 51 | nextFireDate = [alarm nextFireDateAfterDate:today includeBedtimeNotification:NO]; 52 | BOOL isAlarmSkippable = [SLCompatibilityHelper isAlarmSkippableForAlarmId:sleeperAlarmId withNextFireDate:nextFireDate]; 53 | if (isAlarmSkippable) { 54 | foundSkippableAlarm = YES; 55 | alarmTitle = [SLCompatibilityHelper alarmTitleForMTAlarm:alarm]; 56 | break; 57 | } 58 | } 59 | } 60 | if (foundSkippableAlarm) { 61 | // after a slight delay, show an alert that will ask the user to skip the alarm on the main thread 62 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)); 63 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 64 | // create and display the custom alert item 65 | SLSkipAlarmAlertItem *alert = [[objc_getClass("SLSkipAlarmAlertItem") alloc] initWithTitle:alarmTitle 66 | alarmId:sleeperAlarmId 67 | nextFireDate:nextFireDate]; 68 | [alertItemsController activateAlertItem:alert animated:YES]; 69 | }); 70 | } 71 | } 72 | } 73 | 74 | %end 75 | 76 | %ctor { 77 | // check which version we are running to determine which group to initialize 78 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13) { 79 | %init(); 80 | } 81 | } -------------------------------------------------------------------------------- /core/SLSBLockScreenViewControllerBase.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBLockScreenViewControllerBase.x 3 | // Hooks into this class allow for actions to be performed upon unlocking the device (iOS 12). 4 | // 5 | // Created by Joshua Seltzer on 4/12/19. 6 | // 7 | // 8 | 9 | #import "../common/SLSkipAlarmAlertItem.h" 10 | #import "../common/SLCompatibilityHelper.h" 11 | 12 | %hook SBLockScreenViewControllerBase 13 | 14 | // iOS 12: override to display a pop up allowing the user to skip an alarm 15 | - (void)prepareForUIUnlock 16 | { 17 | %orig; 18 | 19 | // check first to see if an existing skip alarm alert is being shown 20 | SBAlertItemsController *alertItemsController = (SBAlertItemsController *)[objc_getClass("SBAlertItemsController") sharedInstance]; 21 | if (![alertItemsController hasAlertOfClass:objc_getClass("SLSkipAlarmAlertItem")]) { 22 | // get dates for today and tomorrow so we can properly determine if any of those alarms need to be skipped 23 | NSDate *today = [NSDate date]; 24 | NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; 25 | dateComponents.day = 1; 26 | NSCalendar *calendar = [NSCalendar currentCalendar]; 27 | NSDate *tomorrow = [calendar dateByAddingComponents:dateComponents toDate:[calendar startOfDayForDate:today] options:0]; 28 | 29 | // get the list of next alarms for today and tomorrow from the alarm manager 30 | MTAlarmManager *alarmManager = [[objc_getClass("MTAlarmManager") alloc] init]; 31 | NSArray *nextAlarmsToday = [alarmManager nextAlarmsForDateSync:today maxCount:500 includeSleepAlarm:YES includeBedtimeNotification:NO]; 32 | NSArray *nextAlarmsTomorrow = [alarmManager nextAlarmsForDateSync:tomorrow maxCount:500 includeSleepAlarm:YES includeBedtimeNotification:NO]; 33 | NSArray *nextAlarms = [[NSOrderedSet orderedSetWithArray:[nextAlarmsToday arrayByAddingObjectsFromArray:nextAlarmsTomorrow]] array]; 34 | 35 | // Iterate through the MTAlarm (and MTMutableAlarm) objects to see if any are skippable. The alarm objects should already be sorted. 36 | NSString *alarmTitle = nil; 37 | NSString *alarmId = nil; 38 | NSDate *nextFireDate = nil; 39 | BOOL foundSkippableAlarm = NO; 40 | for (MTAlarm *alarm in nextAlarms) { 41 | // check first if this alarm is being snoozed 42 | if (!alarm.snoozed) { 43 | alarmId = [alarm alarmIDString]; 44 | nextFireDate = [alarm nextFireDateAfterDate:today includeBedtimeNotification:NO]; 45 | BOOL isAlarmSkippable = [SLCompatibilityHelper isAlarmSkippableForAlarmId:alarmId withNextFireDate:nextFireDate]; 46 | if (isAlarmSkippable) { 47 | foundSkippableAlarm = YES; 48 | alarmTitle = [SLCompatibilityHelper alarmTitleForMTAlarm:alarm]; 49 | break; 50 | } 51 | } 52 | } 53 | if (foundSkippableAlarm) { 54 | // after a slight delay, show an alert that will ask the user to skip the alarm on the main thread 55 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)); 56 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 57 | // create and display the custom alert item 58 | SLSkipAlarmAlertItem *alert = [[objc_getClass("SLSkipAlarmAlertItem") alloc] initWithTitle:alarmTitle 59 | alarmId:alarmId 60 | nextFireDate:nextFireDate]; 61 | [alertItemsController activateAlertItem:alert animated:YES]; 62 | }); 63 | } 64 | } 65 | } 66 | 67 | %end 68 | 69 | %ctor { 70 | // check which version we are running to determine which group to initialize 71 | if (kSLSystemVersioniOS12) { 72 | %init(); 73 | } 74 | } -------------------------------------------------------------------------------- /core_legacy/SLAlarmManager.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLAlarmManager.x 3 | // Modify Apple's internal class for managing alarms. 4 | // 5 | // Created by Joshua Seltzer on 2/22/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | #import "../common/SLPrefsManager.h" 11 | 12 | // utilized in iOS 8, iOS 9, iOS 10, and iOS 11 13 | %hook AlarmManager 14 | 15 | - (void)removeAlarm:(Alarm *)alarm 16 | { 17 | %orig; 18 | 19 | // delete the attributes for this given alarm 20 | [SLPrefsManager deleteAlarmForAlarmId:[SLCompatibilityHelper alarmIdForAlarm:alarm]]; 21 | } 22 | 23 | - (void)setAlarm:(Alarm *)alarm active:(BOOL)active 24 | { 25 | %orig; 26 | 27 | // get the alarm Id for the alarm 28 | NSString *alarmId = [SLCompatibilityHelper alarmIdForAlarm:alarm]; 29 | 30 | // check if we have alarm preferences for this alarm 31 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 32 | if (alarmPrefs && alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 33 | // reset the skip activation status for this alarm 34 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 35 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 36 | } else if (!alarmPrefs) { 37 | alarmPrefs = [[SLAlarmPrefs alloc] initWithAlarmId:alarmId]; 38 | [SLPrefsManager saveAlarmPrefs:alarmPrefs]; 39 | } 40 | } 41 | 42 | %end 43 | 44 | %ctor { 45 | // only initialize this file if we are on iOS 8, iOS 9, iOS 10, or iOS 11 46 | if (kSLSystemVersioniOS8 || kSLSystemVersioniOS9 || kSLSystemVersioniOS10 || kSLSystemVersioniOS11) { 47 | %init(); 48 | } 49 | } -------------------------------------------------------------------------------- /core_legacy/SLSBApplication.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBApplication.x 3 | // Hook into the SBApplication class to modify the snooze notification on iOS 8. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | 11 | %hook SBApplication 12 | 13 | // iOS 8: override to insert our custom snooze time if it was defined 14 | - (void)scheduleSnoozeNotification:(UIConcreteLocalNotification *)notification 15 | { 16 | // attempt to modify the notification with a custom snooze time 17 | [SLCompatibilityHelper modifySnoozeNotificationForLocalNotification:notification]; 18 | 19 | %orig; 20 | } 21 | 22 | %end 23 | 24 | %ctor { 25 | // only initialize this file if we are on iOS 8 26 | if (kSLSystemVersioniOS8) { 27 | %init(); 28 | } 29 | } -------------------------------------------------------------------------------- /core_legacy/SLSBClockDataProvider.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBClockDataProvider.x 3 | // Hook into the SBClockDataProvider class to potentially skip an alarm notification. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | #import "../common/SLPrefsManager.h" 11 | 12 | %group iOS10iOS11 13 | 14 | %hook SBClockDataProvider 15 | 16 | // iOS 10 / iOS 11: invoked when an alarm alert (i.e. bulletin) is about to be displayed 17 | - (void)_publishBulletinForNotification:(UNNotification *)notification 18 | { 19 | // grab the shared instance of the clock data provider 20 | SBClockDataProvider *clockDataProvider = [objc_getClass("SBClockDataProvider") sharedInstance]; 21 | 22 | // check to see if this notification is an alarm notification 23 | if ([clockDataProvider _isAlarmNotification:notification]) { 24 | // get the alarm Id from the notification 25 | NSString *alarmId = [clockDataProvider _alarmIDFromNotificationRequest:notification.request]; 26 | 27 | // get the sleeper alarm preferences for this alarm 28 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 29 | if (alarmPrefs) { 30 | // only activate the actual alarm if we should not be skipping this alarm 31 | if (![alarmPrefs shouldSkipToday]) { 32 | %orig; 33 | } 34 | 35 | // save the alarm's skip activation state to unknown for this alarm 36 | if (alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 37 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 38 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 39 | } 40 | } else { 41 | %orig; 42 | } 43 | } else { 44 | %orig; 45 | } 46 | } 47 | 48 | %end 49 | 50 | %end // %group iOS10iOS11 51 | 52 | %group iOS8iOS9 53 | 54 | %hook SBClockDataProvider 55 | 56 | // iOS 8 / iOS 9: invoked when an alarm alert (i.e. bulletin) is about to be displayed 57 | - (void)_publishBulletinForLocalNotification:(UIConcreteLocalNotification *)notification 58 | { 59 | // grab the shared instance of the clock data provider 60 | SBClockDataProvider *clockDataProvider = [objc_getClass("SBClockDataProvider") sharedInstance]; 61 | 62 | // check to see if this notification is an alarm notification 63 | if ([clockDataProvider _isAlarmNotification:notification]) { 64 | // get the alarm Id from the notification 65 | NSString *alarmId = [clockDataProvider _alarmIDFromNotification:notification]; 66 | 67 | // get the sleeper alarm preferences for this alarm 68 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 69 | if (alarmPrefs) { 70 | // check to see if this alarm should be skipped 71 | if ([alarmPrefs shouldSkipToday]) { 72 | // grab the alarm that we are going to ask to skip from the shared alarm manager 73 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 74 | [alarmManager loadAlarms]; 75 | Alarm *alarm = [alarmManager alarmWithId:alarmId]; 76 | 77 | // simulate the alarm going off 78 | [alarm handleAlarmFired:notification]; 79 | [alarmManager handleNotificationFired:notification]; 80 | } else { 81 | %orig; 82 | } 83 | 84 | // save the alarm's skip activation state to unknown for this alarm 85 | if (alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 86 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 87 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 88 | } 89 | } else { 90 | %orig; 91 | } 92 | } else { 93 | %orig; 94 | } 95 | } 96 | 97 | %end 98 | 99 | %end // %group iOS8iOS9 100 | 101 | %ctor { 102 | // check which version we are running to determine which group to initialize 103 | if (kSLSystemVersioniOS10 || kSLSystemVersioniOS11) { 104 | %init(iOS10iOS11); 105 | } else if (kSLSystemVersioniOS8 || kSLSystemVersioniOS9) { 106 | %init(iOS8iOS9); 107 | } 108 | } -------------------------------------------------------------------------------- /core_legacy/SLSBLockScreenManager.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBLockScreenManager.x 3 | // Hook into the SBLockScreenManager class to potentially show an alert after unlocking the device. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLSkipAlarmAlertItem.h" 10 | #import "../common/SLCompatibilityHelper.h" 11 | 12 | %hook SBLockScreenManager 13 | 14 | // iOS 10: override to display a pop up allowing the user to skip an alarm 15 | - (void)_finishUIUnlockFromSource:(int)source withOptions:(id)options 16 | { 17 | %orig; 18 | 19 | // check first to see if an existing skip alarm alert is being shown 20 | SBAlertItemsController *alertItemsController = (SBAlertItemsController *)[objc_getClass("SBAlertItemsController") sharedInstance]; 21 | if (![alertItemsController hasAlertOfClass:objc_getClass("SLSkipAlarmAlertItem")]) { 22 | // create the block that will be used to inspect the notification requests from the clock notification manager 23 | void (^clockNotificationManagerNotificationRequests) (NSArray *) = ^(NSArray *notificationRequests) { 24 | // only continue if valid notification requests were returned 25 | if (notificationRequests.count > 0) { 26 | // attempt to get the next skippable alarm notification request from the notification requests returned 27 | UNNotificationRequest *nextAlarmNotificationRequest = [SLCompatibilityHelper nextSkippableAlarmNotificationRequestForNotificationRequests:notificationRequests]; 28 | 29 | // if we found a valid alarm, check to see if we should ask to skip it 30 | if (nextAlarmNotificationRequest != nil) { 31 | // grab the shared instance of the clock data provider 32 | SBClockDataProvider *clockDataProvider = [objc_getClass("SBClockDataProvider") sharedInstance]; 33 | 34 | // grab the alarm Id for this notification request 35 | NSString *alarmId = [clockDataProvider _alarmIDFromNotificationRequest:nextAlarmNotificationRequest]; 36 | 37 | // grab the shared instance of the alarm manager, load the alarms, and get the alarm object 38 | // that is associated with this notification request 39 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 40 | [alarmManager loadAlarms]; 41 | Alarm *alarm = [alarmManager alarmWithId:alarmId]; 42 | 43 | // after a slight delay, show an alert that will ask the user to skip the alarm on the main thread 44 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)); 45 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 46 | // get the fire date of the alarm we are going to display 47 | NSDate *nextTriggerDate = [((UNLegacyNotificationTrigger *)nextAlarmNotificationRequest.trigger) _nextTriggerDateAfterDate:[NSDate date] 48 | withRequestedDate:nil 49 | defaultTimeZone:[NSTimeZone localTimeZone]]; 50 | 51 | // create and display the custom alert item 52 | SLSkipAlarmAlertItem *alert = [[objc_getClass("SLSkipAlarmAlertItem") alloc] initWithTitle:[SLCompatibilityHelper alarmTitleForAlarm:alarm] 53 | alarmId:alarmId 54 | nextFireDate:nextTriggerDate]; 55 | [alertItemsController activateAlertItem:alert animated:YES]; 56 | }); 57 | } 58 | } 59 | }; 60 | 61 | // get the clock notification manager and get the notification requests 62 | SBClockNotificationManager *clockNotificationManager = [objc_getClass("SBClockNotificationManager") sharedInstance]; 63 | [clockNotificationManager getPendingNotificationRequestsWithCompletionHandler:clockNotificationManagerNotificationRequests]; 64 | } 65 | } 66 | 67 | %end 68 | 69 | %ctor { 70 | if (kSLSystemVersioniOS10) { 71 | %init(); 72 | } 73 | } -------------------------------------------------------------------------------- /core_legacy/SLSBLockScreenViewController.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBLockScreenViewController.x 3 | // Hook into the SBLockScreenViewController class to potentially show an alert after unlocking the device for iOS 8 or iOS 9. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLSkipAlarmAlertItem.h" 10 | #import "../common/SLCompatibilityHelper.h" 11 | 12 | %hook SBLockScreenViewController 13 | 14 | // iOS 8 / iOS 9: override to display a pop up allowing the user to skip an alarm 15 | - (void)finishUIUnlockFromSource:(int)source 16 | { 17 | %orig; 18 | 19 | // check first to see if an existing skip alarm alert is being shown 20 | SBAlertItemsController *alertItemsController = (SBAlertItemsController *)[objc_getClass("SBAlertItemsController") sharedInstance]; 21 | if (![alertItemsController hasAlertOfClass:objc_getClass("SLSkipAlarmAlertItem")]) { 22 | // grab the shared instance of the clock data provider 23 | SBClockDataProvider *clockDataProvider = [objc_getClass("SBClockDataProvider") sharedInstance]; 24 | 25 | // attempt to get the next skippable alarm notification 26 | UIConcreteLocalNotification *nextAlarmNotification = [SLCompatibilityHelper nextSkippableAlarmLocalNotification]; 27 | 28 | // if we found a valid alarm, check to see if we should ask to skip it 29 | if (nextAlarmNotification != nil) { 30 | // grab the alarm Id for this notification 31 | NSString *alarmId = [clockDataProvider _alarmIDFromNotification:nextAlarmNotification]; 32 | 33 | // grab the shared instance of the alarm manager and load the alarms 34 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 35 | [alarmManager loadAlarms]; 36 | Alarm *alarm = [alarmManager alarmWithId:alarmId]; 37 | 38 | // after a slight delay, show an alert that will ask the user to skip the alarm 39 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)); 40 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 41 | // get the fire date of the alarm we are going to display 42 | NSDate *alarmFireDate = [nextAlarmNotification nextFireDateAfterDate:[NSDate date] 43 | localTimeZone:[NSTimeZone localTimeZone]]; 44 | 45 | // create and display the custom alert item 46 | SLSkipAlarmAlertItem *alert = [[objc_getClass("SLSkipAlarmAlertItem") alloc] initWithTitle:[SLCompatibilityHelper alarmTitleForAlarm:alarm] 47 | alarmId:alarmId 48 | nextFireDate:alarmFireDate]; 49 | [alertItemsController activateAlertItem:alert animated:YES]; 50 | }); 51 | } 52 | } 53 | } 54 | 55 | %end 56 | 57 | %ctor { 58 | // only initialize this file if we are on iOS 8 or iOS 9 59 | if (kSLSystemVersioniOS8 || kSLSystemVersioniOS9) { 60 | %init(); 61 | } 62 | } -------------------------------------------------------------------------------- /core_legacy/SLSBLockScreenViewControllerBase.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLSBLockScreenViewControllerBase.x 3 | // Hooks into this class allow for actions to be performed upon unlocking the device (iOS 11). 4 | // 5 | // Created by Joshua Seltzer on 4/12/19. 6 | // 7 | // 8 | 9 | #import "../common/SLSkipAlarmAlertItem.h" 10 | #import "../common/SLCompatibilityHelper.h" 11 | 12 | %hook SBLockScreenViewControllerBase 13 | 14 | // iOS 11: override to display a pop up allowing the user to skip an alarm 15 | - (void)prepareForUIUnlock 16 | { 17 | // check first to see if an existing skip alarm alert is being shown 18 | SBAlertItemsController *alertItemsController = (SBAlertItemsController *)[objc_getClass("SBAlertItemsController") sharedInstance]; 19 | if (![alertItemsController hasAlertOfClass:objc_getClass("SLSkipAlarmAlertItem")]) { 20 | // create the block that will be used to inspect the notification requests from the clock notification manager 21 | void (^clockNotificationManagerNotificationRequests) (NSArray *) = ^(NSArray *notificationRequests) { 22 | // only continue if valid notification requests were returned 23 | if (notificationRequests.count > 0) { 24 | // attempt to get the next skippable alarm notification request from the notification requests returned 25 | UNNotificationRequest *nextAlarmNotificationRequest = [SLCompatibilityHelper nextSkippableAlarmNotificationRequestForNotificationRequests:notificationRequests]; 26 | 27 | // if we found a valid alarm, check to see if we should ask to skip it 28 | if (nextAlarmNotificationRequest != nil) { 29 | // grab the shared instance of the clock data provider 30 | SBClockDataProvider *clockDataProvider = [objc_getClass("SBClockDataProvider") sharedInstance]; 31 | 32 | // grab the alarm Id for this notification request 33 | NSString *alarmId = [clockDataProvider _alarmIDFromNotificationRequest:nextAlarmNotificationRequest]; 34 | 35 | // grab the shared instance of the alarm manager, load the alarms, and get the alarm object 36 | // that is associated with this notification request 37 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 38 | [alarmManager loadAlarms]; 39 | Alarm *alarm = [alarmManager alarmWithId:alarmId]; 40 | 41 | // after a slight delay, show an alert that will ask the user to skip the alarm on the main thread 42 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)); 43 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 44 | // get the fire date of the alarm we are going to display 45 | NSDate *nextTriggerDate = [((UNLegacyNotificationTrigger *)nextAlarmNotificationRequest.trigger) _nextTriggerDateAfterDate:[NSDate date] 46 | withRequestedDate:nil 47 | defaultTimeZone:[NSTimeZone localTimeZone]]; 48 | 49 | // create and display the custom alert item 50 | SLSkipAlarmAlertItem *alert = [[objc_getClass("SLSkipAlarmAlertItem") alloc] initWithTitle:[SLCompatibilityHelper alarmTitleForAlarm:alarm] 51 | alarmId:alarmId 52 | nextFireDate:nextTriggerDate]; 53 | [alertItemsController activateAlertItem:alert animated:YES]; 54 | }); 55 | } 56 | } 57 | }; 58 | 59 | // get the clock notification manager and get the notification requests 60 | SBClockNotificationManager *clockNotificationManager = [objc_getClass("SBClockNotificationManager") sharedInstance]; 61 | [clockNotificationManager getPendingNotificationRequestsWithCompletionHandler:clockNotificationManagerNotificationRequests]; 62 | } 63 | } 64 | 65 | %end 66 | 67 | %ctor { 68 | // check which version we are running to determine which group to initialize 69 | if (kSLSystemVersioniOS11) { 70 | %init(); 71 | } 72 | } -------------------------------------------------------------------------------- /core_legacy/SLUNLocalNotificationClient.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLUNLocalNotificationClient.x 3 | // Hook into the UNLocalNotificationClient class to modify the snooze notification on iOS 9. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | 11 | %hook UNLocalNotificationClient 12 | 13 | // iOS 9: override to insert our custom snooze time if it was defined 14 | - (void)scheduleSnoozeNotification:(UIConcreteLocalNotification *)notification 15 | { 16 | // attempt to modify the notification with a custom snooze time 17 | [SLCompatibilityHelper modifySnoozeNotificationForLocalNotification:notification]; 18 | 19 | %orig; 20 | } 21 | 22 | %end 23 | 24 | %ctor { 25 | // only initialize this file if we are on iOS 9 26 | if (kSLSystemVersioniOS9) { 27 | %init(); 28 | } 29 | } -------------------------------------------------------------------------------- /core_legacy/SLUNSNotificationSchedulingService.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLUNSNotificationSchedulingService.x 3 | // Hook into the UNSNotificationSchedulingService class to modify the snooze notification on iOS 10 and iOS 11. 4 | // 5 | // Created by Joshua Seltzer on 2/23/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCompatibilityHelper.h" 10 | 11 | %hook UNSNotificationSchedulingService 12 | 13 | // iOS 10 / iOS 11: function that adds new notification records to the scheduling service 14 | - (void)addPendingNotificationRecords:(NSArray *)notificationRecords forBundleIdentifier:(NSString *)bundleId withCompletionHandler:(id)completionHandler 15 | { 16 | // check to see if the notification is for the timer application 17 | if ([bundleId isEqualToString:@"com.apple.mobiletimer"]) { 18 | // iterate through the notification records 19 | for (UNSNotificationRecord *notification in notificationRecords) { 20 | // check to see if the notification is a snooze notification 21 | if ([notification isFromSnooze]) { 22 | // modify the snooze notifications with the updated snooze times 23 | [SLCompatibilityHelper modifySnoozeNotificationForNotificationRecord:notification]; 24 | } 25 | } 26 | } 27 | 28 | %orig; 29 | } 30 | 31 | %end 32 | 33 | %ctor { 34 | // only initialize this file if we are on iOS 10 or iOS 11 35 | if (kSLSystemVersioniOS10 || kSLSystemVersioniOS11) { 36 | %init(); 37 | } 38 | } -------------------------------------------------------------------------------- /holiday_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | import re 6 | import datetime 7 | import holidays 8 | import plistlib 9 | 10 | # years which will be generated for any given country 11 | START_YEAR = 2023 12 | END_YEAR = 2050 13 | 14 | # constants used to modify holidays upon generation 15 | OBSERVED_TEXT = "(Observed)" 16 | THANKSGIVING_TEXT = "Thanksgiving" 17 | DAY_AFTER_THANKSGIVING_TEXT = "Day After Thanksgiving" 18 | MARTIN_LUTHER_KING_JR_TEXT = "Martin Luther King, Jr. Day" 19 | CHRISTMAS_DAY_TEXT = "Christmas Day" 20 | CHRISTMAS_EVE_TEXT = "Christmas Eve" 21 | NEW_YEARS_DAY_TEXT = "New Year's Day" 22 | NEW_YEARS_EVE_TEXT = "New Year's Eve" 23 | 24 | # path to the Sleeper bundle which is used to store the holidays and localized strings 25 | SLEEPER_BUNDLE_PATH = "layout/Library/Application Support/Sleeper.bundle" 26 | 27 | # names of the keys that will be used when creating the plist 28 | DATE_CREATED_KEY = "dateCreated" 29 | HOLIDAYS_KEY = "holidays" 30 | NAME_KEY = "name" 31 | DATES_KEY = "dates" 32 | 33 | # entry point for creating the holidays for a particular country 34 | def gen_country_holidays(country_code): 35 | print("Generating holiday plist file for \"{0}\" from years {1} to {2}.".format(country_code, START_YEAR, END_YEAR)) 36 | 37 | # define the high-level plist file and holiday mapping which will be generated for this country 38 | country_holidays = [] 39 | holiday_map = {} 40 | 41 | # iterate through each year one by one 42 | years = list(range(START_YEAR, END_YEAR)) 43 | for year in years: 44 | # generate the list of holidays for the given country code (if valid) for the iterated year 45 | try: 46 | global holidays_for_year 47 | exec("holidays_for_year = holidays.{0}(observed=True, expand=False, years=[{1}])".format(country_code, year), globals()) 48 | except AttributeError: 49 | print("Entered invalid country code, exiting.") 50 | exit(1) 51 | 52 | if year == START_YEAR: 53 | print(holidays_for_year) 54 | print("This country has {0} holidays.".format(len(holidays_for_year))) 55 | 56 | # iterate through the generated holidays to potentially remove holidays 57 | holidays_to_remove = [] 58 | for date, name in holidays_for_year.items(): 59 | # mark any non-observed holidays for removal 60 | if OBSERVED_TEXT in name: 61 | holiday_to_remove = name.replace(OBSERVED_TEXT, "").strip() 62 | holidays_to_remove.append(holiday_to_remove) 63 | print("Attempting to remove holiday \"{0}\" since this is an observed holiday in {1}.".format(holiday_to_remove, year)) 64 | holidays_for_year = {date:name.replace(OBSERVED_TEXT, "").strip() for date, name in holidays_for_year.items() if name not in holidays_to_remove or date.weekday() < 5} 65 | 66 | if year == START_YEAR: 67 | print("After removing observed holidays, this country has {0} holidays.".format(len(holidays_for_year))) 68 | 69 | # add additional holidays for particular countries 70 | holidays_for_year.update(generate_additional_holidays(country_code, year, holidays_for_year)) 71 | 72 | # final pass of the holidays for the given year to add them to the plist 73 | for date, combined_names in sorted(holidays_for_year.items()): 74 | # remove some extra text in between brackets from the name 75 | combined_names = re.sub(r"\[.*?\]", "", combined_names) 76 | 77 | # check to see if the name needs to be split (the holidays library will combine the same dates with a combined name) 78 | for name in combined_names.split(', '): 79 | # remove any additional leading and trailing whitespace 80 | name = name.strip() 81 | 82 | # update the holiday map with the added holiday 83 | date_time = datetime.datetime.combine(date, datetime.time(0, 0)).astimezone(datetime.timezone.utc) 84 | dates = holiday_map.get(name) 85 | if not dates: 86 | dates = [date_time] 87 | elif date_time not in dates: 88 | dates.append(date_time) 89 | holiday_map.update({name:dates}) 90 | 91 | # get the current datetime in UTC timezone 92 | now = datetime.datetime.now().astimezone(datetime.timezone.utc) 93 | 94 | # generate the plist 95 | for name in holiday_map.keys(): 96 | # get all of the parts for the dictionary that will be added to the plist 97 | dates = holiday_map.get(name) 98 | 99 | # convert the datetime objects to date strings and remove any past dates 100 | date_strings = [] 101 | for date in dates: 102 | if date >= now: 103 | date_strings.append(date.strftime('%Y-%m-%d')) 104 | 105 | # add a new entry to the plist 106 | country_holidays.append({NAME_KEY:name, DATES_KEY:date_strings}) 107 | 108 | # create the root of the plist 109 | plist_root = {DATE_CREATED_KEY:now, "holidays":country_holidays} 110 | 111 | # write the final plist to file 112 | plist_file_path = os.path.join(SLEEPER_BUNDLE_PATH, "{0}_holidays.plist".format(country_code.lower())) 113 | with open(plist_file_path, 'wb') as fp: 114 | plistlib.dump(plist_root, fp, sort_keys=False) 115 | 116 | print("Wrote results to file: {0}".format(plist_file_path)) 117 | print("Holiday list generation completed for \"{0}\" from years {1} to {2}.".format(country_code, START_YEAR, END_YEAR)) 118 | 119 | # creates new holidays for particular countries 120 | def generate_additional_holidays(country_code, year, holidays_for_year): 121 | new_holidays = {} 122 | 123 | if country_code == 'US': 124 | # add new holidays which have different dates each year 125 | for date, name in holidays_for_year.items(): 126 | if THANKSGIVING_TEXT in name: 127 | print("Adding additional holiday, \"{0}\" for {1}.".format(DAY_AFTER_THANKSGIVING_TEXT, year)) 128 | new_holidays.update({date + datetime.timedelta(days=1):DAY_AFTER_THANKSGIVING_TEXT}) 129 | 130 | if MARTIN_LUTHER_KING_JR_TEXT in name: 131 | print("Fixing Martin Luther King Jr. Day") 132 | new_holidays.update({date:"Martin Luther King Jr. Day"}) 133 | 134 | # add New Year's Eve and Christmas Eve which are static each year 135 | print("Adding additional holiday, \"{0}\" for {1}.".format(CHRISTMAS_EVE_TEXT, year)) 136 | print("Adding additional holiday, \"{0}\" for {1}.".format(NEW_YEARS_EVE_TEXT, year)) 137 | new_holidays.update({datetime.date(year, 12, 24):CHRISTMAS_EVE_TEXT, datetime.date(year, 12, 31):NEW_YEARS_EVE_TEXT}) 138 | 139 | return new_holidays 140 | 141 | if __name__== "__main__": 142 | if len(sys.argv) == 2: 143 | # generate the plist 144 | gen_country_holidays(sys.argv[1]) 145 | else: 146 | print("Incorrect usage! Please supply a valid country code.") -------------------------------------------------------------------------------- /layout/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Sleeper (postinst): Killing mobiletimerd" 4 | killall -9 mobiletimerd 5 | exit 0 6 | -------------------------------------------------------------------------------- /layout/DEBIAN/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Sleeper (postrm): Killing mobiletimerd" 4 | killall -9 mobiletimerd 5 | exit 0 6 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Arabic (translation provided by MiRO92) 10 | "SNOOZE_TIME" = "وقت الغفوة"; 11 | "HOURS" = "ساعة"; 12 | "MINUTES" = "دقيقة"; 13 | "SECONDS" = "ثانية"; 14 | "RESET_DEFAULT" = "إعادة التعيين إلى الإفتراضي"; 15 | "DEFAULT_SNOOZE_TIME" = "وقت الغفوة الإفتراضي هو %@."; 16 | "SKIP" = "تخطي رنين المنبه"; 17 | "SKIP_TIME" = "اختر وقت لـ(تخطي رنين المنبه)"; 18 | "SKIP_ALARM" = "تخطي المنبه"; 19 | "SKIP_QUESTION" = "هل تريد تخطي \"%@\" المقرر له أن يرن في %@؟"; 20 | "SKIP_TIME_EXPLANATION" = "إختر المدة التي سيتم فيها إظهار تنبيه لـ(تخطي رنين المنبه) قبل وقت رنين المنبه."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/au_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2019-10-20T20:33:04Z 7 | holidays 8 | 9 | 10 | name 11 | New Year's Day 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-03 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-03 23 | 2034-01-02 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-03 29 | 2040-01-02 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-02 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Australia Day 44 | dates 45 | 46 | 2025-01-27 47 | 2026-01-26 48 | 2027-01-26 49 | 2028-01-26 50 | 2029-01-26 51 | 2030-01-28 52 | 2031-01-27 53 | 2032-01-26 54 | 2033-01-26 55 | 2034-01-26 56 | 2035-01-26 57 | 2036-01-28 58 | 2037-01-26 59 | 2038-01-26 60 | 2039-01-26 61 | 2040-01-26 62 | 2041-01-28 63 | 2042-01-27 64 | 2043-01-26 65 | 2044-01-26 66 | 2045-01-26 67 | 2046-01-26 68 | 2047-01-28 69 | 2048-01-27 70 | 2049-01-26 71 | 72 | 73 | 74 | name 75 | Good Friday 76 | dates 77 | 78 | 2024-03-29 79 | 2025-04-18 80 | 2026-04-03 81 | 2027-03-26 82 | 2028-04-14 83 | 2029-03-30 84 | 2030-04-19 85 | 2031-04-11 86 | 2032-03-26 87 | 2033-04-15 88 | 2034-04-07 89 | 2035-03-23 90 | 2036-04-11 91 | 2037-04-03 92 | 2038-04-23 93 | 2039-04-08 94 | 2040-03-30 95 | 2041-04-19 96 | 2042-04-04 97 | 2043-03-27 98 | 2044-04-15 99 | 2045-04-07 100 | 2046-03-23 101 | 2047-04-12 102 | 2048-04-03 103 | 2049-04-16 104 | 105 | 106 | 107 | name 108 | Easter Monday 109 | dates 110 | 111 | 2024-04-01 112 | 2025-04-21 113 | 2026-04-06 114 | 2027-03-29 115 | 2028-04-17 116 | 2029-04-02 117 | 2030-04-22 118 | 2031-04-14 119 | 2032-03-29 120 | 2033-04-18 121 | 2034-04-10 122 | 2035-03-26 123 | 2036-04-14 124 | 2037-04-06 125 | 2038-04-26 126 | 2039-04-11 127 | 2040-04-02 128 | 2041-04-22 129 | 2042-04-07 130 | 2043-03-30 131 | 2044-04-18 132 | 2045-04-10 133 | 2046-03-26 134 | 2047-04-15 135 | 2048-04-06 136 | 2049-04-19 137 | 138 | 139 | 140 | name 141 | Anzac Day 142 | dates 143 | 144 | 2024-04-25 145 | 2025-04-25 146 | 2026-04-25 147 | 2027-04-25 148 | 2028-04-25 149 | 2029-04-25 150 | 2030-04-25 151 | 2031-04-25 152 | 2032-04-25 153 | 2033-04-25 154 | 2034-04-25 155 | 2035-04-25 156 | 2036-04-25 157 | 2037-04-25 158 | 2038-04-25 159 | 2039-04-25 160 | 2040-04-25 161 | 2041-04-25 162 | 2042-04-25 163 | 2043-04-25 164 | 2044-04-25 165 | 2045-04-25 166 | 2046-04-25 167 | 2047-04-25 168 | 2048-04-25 169 | 2049-04-25 170 | 171 | 172 | 173 | name 174 | Christmas Day 175 | dates 176 | 177 | 2024-12-25 178 | 2025-12-25 179 | 2026-12-25 180 | 2027-12-27 181 | 2028-12-25 182 | 2029-12-25 183 | 2030-12-25 184 | 2031-12-25 185 | 2032-12-27 186 | 2033-12-27 187 | 2034-12-25 188 | 2035-12-25 189 | 2036-12-25 190 | 2037-12-25 191 | 2038-12-27 192 | 2039-12-27 193 | 2040-12-25 194 | 2041-12-25 195 | 2042-12-25 196 | 2043-12-25 197 | 2044-12-27 198 | 2045-12-25 199 | 2046-12-25 200 | 2047-12-25 201 | 2048-12-25 202 | 2049-12-27 203 | 204 | 205 | 206 | name 207 | Boxing Day 208 | dates 209 | 210 | 2024-12-26 211 | 2025-12-26 212 | 2026-12-28 213 | 2027-12-28 214 | 2028-12-26 215 | 2029-12-26 216 | 2030-12-26 217 | 2031-12-26 218 | 2032-12-28 219 | 2033-12-26 220 | 2034-12-26 221 | 2035-12-26 222 | 2036-12-26 223 | 2037-12-28 224 | 2038-12-28 225 | 2039-12-26 226 | 2040-12-26 227 | 2041-12-26 228 | 2042-12-26 229 | 2043-12-28 230 | 2044-12-26 231 | 2045-12-26 232 | 2046-12-26 233 | 2047-12-26 234 | 2048-12-28 235 | 2049-12-28 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ca.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Catalan (translation provided by q-quan) 10 | "SNOOZE_TIME" = "Temps d'Ajorn"; 11 | "HOURS" = "hores"; 12 | "MINUTES" = "minuts"; 13 | "SECONDS" = "segons"; 14 | "RESET_DEFAULT" = "Restaurar Predeterminat"; 15 | "DEFAULT_SNOOZE_TIME" = "El temps d'ajorn predeterminat és de %@."; 16 | "SKIP" = "Ometre"; 17 | "SKIP_TIME" = "Temps d’omissió"; 18 | "SKIP_ALARM" = "Alarma d’omissió"; 19 | "SKIP_QUESTION" = "T’agradaria saltar-te \"%@\", que està programat per les %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Tria a quant de temps se’t demanarà per ometre l’alarma abans de que soni."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ch_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2019-11-09T19:45:08Z 7 | holidays 8 | 9 | 10 | name 11 | Neujahrestag 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-01 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-01 23 | 2034-01-01 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-01 29 | 2040-01-01 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-01 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Karfreitag 44 | dates 45 | 46 | 2024-03-29 47 | 2025-04-18 48 | 2026-04-03 49 | 2027-03-26 50 | 2028-04-14 51 | 2029-03-30 52 | 2030-04-19 53 | 2031-04-11 54 | 2032-03-26 55 | 2033-04-15 56 | 2034-04-07 57 | 2035-03-23 58 | 2036-04-11 59 | 2037-04-03 60 | 2038-04-23 61 | 2039-04-08 62 | 2040-03-30 63 | 2041-04-19 64 | 2042-04-04 65 | 2043-03-27 66 | 2044-04-15 67 | 2045-04-07 68 | 2046-03-23 69 | 2047-04-12 70 | 2048-04-03 71 | 2049-04-16 72 | 73 | 74 | 75 | name 76 | Ostern 77 | dates 78 | 79 | 2024-03-31 80 | 2025-04-20 81 | 2026-04-05 82 | 2027-03-28 83 | 2028-04-16 84 | 2029-04-01 85 | 2030-04-21 86 | 2031-04-13 87 | 2032-03-28 88 | 2033-04-17 89 | 2034-04-09 90 | 2035-03-25 91 | 2036-04-13 92 | 2037-04-05 93 | 2038-04-25 94 | 2039-04-10 95 | 2040-04-01 96 | 2041-04-21 97 | 2042-04-06 98 | 2043-03-29 99 | 2044-04-17 100 | 2045-04-09 101 | 2046-03-25 102 | 2047-04-14 103 | 2048-04-05 104 | 2049-04-18 105 | 106 | 107 | 108 | name 109 | Ostermontag 110 | dates 111 | 112 | 2024-04-01 113 | 2025-04-21 114 | 2026-04-06 115 | 2027-03-29 116 | 2028-04-17 117 | 2029-04-02 118 | 2030-04-22 119 | 2031-04-14 120 | 2032-03-29 121 | 2033-04-18 122 | 2034-04-10 123 | 2035-03-26 124 | 2036-04-14 125 | 2037-04-06 126 | 2038-04-26 127 | 2039-04-11 128 | 2040-04-02 129 | 2041-04-22 130 | 2042-04-07 131 | 2043-03-30 132 | 2044-04-18 133 | 2045-04-10 134 | 2046-03-26 135 | 2047-04-15 136 | 2048-04-06 137 | 2049-04-19 138 | 139 | 140 | 141 | name 142 | Auffahrt 143 | dates 144 | 145 | 2024-05-09 146 | 2025-05-29 147 | 2026-05-14 148 | 2027-05-06 149 | 2028-05-25 150 | 2029-05-10 151 | 2030-05-30 152 | 2031-05-22 153 | 2032-05-06 154 | 2033-05-26 155 | 2034-05-18 156 | 2035-05-03 157 | 2036-05-22 158 | 2037-05-14 159 | 2038-06-03 160 | 2039-05-19 161 | 2040-05-10 162 | 2041-05-30 163 | 2042-05-15 164 | 2043-05-07 165 | 2044-05-26 166 | 2045-05-18 167 | 2046-05-03 168 | 2047-05-23 169 | 2048-05-14 170 | 2049-05-27 171 | 172 | 173 | 174 | name 175 | Pfingsten 176 | dates 177 | 178 | 2024-05-19 179 | 2025-06-08 180 | 2026-05-24 181 | 2027-05-16 182 | 2028-06-04 183 | 2029-05-20 184 | 2030-06-09 185 | 2031-06-01 186 | 2032-05-16 187 | 2033-06-05 188 | 2034-05-28 189 | 2035-05-13 190 | 2036-06-01 191 | 2037-05-24 192 | 2038-06-13 193 | 2039-05-29 194 | 2040-05-20 195 | 2041-06-09 196 | 2042-05-25 197 | 2043-05-17 198 | 2044-06-05 199 | 2045-05-28 200 | 2046-05-13 201 | 2047-06-02 202 | 2048-05-24 203 | 2049-06-06 204 | 205 | 206 | 207 | name 208 | Pfingstmontag 209 | dates 210 | 211 | 2024-05-20 212 | 2025-06-09 213 | 2026-05-25 214 | 2027-05-17 215 | 2028-06-05 216 | 2029-05-21 217 | 2030-06-10 218 | 2031-06-02 219 | 2032-05-17 220 | 2033-06-06 221 | 2034-05-29 222 | 2035-05-14 223 | 2036-06-02 224 | 2037-05-25 225 | 2038-06-14 226 | 2039-05-30 227 | 2040-05-21 228 | 2041-06-10 229 | 2042-05-26 230 | 2043-05-18 231 | 2044-06-06 232 | 2045-05-29 233 | 2046-05-14 234 | 2047-06-03 235 | 2048-05-25 236 | 2049-06-07 237 | 238 | 239 | 240 | name 241 | Nationalfeiertag 242 | dates 243 | 244 | 2024-08-01 245 | 2025-08-01 246 | 2026-08-01 247 | 2027-08-01 248 | 2028-08-01 249 | 2029-08-01 250 | 2030-08-01 251 | 2031-08-01 252 | 2032-08-01 253 | 2033-08-01 254 | 2034-08-01 255 | 2035-08-01 256 | 2036-08-01 257 | 2037-08-01 258 | 2038-08-01 259 | 2039-08-01 260 | 2040-08-01 261 | 2041-08-01 262 | 2042-08-01 263 | 2043-08-01 264 | 2044-08-01 265 | 2045-08-01 266 | 2046-08-01 267 | 2047-08-01 268 | 2048-08-01 269 | 2049-08-01 270 | 271 | 272 | 273 | name 274 | Weihnachten 275 | dates 276 | 277 | 2024-12-25 278 | 2025-12-25 279 | 2026-12-25 280 | 2027-12-25 281 | 2028-12-25 282 | 2029-12-25 283 | 2030-12-25 284 | 2031-12-25 285 | 2032-12-25 286 | 2033-12-25 287 | 2034-12-25 288 | 2035-12-25 289 | 2036-12-25 290 | 2037-12-25 291 | 2038-12-25 292 | 2039-12-25 293 | 2040-12-25 294 | 2041-12-25 295 | 2042-12-25 296 | 2043-12-25 297 | 2044-12-25 298 | 2045-12-25 299 | 2046-12-25 300 | 2047-12-25 301 | 2048-12-25 302 | 2049-12-25 303 | 304 | 305 | 306 | 307 | 308 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/checkmark.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/checkmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/checkmark@2x.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/checkmark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/checkmark@3x.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/cs.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Czech (translation provided by Sh4rPEYE) 10 | "SNOOZE_TIME" = "Délka odložení"; 11 | "HOURS" = "hod"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sek"; 14 | "RESET_DEFAULT" = "Obnovit na výchozí"; 15 | "DEFAULT_SNOOZE_TIME" = "Výchozí délka odložení je %@."; 16 | "SKIP" = "Přeskočit"; 17 | "SKIP_TIME" = "Čas přeskočení"; 18 | "SKIP_ALARM" = "Přeskočit budík"; 19 | "SKIP_QUESTION" = "Chcete přeskočit budík \"%@\", který má zazvonit v %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Vyberte si počet nabídek k přeskočení budíku před tím, než zazvoní."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/da.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Danish (translation provided by Rasmushp and qlimax5000) 10 | "SNOOZE_TIME" = "Snooze interval"; 11 | "HOURS" = "Timer"; 12 | "MINUTES" = "Min."; 13 | "SECONDS" = "Sek."; 14 | "RESET_DEFAULT" = "Gendan standardindstillinger"; 15 | "DEFAULT_SNOOZE_TIME" = "Standard snooze interval er %@."; 16 | "SKIP" = "Spring Over"; 17 | "SKIP_TIME" = "Spring Time Over"; 18 | "SKIP_ALARM" = "Spring Alarm Over"; 19 | "SKIP_QUESTION" = "Vil du springe \"%@\" over? Den er sat til kl. \"%@\""; 20 | "SKIP_TIME_EXPLANATION" = "Vælg hvor lang tid før en alarm ringer at du vil spørges om du vil springe den fra."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // German (translation provided by thapublicMAN) 10 | "SNOOZE_TIME" = "Schlummerzeit"; 11 | "HOURS" = "Std."; 12 | "MINUTES" = "Min."; 13 | "SECONDS" = "Sek."; 14 | "RESET_DEFAULT" = "Zurücksetzen"; 15 | "DEFAULT_SNOOZE_TIME" = "Die Standard-Schlummerzeit ist %@."; 16 | "SKIP" = "Überspringen"; 17 | "SKIP_TIME" = "Zeit-Überspringen"; 18 | "SKIP_ALARM" = "Wecker-Überspringen"; 19 | "SKIP_QUESTION" = "Möchtest du \"%@\" überspringen, der in %@ losgehen wird?"; 20 | "SKIP_TIME_EXPLANATION" = "Wähle eine Zeitspanne in der du abgefragt wirst den Wecker zu überspringen, bevor er ausgelöst wird."; 21 | 22 | // German (translation provided by 100k_Jahresgehalt) 23 | "SKIP_DATES" = "Ausgelassene Tage"; 24 | "SELECT_NEW_DATE" = "Wähle neues Datum"; 25 | "SELECT_START_DATE" = "Wähle das Startdatum"; 26 | "SELECT_END_DATE" = "Wähle das Enddatum"; 27 | "EDIT_EXISTING_DATE" = "Vorhandenes Datum bearbeiten"; 28 | "NUM_HOLIDAYS" = "%ld Feiertage"; 29 | "NUM_HOLIDAY" = "%ld Feiertag"; 30 | "NUM_DATES" = "%ld Tage"; 31 | "NUM_DATE" = "%ld Tag"; 32 | "DEFAULT_SKIP_DATES" = "Alle ausgelassene Tage für diesen Wecker entfernen."; 33 | "CONFIRM_DEFAULT_SKIP_DATES" = "Bist du sicher, dass du alle ausgelassene Tage für diesen Alarm entfernen möchtest?"; 34 | "DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Alle ausgelassenen Tage, einschließlich aller Feiertagsauswahlen, für diesen Wecker entfernen."; 35 | "CONFIRM_DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Bist du sicher, dass du alle ausgelassenen Tage und Feiertagsauswahlen für diesen Wecker entfernen möchtest?"; 36 | "SKIP_DATE_EXPLANATION" = "Dieser Wecker wird an den ausgewählten Tagen übersprungen."; 37 | "HOLIDAY_EXPLANATION" = "Wenn in diesem Land beobachtete Feiertage anerkannt werden und der Feiertag auf ein Wochenende fällt, wird das beobachtete Datum verwendet. Sobald ein Feiertag ausgewählt wurde, wird er auch weiterhin jedes Jahr übersprungen."; 38 | "ADD_NEW_DATE" = "Neues Datum hinzufügen..."; 39 | "NUMBER_SELECTED" = "%ld Ausgewählt"; 40 | "SKIP_REASON_POPUP" = "Du hast dich entschieden, diesen Wecker zu überspringen, wenn er das nächste Mal ausgelöst wird. Beim Speichern des Weckers wird diese Einstellung zurückgesetzt."; 41 | "SKIP_REASON_DATE" = "Das nächste Übersprungsdatum, das Sie für diesen Alarm ausgewählt haben, ist %@."; 42 | "SKIP_REASON_HOLIDAY" = "Der nächste Feiertag, den Sie für diesen Wecker ausgewählt haben, ist %@ (%@)."; 43 | "ALL_HOLIDAYS" = "Alle Feiertage"; 44 | "RECOMMENDED_HOLIDAYS_EXPLANATION" = "Diese Feiertage werden auf der Grundlage des aktuellen Standorts des Geräts empfohlen."; 45 | "SINGLE_DATE" = "Einzeldatum"; 46 | "DATE_RANGE" = "Datumsbereich"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/el.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Greek (translation provided by TeamArrow) 10 | "SNOOZE_TIME" = "Ώρα υπνάκου"; 11 | "HOURS" = "ώρες"; 12 | "MINUTES" = "λεπτά"; 13 | "SECONDS" = "δευτερόλεπτα"; 14 | "RESET_DEFAULT" = "Επαναφορά στο κανονικό."; 15 | "DEFAULT_SNOOZE_TIME" = "Η κανονική ώρα \"υπνάκου\" είναι: %@."; 16 | "SKIP" = "Παράλειψη"; 17 | "SKIP_TIME" = "Χρόνος παράλειψης"; 18 | "SKIP_ALARM" = "Παράλειψη ξυπνητηριού"; 19 | "SKIP_QUESTION" = "Θα θέλατε να παραλείψετε το οποίο είναι να χτυπήσει στις"; 20 | "SKIP_TIME_EXPLANATION" = "Διαλέξτε ένα συγκεκριμένο χρόνο που θέλετε να παραλείψετε το ξυπνητήρι πριν χτυπήσει."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // English 10 | "SNOOZE_TIME" = "Snooze Time"; 11 | "HOURS" = "hours"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sec"; 14 | "RESET_DEFAULT" = "Reset Default"; 15 | "DEFAULT_SNOOZE_TIME" = "The default snooze time is %@."; 16 | "SKIP" = "Skip"; 17 | "SKIP_TIME" = "Skip Time"; 18 | "SKIP_ALARM" = "Skip Alarm"; 19 | "SKIP_QUESTION" = "Would you like to skip \"%@\" which is scheduled to go off at %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Choose an amount of time that you will be prompted to skip the alarm before it fires."; 21 | "SKIP_DATES" = "Skip Dates"; 22 | "SELECT_NEW_DATE" = "Select New Date"; 23 | "SELECT_START_DATE" = "Select Start Date"; 24 | "SELECT_END_DATE" = "Select End Date"; 25 | "EDIT_EXISTING_DATE" = "Edit Existing Date"; 26 | "NUM_HOLIDAYS" = "%ld Holidays"; 27 | "NUM_HOLIDAY" = "%ld Holiday"; 28 | "NUM_DATES" = "%ld Dates"; 29 | "NUM_DATE" = "%ld Date"; 30 | "DEFAULT_SKIP_DATES" = "Remove all skip dates for this alarm."; 31 | "CONFIRM_DEFAULT_SKIP_DATES" = "Are you sure you want to remove all of the skip dates for this alarm?"; 32 | "DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Remove all skip dates, including any holiday selections, for this alarm."; 33 | "CONFIRM_DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Are you sure you want to remove all of the skip dates and holiday selections for this alarm?"; 34 | "SKIP_DATE_EXPLANATION" = "This alarm will be skipped on the dates selected."; 35 | "HOLIDAY_EXPLANATION" = "If this country recognizes observed holidays and the holiday falls on a weekend, the observed date is used. Once a holiday is selected, it will continue to be skipped every year. The next date that will be skipped is displayed underneath each holiday name."; 36 | "ADD_NEW_DATE" = "Add New Date..."; 37 | "NUMBER_SELECTED" = "%ld Selected"; 38 | "SKIP_REASON_POPUP" = "You have decided to skip this alarm the next time it is set to fire. This decision will be reset if you save the alarm."; 39 | "SKIP_REASON_DATE" = "The next skip date you've selected for this alarm is %@."; 40 | "SKIP_REASON_HOLIDAY" = "The next holiday you've selected for this alarm is %@ (%@)."; 41 | "ALL_HOLIDAYS" = "All Holidays"; 42 | "RECOMMENDED_HOLIDAYS_EXPLANATION" = "These are the recommended holidays based on your device's current locale."; 43 | "SINGLE_DATE" = "Single Date"; 44 | "DATE_RANGE" = "Date Range"; 45 | "SKIP_EXPLANATION" = "Use the skip feature to temporarily disable alarms based on selected away dates/holidays or by setting a time in which the system will prompt you upon unlocking the device to skip the alarm before it fires."; 46 | "NO_FUTURE_DATES" = "No Future Dates Available"; 47 | "AUTO_SET" = "Auto-Set"; 48 | "AUTO_SET_DISABLED_EXPLANATION" = "The auto-set feature cannot be enabled on this device because the Weather application is not installed. Please install and configure the Weather application from the App Store and try again."; 49 | "AUTO_SET_WEATHER_EXPLANATION" = "The auto-set times will be determined by the first location set in the Weather application.\n\nIf the first location is determined using your device's location, then the Weather app will need to be opened any time the device is rebooted or SpringBoard is restarted to refresh the first location.\n\nTo ensure the auto-set feature is always functioning properly, please also set a secondary location manually in the Weather application."; 50 | "AUTO_SET_OPEN_WEATHER_APP" = "Open Weather App"; 51 | "AUTO_SET_EXPLANATION" = "Choose an auto-set option to have this alarm automatically update its fire time."; 52 | "AUTO_SET_OFFSET_EXPLANATION" = "When enabled, the offset hours and minutes will be applied either before or after the selected auto-set time.\n\nFor example, if the sunrise auto-set option is selected with a 1-hour-before offset, the alarm will be set to fire 1 hour before the actual sunrise occurs."; 53 | "AUTO_SET_OFF_EXPLANATION" = "You can use the auto-set feature to have this alarm automatically set its time based on various parameters."; 54 | "AUTO_SET_ON_EXPLANATION" = "This alarm's fire time will automatically be set to %@."; 55 | "AUTO_SET_ON_WITH_OFFSET_EXPLANATION" = "This alarm's fire time will automatically be set to %@ %@ %@."; 56 | "BEFORE" = "Before"; 57 | "AFTER" = "After"; 58 | "OFFSET" = "Offset"; 59 | "OFFSET_TIME" = "Offset Time"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Spanish (translation provided by Retosteante) 10 | "SNOOZE_TIME" = "Posponer Tiempo"; 11 | "HOURS" = "horas"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "seg"; 14 | "RESET_DEFAULT" = "Valores Predeterminados"; 15 | "DEFAULT_SNOOZE_TIME" = "El tiempo predeterminado para posponer es %@."; 16 | "SKIP" = "Omitir"; 17 | "SKIP_TIME" = "Omitir tiempo"; 18 | "SKIP_ALARM" = "Omitir alarma"; 19 | "SKIP_QUESTION" = "¿Deseas omitir la alarma \"%@\" que está programada para que suene a las %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Define el tiempo en el que se te pedirá omitir la alarma antes de que salte."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/fi.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 11/3/15. 6 | 7 | */ 8 | 9 | // Finnish (translation provided by mikkoko) 10 | "SNOOZE_TIME" = "Torkkuaika"; 11 | "HOURS" = "tuntia"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sek"; 14 | "RESET_DEFAULT" = "Palauta oletukset"; 15 | "DEFAULT_SNOOZE_TIME" = "Oletus torkkuaika on %@."; 16 | "SKIP" = "Ohita"; 17 | "SKIP_TIME" = "Ohita aika"; 18 | "SKIP_ALARM" = "Ohita hälytys"; 19 | "SKIP_QUESTION" = "Haluatko ohittaa herätyksen \"%@\" jonka on tarkoitus käynnistyä %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Aseta aika milloin sinua muistutetaan ohittamaan herätys ennen kuin se alkaa."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // French (translation provided by Ziph0n & zazouboy) 10 | "SNOOZE_TIME" = "Temporisation"; 11 | "HOURS" = "heures"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sec"; 14 | "RESET_DEFAULT" = "Réinitialiser"; 15 | "DEFAULT_SNOOZE_TIME" = "La temporisation par défaut est %@."; 16 | "SKIP" = "Possibilité de l'ignorer"; 17 | "SKIP_TIME" = "Durée"; 18 | "SKIP_ALARM" = "Ignorer l'alarme"; 19 | "SKIP_QUESTION" = "Voulez-vous ignorer \"%@\" qui doit se déclencher à %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Choisissez la durée pendant laquelle il vous sera demandé si vous souhaitez ignorer l'alarme avant qu'elle ne se déclenche."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/he.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Hebrew (translation provided by Aransh) 10 | "SNOOZE_TIME" = "זמן תנומה"; 11 | "HOURS" = "שעות"; 12 | "MINUTES" = "דקות"; 13 | "SECONDS" = "שניות"; 14 | "RESET_DEFAULT" = "אתחל לברירת מחדל"; 15 | "DEFAULT_SNOOZE_TIME" = "זמן התנומה ברירת המחדל הוא %@."; 16 | "SKIP" = "דלג"; 17 | "SKIP_TIME" = "זמן דילוג"; 18 | "SKIP_ALARM" = "דלג/י על ההתראה"; 19 | "SKIP_QUESTION" = "האם תרצה/י לדלג על ההתראה \"%@\" שמתוזמנת לפעול ב%@?"; 20 | "SKIP_TIME_EXPLANATION" = "בחר כמות זמן שבו תישאל/י האם את/ה רוצה לדלג על ההתראה לפני שהיא מתחילה."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/hu.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 10/9/15. 6 | 7 | */ 8 | 9 | // Hungarian (translation provided by benciikee) 10 | "SNOOZE_TIME" = "Szundi idő"; 11 | "HOURS" = "Óra"; 12 | "MINUTES" = "Perc"; 13 | "SECONDS" = "Másodperc"; 14 | "RESET_DEFAULT" = "Eredeti Beállítások"; 15 | "DEFAULT_SNOOZE_TIME" = "Az alapértelmezett szundi idő %@"; 16 | "SKIP" = "Kihagyás"; 17 | "SKIP_TIME" = "Időpont kihagyása"; 18 | "SKIP_ALARM" = "Ébresztő kihagyása"; 19 | "SKIP_QUESTION" = "Biztosan ki szeretnéd hagyni a \"%@\" nevű ébresztőt ami %@ időben indul?"; 20 | "SKIP_TIME_EXPLANATION" = "Válassz egy időintervallumot amikor a program megkér, hogy átugord az ébresztőt mielőtt az indul"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/icon.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/id.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Indonesian (translation provided by flyinggreenfish) 10 | "SNOOZE_TIME" = "Waktu Tunda Alarm"; 11 | "HOURS" = "Jam"; 12 | "MINUTES" = "Menit"; 13 | "SECONDS" = "Detik"; 14 | "RESET_DEFAULT" = "Setelan Baku"; 15 | "DEFAULT_SNOOZE_TIME" = "Setelan awal waktu tunda alarm adalah %@."; 16 | "SKIP" = "Lewati"; 17 | "SKIP_TIME" = "Waktu yang dilewatkan"; 18 | "SKIP_ALARM" = "Alarm yang dilewatkan"; 19 | "SKIP_QUESTION" = "Apakah anda mau melewatkan \"%@\" yang dijadwalkan untuk %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Pilih waktu yang dibutuhkan untuk meminta anda melewatkan alarmnya sebelum alarmnya menyala."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ind_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2019-11-09T15:24:01Z 7 | holidays 8 | 9 | 10 | name 11 | New Year 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-01 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-01 23 | 2034-01-01 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-01 29 | 2040-01-01 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-01 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Makar Sankranti / Pongal 44 | dates 45 | 46 | 2025-01-14 47 | 2026-01-14 48 | 2027-01-14 49 | 2028-01-14 50 | 2029-01-14 51 | 2030-01-14 52 | 2031-01-14 53 | 2032-01-14 54 | 2033-01-14 55 | 2034-01-14 56 | 2035-01-14 57 | 2036-01-14 58 | 2037-01-14 59 | 2038-01-14 60 | 2039-01-14 61 | 2040-01-14 62 | 2041-01-14 63 | 2042-01-14 64 | 2043-01-14 65 | 2044-01-14 66 | 2045-01-14 67 | 2046-01-14 68 | 2047-01-14 69 | 2048-01-14 70 | 2049-01-14 71 | 72 | 73 | 74 | name 75 | Republic Day 76 | dates 77 | 78 | 2025-01-26 79 | 2026-01-26 80 | 2027-01-26 81 | 2028-01-26 82 | 2029-01-26 83 | 2030-01-26 84 | 2031-01-26 85 | 2032-01-26 86 | 2033-01-26 87 | 2034-01-26 88 | 2035-01-26 89 | 2036-01-26 90 | 2037-01-26 91 | 2038-01-26 92 | 2039-01-26 93 | 2040-01-26 94 | 2041-01-26 95 | 2042-01-26 96 | 2043-01-26 97 | 2044-01-26 98 | 2045-01-26 99 | 2046-01-26 100 | 2047-01-26 101 | 2048-01-26 102 | 2049-01-26 103 | 104 | 105 | 106 | name 107 | Labour Day 108 | dates 109 | 110 | 2024-05-01 111 | 2025-05-01 112 | 2026-05-01 113 | 2027-05-01 114 | 2028-05-01 115 | 2029-05-01 116 | 2030-05-01 117 | 2031-05-01 118 | 2032-05-01 119 | 2033-05-01 120 | 2034-05-01 121 | 2035-05-01 122 | 2036-05-01 123 | 2037-05-01 124 | 2038-05-01 125 | 2039-05-01 126 | 2040-05-01 127 | 2041-05-01 128 | 2042-05-01 129 | 2043-05-01 130 | 2044-05-01 131 | 2045-05-01 132 | 2046-05-01 133 | 2047-05-01 134 | 2048-05-01 135 | 2049-05-01 136 | 137 | 138 | 139 | name 140 | Independence Day 141 | dates 142 | 143 | 2024-08-15 144 | 2025-08-15 145 | 2026-08-15 146 | 2027-08-15 147 | 2028-08-15 148 | 2029-08-15 149 | 2030-08-15 150 | 2031-08-15 151 | 2032-08-15 152 | 2033-08-15 153 | 2034-08-15 154 | 2035-08-15 155 | 2036-08-15 156 | 2037-08-15 157 | 2038-08-15 158 | 2039-08-15 159 | 2040-08-15 160 | 2041-08-15 161 | 2042-08-15 162 | 2043-08-15 163 | 2044-08-15 164 | 2045-08-15 165 | 2046-08-15 166 | 2047-08-15 167 | 2048-08-15 168 | 2049-08-15 169 | 170 | 171 | 172 | name 173 | Gandhi Jayanti 174 | dates 175 | 176 | 2024-10-02 177 | 2025-10-02 178 | 2026-10-02 179 | 2027-10-02 180 | 2028-10-02 181 | 2029-10-02 182 | 2030-10-02 183 | 2031-10-02 184 | 2032-10-02 185 | 2033-10-02 186 | 2034-10-02 187 | 2035-10-02 188 | 2036-10-02 189 | 2037-10-02 190 | 2038-10-02 191 | 2039-10-02 192 | 2040-10-02 193 | 2041-10-02 194 | 2042-10-02 195 | 2043-10-02 196 | 2044-10-02 197 | 2045-10-02 198 | 2046-10-02 199 | 2047-10-02 200 | 2048-10-02 201 | 2049-10-02 202 | 203 | 204 | 205 | name 206 | Christmas 207 | dates 208 | 209 | 2024-12-25 210 | 2025-12-25 211 | 2026-12-25 212 | 2027-12-25 213 | 2028-12-25 214 | 2029-12-25 215 | 2030-12-25 216 | 2031-12-25 217 | 2032-12-25 218 | 2033-12-25 219 | 2034-12-25 220 | 2035-12-25 221 | 2036-12-25 222 | 2037-12-25 223 | 2038-12-25 224 | 2039-12-25 225 | 2040-12-25 226 | 2041-12-25 227 | 2042-12-25 228 | 2043-12-25 229 | 2044-12-25 230 | 2045-12-25 231 | 2046-12-25 232 | 2047-12-25 233 | 2048-12-25 234 | 2049-12-25 235 | 236 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/it.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Italian (translation provided by Agru007) 10 | "ADD_NEW_DATE" = "Aggiungi nuova data..."; 11 | "ALL_HOLIDAYS" = "Tutte le festività"; 12 | "CONFIRM_DEFAULT_SKIP_DATES" = "Sei sicuro di voler eliminare tutte le date in cui saltare questa sveglia?"; 13 | "CONFIRM_DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Sei sicuro di voler eliminare tutte le date e le festività in cui saltare questa sveglia?"; 14 | "DATE_RANGE" = "Intervallo di date"; 15 | "DEFAULT_SKIP_DATES" = "Elimina tutte le date in cui saltare questa sveglia."; 16 | "DEFAULT_SKIP_DATES_AND_HOLIDAYS" = "Elimina tutte le date, incluse le festività, in cui saltare questa sveglia."; 17 | "DEFAULT_SNOOZE_TIME" = "Il ritardo predefinito è %@."; 18 | "EDIT_EXISTING_DATE" = "Modifica data esistente"; 19 | "HOLIDAY_EXPLANATION" = "Se il paese scelto supporta il cambio di data per le festività che cadono nel weekend, Sleeper silenzierà la sveglia nel giorno feriale corrispondente. Quando viene scelta una festività, essa resta valida ogni anno."; 20 | "HOURS" = "ore"; 21 | "MINUTES" = "min"; 22 | "NUMBER_SELECTED" = "%ld selezionato"; 23 | "NUM_DATE" = "%ld data"; 24 | "NUM_DATES" = "%ld date"; 25 | "NUM_HOLIDAY" = "%ld festività"; 26 | "NUM_HOLIDAYS" = "%ld festività"; 27 | "RECOMMENDED_HOLIDAYS_EXPLANATION" = "Queste sono le festività raccomandate in base alla località geografica impostata sul tuo telefono."; 28 | "RESET_DEFAULT" = "Ripristina valori predefiniti"; 29 | "SECONDS" = "sec"; 30 | "SELECT_END_DATE" = "Seleziona data finale"; 31 | "SELECT_NEW_DATE" = "Seleziona nuova data"; 32 | "SELECT_START_DATE" = "Seleziona data iniziale"; 33 | "SINGLE_DATE" = "Singola data"; 34 | "SKIP" = "Proponi salto"; 35 | "SKIP_ALARM" = "Salta sveglia"; 36 | "SKIP_DATES" = "Salta in data:"; 37 | "SKIP_DATE_EXPLANATION" = "Questa sveglia verrà saltata nelle date selezionate"; 38 | "SKIP_QUESTION" = "Vuoi saltare la sveglia \"%@\", programmata per le ore %@?"; 39 | "SKIP_REASON_DATE" = "La prossima data in cui saltare questa sveglia è %@."; 40 | "SKIP_REASON_HOLIDAY" = "La prossima festività in cui saltare questa sveglia è %@ (%@)."; 41 | "SKIP_REASON_POPUP" = "Hai scelto di saltare questa sveglia la prossima volta che scatterà. Questa scelta verrà dimenticata se salvi la sveglia."; 42 | "SKIP_TIME" = "Chiedi quando manca:"; 43 | "SKIP_TIME_EXPLANATION" = "Scegli il lasso di tempo prima della sveglia in cui ti verrà proposto se saltarla."; 44 | "SNOOZE_TIME" = "Ritarda di:"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Japanese (translation provided by koh_kun) 10 | "SNOOZE_TIME" = "スヌーズ間隔"; 11 | "HOURS" = "時間"; 12 | "MINUTES" = "分"; 13 | "SECONDS" = "秒"; 14 | "RESET_DEFAULT" = "初期設定に戻す"; 15 | "DEFAULT_SNOOZE_TIME" = "スヌーズ間隔の初期設定は%@です。"; 16 | "SKIP" = "スキップ"; 17 | "SKIP_TIME" = "スキップ間隔"; 18 | "SKIP_ALARM" = "アラームをスキップ"; 19 | "SKIP_QUESTION" = "%@に設定されているアラーム「\"%@\"」をスキップしますか?"; 20 | "SKIP_TIME_EXPLANATION" = "何度スキップされればアラームが発射される回数を決めてください。"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ke_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2019-11-09T15:58:27Z 7 | holidays 8 | 9 | 10 | name 11 | New Year's Day 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-01 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-01 23 | 2034-01-02 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-01 29 | 2040-01-02 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-02 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Good Friday 44 | dates 45 | 46 | 2024-03-29 47 | 2025-04-18 48 | 2026-04-03 49 | 2027-03-26 50 | 2028-04-14 51 | 2029-03-30 52 | 2030-04-19 53 | 2031-04-11 54 | 2032-03-26 55 | 2033-04-15 56 | 2034-04-07 57 | 2035-03-23 58 | 2036-04-11 59 | 2037-04-03 60 | 2038-04-23 61 | 2039-04-08 62 | 2040-03-30 63 | 2041-04-19 64 | 2042-04-04 65 | 2043-03-27 66 | 2044-04-15 67 | 2045-04-07 68 | 2046-03-23 69 | 2047-04-12 70 | 2048-04-03 71 | 2049-04-16 72 | 73 | 74 | 75 | name 76 | Easter Monday 77 | dates 78 | 79 | 2024-04-01 80 | 2025-04-21 81 | 2026-04-06 82 | 2027-03-29 83 | 2028-04-17 84 | 2029-04-02 85 | 2030-04-22 86 | 2031-04-14 87 | 2032-03-29 88 | 2033-04-18 89 | 2034-04-10 90 | 2035-03-26 91 | 2036-04-14 92 | 2037-04-06 93 | 2038-04-26 94 | 2039-04-11 95 | 2040-04-02 96 | 2041-04-22 97 | 2042-04-07 98 | 2043-03-30 99 | 2044-04-18 100 | 2045-04-10 101 | 2046-03-26 102 | 2047-04-15 103 | 2048-04-06 104 | 2049-04-19 105 | 106 | 107 | 108 | name 109 | Labour Day 110 | dates 111 | 112 | 2024-05-01 113 | 2025-05-01 114 | 2026-05-01 115 | 2027-05-01 116 | 2028-05-01 117 | 2029-05-01 118 | 2030-05-01 119 | 2031-05-01 120 | 2032-05-01 121 | 2033-05-02 122 | 2034-05-01 123 | 2035-05-01 124 | 2036-05-01 125 | 2037-05-01 126 | 2038-05-01 127 | 2039-05-02 128 | 2040-05-01 129 | 2041-05-01 130 | 2042-05-01 131 | 2043-05-01 132 | 2044-05-02 133 | 2045-05-01 134 | 2046-05-01 135 | 2047-05-01 136 | 2048-05-01 137 | 2049-05-01 138 | 139 | 140 | 141 | name 142 | Madaraka Day 143 | dates 144 | 145 | 2024-06-01 146 | 2025-06-02 147 | 2026-06-01 148 | 2027-06-01 149 | 2028-06-01 150 | 2029-06-01 151 | 2030-06-01 152 | 2031-06-02 153 | 2032-06-01 154 | 2033-06-01 155 | 2034-06-01 156 | 2035-06-01 157 | 2036-06-02 158 | 2037-06-01 159 | 2038-06-01 160 | 2039-06-01 161 | 2040-06-01 162 | 2041-06-01 163 | 2042-06-02 164 | 2043-06-01 165 | 2044-06-01 166 | 2045-06-01 167 | 2046-06-01 168 | 2047-06-01 169 | 2048-06-01 170 | 2049-06-01 171 | 172 | 173 | 174 | name 175 | Mashujaa Day 176 | dates 177 | 178 | 2024-10-21 179 | 2025-10-20 180 | 2026-10-20 181 | 2027-10-20 182 | 2028-10-20 183 | 2029-10-20 184 | 2030-10-21 185 | 2031-10-20 186 | 2032-10-20 187 | 2033-10-20 188 | 2034-10-20 189 | 2035-10-20 190 | 2036-10-20 191 | 2037-10-20 192 | 2038-10-20 193 | 2039-10-20 194 | 2040-10-20 195 | 2041-10-21 196 | 2042-10-20 197 | 2043-10-20 198 | 2044-10-20 199 | 2045-10-20 200 | 2046-10-20 201 | 2047-10-21 202 | 2048-10-20 203 | 2049-10-20 204 | 205 | 206 | 207 | name 208 | Jamhuri (Independence) Day 209 | dates 210 | 211 | 2024-12-12 212 | 2025-12-12 213 | 2026-12-12 214 | 2027-12-13 215 | 2028-12-12 216 | 2029-12-12 217 | 2030-12-12 218 | 2031-12-12 219 | 2032-12-13 220 | 2033-12-12 221 | 2034-12-12 222 | 2035-12-12 223 | 2036-12-12 224 | 2037-12-12 225 | 2038-12-13 226 | 2039-12-12 227 | 2040-12-12 228 | 2041-12-12 229 | 2042-12-12 230 | 2043-12-12 231 | 2044-12-12 232 | 2045-12-12 233 | 2046-12-12 234 | 2047-12-12 235 | 2048-12-12 236 | 2049-12-13 237 | 238 | 239 | 240 | name 241 | Christmas Day 242 | dates 243 | 244 | 2024-12-25 245 | 2025-12-25 246 | 2026-12-25 247 | 2027-12-25 248 | 2028-12-25 249 | 2029-12-25 250 | 2030-12-25 251 | 2031-12-25 252 | 2032-12-25 253 | 2033-12-26 254 | 2034-12-25 255 | 2035-12-25 256 | 2036-12-25 257 | 2037-12-25 258 | 2038-12-25 259 | 2039-12-26 260 | 2040-12-25 261 | 2041-12-25 262 | 2042-12-25 263 | 2043-12-25 264 | 2044-12-26 265 | 2045-12-25 266 | 2046-12-25 267 | 2047-12-25 268 | 2048-12-25 269 | 2049-12-25 270 | 271 | 272 | 273 | name 274 | Boxing Day 275 | dates 276 | 277 | 2024-12-26 278 | 2025-12-26 279 | 2026-12-26 280 | 2027-12-27 281 | 2028-12-26 282 | 2029-12-26 283 | 2030-12-26 284 | 2031-12-26 285 | 2032-12-27 286 | 2033-12-26 287 | 2034-12-26 288 | 2035-12-26 289 | 2036-12-26 290 | 2037-12-26 291 | 2038-12-27 292 | 2039-12-26 293 | 2040-12-26 294 | 2041-12-26 295 | 2042-12-26 296 | 2043-12-26 297 | 2044-12-26 298 | 2045-12-26 299 | 2046-12-26 300 | 2047-12-26 301 | 2048-12-26 302 | 2049-12-27 303 | 304 | 305 | 306 | 307 | 308 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ko.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Korean (translation provided by mujjingun) 10 | "SNOOZE_TIME" = "스누즈 시간"; 11 | "HOURS" = "시간"; 12 | "MINUTES" = "분"; 13 | "SECONDS" = "초"; 14 | "RESET_DEFAULT" = "초기화"; 15 | "DEFAULT_SNOOZE_TIME" = "기본 스누즈 시간은 %@ 입니다."; 16 | "SKIP" = "건너뛰기"; 17 | "SKIP_TIME" = "건너뛸 시간"; 18 | "SKIP_ALARM" = "알람 건너뛰기"; 19 | "SKIP_QUESTION" = "%2$@에 울릴 알람 \"%1$@\"를 건너뛰시겠습니까?"; 20 | "SKIP_TIME_EXPLANATION" = "알람이 울리기 직전에 나오는 알람 건너뛰기 옵션을 얼마동안 표시하시겠습니까?"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/la.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Latin (translation provided by swaggity_swiggity) 10 | "SNOOZE_TIME" = "quam diu expectare"; 11 | "HOURS" = "horis"; 12 | "MINUTES" = "minutus"; 13 | "SECONDS" = "secundus"; 14 | "RESET_DEFAULT" = "mutare ad regularem"; 15 | "DEFAULT_SNOOZE_TIME" = "in defectu est, snooze tempus %@."; 16 | "SKIP" = "Autem"; 17 | "SKIP_TIME" = "Degero"; 18 | "SKIP_ALARM" = "Autem Clangor"; 19 | "SKIP_QUESTION" = "Vis omit \"%@\" in qua venturus est %@ abire?"; 20 | "SKIP_TIME_EXPLANATION" = "Elige quam promptus spatium antequam trepidatione ignes omit."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ms.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Malay (translation provided by redzrex) 10 | "SNOOZE_TIME" = "Tunda Masa"; 11 | "HOURS" = "jam"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "saat"; 14 | "RESET_DEFAULT" = "Pulih Asal"; 15 | "DEFAULT_SNOOZE_TIME" = "Masa tunda yang asal ialah %@."; 16 | "SKIP" = "Langkau"; 17 | "SKIP_TIME" = "Langkau Masa"; 18 | "SKIP_ALARM" = "Langkau Penggera"; 19 | "SKIP_QUESTION" = "Adakah kamu ingin melangkau \"%@\" dimana ia telah dijadualkan untuk bunyi pada %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Pilih berapa kali kamu ingin didorong untuk melangkau penggera sebelum ia berbunyi."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/mx_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2019-11-09T18:57:00Z 7 | holidays 8 | 9 | 10 | name 11 | Año Nuevo 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2027-12-31 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2032-12-31 23 | 2034-01-02 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2038-12-31 29 | 2040-01-02 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-02 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Día de la Constitución 44 | dates 45 | 46 | 2025-02-03 47 | 2026-02-02 48 | 2027-02-01 49 | 2028-02-07 50 | 2029-02-05 51 | 2030-02-04 52 | 2031-02-03 53 | 2032-02-02 54 | 2033-02-07 55 | 2034-02-06 56 | 2035-02-05 57 | 2036-02-04 58 | 2037-02-02 59 | 2038-02-01 60 | 2039-02-07 61 | 2040-02-06 62 | 2041-02-04 63 | 2042-02-03 64 | 2043-02-02 65 | 2044-02-01 66 | 2045-02-06 67 | 2046-02-05 68 | 2047-02-04 69 | 2048-02-03 70 | 2049-02-01 71 | 72 | 73 | 74 | name 75 | Natalicio de Benito Juárez 76 | dates 77 | 78 | 2024-03-18 79 | 2025-03-17 80 | 2026-03-16 81 | 2027-03-15 82 | 2028-03-20 83 | 2029-03-19 84 | 2030-03-18 85 | 2031-03-17 86 | 2032-03-15 87 | 2033-03-21 88 | 2034-03-20 89 | 2035-03-19 90 | 2036-03-17 91 | 2037-03-16 92 | 2038-03-15 93 | 2039-03-21 94 | 2040-03-19 95 | 2041-03-18 96 | 2042-03-17 97 | 2043-03-16 98 | 2044-03-21 99 | 2045-03-20 100 | 2046-03-19 101 | 2047-03-18 102 | 2048-03-16 103 | 2049-03-15 104 | 105 | 106 | 107 | name 108 | Día del Trabajo 109 | dates 110 | 111 | 2024-05-01 112 | 2025-05-01 113 | 2026-05-01 114 | 2027-05-01 115 | 2028-05-01 116 | 2029-05-01 117 | 2030-05-01 118 | 2031-05-01 119 | 2032-05-01 120 | 2033-05-01 121 | 2034-05-01 122 | 2035-05-01 123 | 2036-05-01 124 | 2037-05-01 125 | 2038-05-01 126 | 2039-05-01 127 | 2040-05-01 128 | 2041-05-01 129 | 2042-05-01 130 | 2043-05-01 131 | 2044-05-01 132 | 2045-05-01 133 | 2046-05-01 134 | 2047-05-01 135 | 2048-05-01 136 | 2049-05-01 137 | 138 | 139 | 140 | name 141 | Día de la Independencia 142 | dates 143 | 144 | 2024-09-16 145 | 2025-09-16 146 | 2026-09-16 147 | 2027-09-16 148 | 2028-09-15 149 | 2029-09-17 150 | 2030-09-16 151 | 2031-09-16 152 | 2032-09-16 153 | 2033-09-16 154 | 2034-09-15 155 | 2035-09-17 156 | 2036-09-16 157 | 2037-09-16 158 | 2038-09-16 159 | 2039-09-16 160 | 2040-09-17 161 | 2041-09-16 162 | 2042-09-16 163 | 2043-09-16 164 | 2044-09-16 165 | 2045-09-15 166 | 2046-09-17 167 | 2047-09-16 168 | 2048-09-16 169 | 2049-09-16 170 | 171 | 172 | 173 | name 174 | Día de la Revolución 175 | dates 176 | 177 | 2024-11-18 178 | 2025-11-17 179 | 2026-11-16 180 | 2027-11-15 181 | 2028-11-20 182 | 2029-11-19 183 | 2030-11-18 184 | 2031-11-17 185 | 2032-11-15 186 | 2033-11-21 187 | 2034-11-20 188 | 2035-11-19 189 | 2036-11-17 190 | 2037-11-16 191 | 2038-11-15 192 | 2039-11-21 193 | 2040-11-19 194 | 2041-11-18 195 | 2042-11-17 196 | 2043-11-16 197 | 2044-11-21 198 | 2045-11-20 199 | 2046-11-19 200 | 2047-11-18 201 | 2048-11-16 202 | 2049-11-15 203 | 204 | 205 | 206 | name 207 | Navidad 208 | dates 209 | 210 | 2024-12-25 211 | 2025-12-25 212 | 2026-12-25 213 | 2027-12-25 214 | 2028-12-25 215 | 2029-12-25 216 | 2030-12-25 217 | 2031-12-25 218 | 2032-12-25 219 | 2033-12-25 220 | 2034-12-25 221 | 2035-12-25 222 | 2036-12-25 223 | 2037-12-25 224 | 2038-12-25 225 | 2039-12-25 226 | 2040-12-25 227 | 2041-12-25 228 | 2042-12-25 229 | 2043-12-25 230 | 2044-12-25 231 | 2045-12-25 232 | 2046-12-25 233 | 2047-12-25 234 | 2048-12-25 235 | 2049-12-25 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/nb.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Norwegian (translation provided by BaTmAn9785 and switchpwn) 10 | "SNOOZE_TIME" = "Slumretid"; 11 | "HOURS" = "timer"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sek"; 14 | "RESET_DEFAULT" = "Nullstill til standard"; 15 | "DEFAULT_SNOOZE_TIME" = "Standard slumretid er %@."; 16 | "SKIP" = "Hopp over"; 17 | "SKIP_TIME" = "Hopp over tid"; 18 | "SKIP_ALARM" = "Hopp over alarm"; 19 | "SKIP_QUESTION" = "Vil du hoppe over spørsmålet \"%@\" som er planlagt til å kjøre %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Velg tid som du vil bli spørt om å hoppe over før den kjører."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ng_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2020-06-19T14:53:28Z 7 | holidays 8 | 9 | 10 | name 11 | New Year's Day 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-01 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-01 23 | 2034-01-01 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-01 29 | 2040-01-01 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-01 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Worker's Day 44 | dates 45 | 46 | 2024-05-01 47 | 2025-05-01 48 | 2026-05-01 49 | 2027-05-01 50 | 2028-05-01 51 | 2029-05-01 52 | 2030-05-01 53 | 2031-05-01 54 | 2032-05-01 55 | 2033-05-01 56 | 2034-05-01 57 | 2035-05-01 58 | 2036-05-01 59 | 2037-05-01 60 | 2038-05-01 61 | 2039-05-01 62 | 2040-05-01 63 | 2041-05-01 64 | 2042-05-01 65 | 2043-05-01 66 | 2044-05-01 67 | 2045-05-01 68 | 2046-05-01 69 | 2047-05-01 70 | 2048-05-01 71 | 2049-05-01 72 | 73 | 74 | 75 | name 76 | Children's Day 77 | dates 78 | 79 | 2024-05-27 80 | 2025-05-27 81 | 2026-05-27 82 | 2027-05-27 83 | 2028-05-27 84 | 2029-05-27 85 | 2030-05-27 86 | 2031-05-27 87 | 2032-05-27 88 | 2033-05-27 89 | 2034-05-27 90 | 2035-05-27 91 | 2036-05-27 92 | 2037-05-27 93 | 2038-05-27 94 | 2039-05-27 95 | 2040-05-27 96 | 2041-05-27 97 | 2042-05-27 98 | 2043-05-27 99 | 2044-05-27 100 | 2045-05-27 101 | 2046-05-27 102 | 2047-05-27 103 | 2048-05-27 104 | 2049-05-27 105 | 106 | 107 | 108 | name 109 | Democracy Day 110 | dates 111 | 112 | 2024-06-12 113 | 2025-06-12 114 | 2026-06-12 115 | 2027-06-12 116 | 2028-06-12 117 | 2029-06-12 118 | 2030-06-12 119 | 2031-06-12 120 | 2032-06-12 121 | 2033-06-12 122 | 2034-06-12 123 | 2035-06-12 124 | 2036-06-12 125 | 2037-06-12 126 | 2038-06-12 127 | 2039-06-12 128 | 2040-06-12 129 | 2041-06-12 130 | 2042-06-12 131 | 2043-06-12 132 | 2044-06-12 133 | 2045-06-12 134 | 2046-06-12 135 | 2047-06-12 136 | 2048-06-12 137 | 2049-06-12 138 | 139 | 140 | 141 | name 142 | Independence Day 143 | dates 144 | 145 | 2024-10-01 146 | 2025-10-01 147 | 2026-10-01 148 | 2027-10-01 149 | 2028-10-01 150 | 2029-10-01 151 | 2030-10-01 152 | 2031-10-01 153 | 2032-10-01 154 | 2033-10-01 155 | 2034-10-01 156 | 2035-10-01 157 | 2036-10-01 158 | 2037-10-01 159 | 2038-10-01 160 | 2039-10-01 161 | 2040-10-01 162 | 2041-10-01 163 | 2042-10-01 164 | 2043-10-01 165 | 2044-10-01 166 | 2045-10-01 167 | 2046-10-01 168 | 2047-10-01 169 | 2048-10-01 170 | 2049-10-01 171 | 172 | 173 | 174 | name 175 | Christmas Day 176 | dates 177 | 178 | 2024-12-25 179 | 2025-12-25 180 | 2026-12-25 181 | 2027-12-25 182 | 2028-12-25 183 | 2029-12-25 184 | 2030-12-25 185 | 2031-12-25 186 | 2032-12-25 187 | 2033-12-25 188 | 2034-12-25 189 | 2035-12-25 190 | 2036-12-25 191 | 2037-12-25 192 | 2038-12-25 193 | 2039-12-25 194 | 2040-12-25 195 | 2041-12-25 196 | 2042-12-25 197 | 2043-12-25 198 | 2044-12-25 199 | 2045-12-25 200 | 2046-12-25 201 | 2047-12-25 202 | 2048-12-25 203 | 2049-12-25 204 | 205 | 206 | 207 | name 208 | Boxing Day 209 | dates 210 | 211 | 2024-12-26 212 | 2025-12-26 213 | 2026-12-26 214 | 2027-12-26 215 | 2028-12-26 216 | 2029-12-26 217 | 2030-12-26 218 | 2031-12-26 219 | 2032-12-26 220 | 2033-12-26 221 | 2034-12-26 222 | 2035-12-26 223 | 2036-12-26 224 | 2037-12-26 225 | 2038-12-26 226 | 2039-12-26 227 | 2040-12-26 228 | 2041-12-26 229 | 2042-12-26 230 | 2043-12-26 231 | 2044-12-26 232 | 2045-12-26 233 | 2046-12-26 234 | 2047-12-26 235 | 2048-12-26 236 | 2049-12-26 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/nl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Dutch (translation provided by benjaminisdenaam) 10 | "SNOOZE_TIME" = "Snoozetijd"; 11 | "HOURS" = "uren"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sec"; 14 | "RESET_DEFAULT" = "Herstel Standaardwaarden"; 15 | "DEFAULT_SNOOZE_TIME" = "De standaard ingestelde snoozetijd is %@."; 16 | "SKIP" = "Overslaan"; 17 | "SKIP_TIME" = "Tijd Overslaan"; 18 | "SKIP_ALARM" = "Wekker Overslaan"; 19 | "SKIP_QUESTION" = "Zou u graag \"%@\" overslaan, welke staat gepland om af te gaan binnen %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Hoeveel tijd voordat het alarm afgaat wilt u gevraagd worden om het alarm over te slaan?"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/open_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/open_in.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/open_in@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/open_in@2x.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/open_in@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshuaseltzer/Sleeper/ee3bc5ff3c4ccf524594bff25d8f8019c903c289/layout/Library/Application Support/Sleeper.bundle/open_in@3x.png -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/pl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Polish (translation provided by aaken) 10 | "SNOOZE_TIME" = "Czas drzemki"; 11 | "HOURS" = "godz."; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sek."; 14 | "RESET_DEFAULT" = "Przywróć ustawienia domyślne"; 15 | "DEFAULT_SNOOZE_TIME" = "Standardowy czas drzemki to %@."; 16 | "SKIP" = "Pomiń"; 17 | "SKIP_TIME" = "Czas pominięcia"; 18 | "SKIP_ALARM" = "Pomiń alarm"; 19 | "SKIP_QUESTION" = "Czy chciałbyś pominąć alarm \"%@\" który jest zaplanowany na %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Wybierz, po jakim czasie chcesz być zapytany o możliwość pominięcia alarmu, zanim zabrzmi."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/pt.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Portuguese (Brazil) (translation provided by mtlyoshi9) 10 | "SNOOZE_TIME" = "Tempo de soneca"; 11 | "HOURS" = "horas"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "seg"; 14 | "RESET_DEFAULT" = "Voltar ao padrão"; 15 | "DEFAULT_SNOOZE_TIME" = "O tempo padrão de soneca é %@."; 16 | "SKIP" = "Pular"; 17 | "SKIP_TIME" = "Tempo de adiamento"; 18 | "SKIP_ALARM" = "Pular alarme"; 19 | "SKIP_QUESTION" = "Você gostaria de pular \"%@\" que esta marcado para disparar as %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Escolhe um um período de tempo que você pode esperar antes que o alarme dispara."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/pt_PT.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Portuguese (Portugal) (translation provided by Ru1Sous4) 10 | "SNOOZE_TIME" = "Tempo de Snooze"; 11 | "HOURS" = "horas"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "seg"; 14 | "RESET_DEFAULT" = "Restaurar Valor Padrão"; 15 | "DEFAULT_SNOOZE_TIME" = "O tempo padrão de snooze é %@."; 16 | "SKIP" = "Ignorar"; 17 | "SKIP_TIME" = "Tempo para Ignorar"; 18 | "SKIP_ALARM" = "Ignorar Alarme"; 19 | "SKIP_QUESTION" = "Gostaria de ignorar o alarme \"%@\" que está marcado para as %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Escolha o período de tempo para poder ignorar o alarme antes de o mesmo tocar."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ro.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Romanian (translation provided by blackdeath19) 10 | "SNOOZE_TIME" = "Timpul pentru ațipit"; 11 | "HOURS" = "ore"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "seg"; 14 | "RESET_DEFAULT" = "Resetează valorile implicite"; 15 | "DEFAULT_SNOOZE_TIME" = "Timpul implicit pentru ațipit este %@."; 16 | "SKIP" = "Sari peste"; 17 | "SKIP_TIME" = "Sari peste Timp"; 18 | "SKIP_ALARM" = "Sari peste Alarmă"; 19 | "SKIP_QUESTION" = "Ai vrea să sari peste \"%@\" care este programată să fie declanșată la %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Alege cu cât timp înainte să sune alarma dorești să fi anunțat pentru a sări peste ea."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/ru.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Russian (translation provided by aeternii & b3l1nsky) 10 | "SNOOZE_TIME" = "Период отложения"; 11 | "HOURS" = "ч"; 12 | "MINUTES" = "мин"; 13 | "SECONDS" = "сек"; 14 | "RESET_DEFAULT" = "Сброс настроек"; 15 | "DEFAULT_SNOOZE_TIME" = "Стандартный период отложения – %@."; 16 | "SKIP" = "Отменяемый будильник"; 17 | "SKIP_TIME" = "За сколько можно отменить"; 18 | "SKIP_ALARM" = "Отменить будильник"; 19 | "SKIP_QUESTION" = "Вы хотели бы отменить будильник \"%@\", который прозвенит в %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Выберите за сколько времени вам будет предложено отменить будильник, прежде чем он сработает"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/sg_holidays.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | dateCreated 6 | 2020-06-20T16:57:49Z 7 | holidays 8 | 9 | 10 | name 11 | New Year's Day 12 | dates 13 | 14 | 2025-01-01 15 | 2026-01-01 16 | 2027-01-01 17 | 2028-01-01 18 | 2029-01-01 19 | 2030-01-01 20 | 2031-01-01 21 | 2032-01-01 22 | 2033-01-01 23 | 2034-01-01 24 | 2035-01-01 25 | 2036-01-01 26 | 2037-01-01 27 | 2038-01-01 28 | 2039-01-01 29 | 2040-01-01 30 | 2041-01-01 31 | 2042-01-01 32 | 2043-01-01 33 | 2044-01-01 34 | 2045-01-01 35 | 2046-01-01 36 | 2047-01-01 37 | 2048-01-01 38 | 2049-01-01 39 | 40 | 41 | 42 | name 43 | Chinese New Year 44 | dates 45 | 46 | 2025-01-29 47 | 2025-01-30 48 | 2026-02-17 49 | 2026-02-18 50 | 2027-02-06 51 | 2027-02-07 52 | 2028-01-26 53 | 2028-01-27 54 | 2029-02-13 55 | 2029-02-14 56 | 2030-02-03 57 | 2030-02-04 58 | 2031-01-23 59 | 2031-01-24 60 | 2032-02-11 61 | 2032-02-12 62 | 2033-01-31 63 | 2033-02-01 64 | 2034-02-19 65 | 2034-02-20 66 | 2035-02-08 67 | 2035-02-09 68 | 2036-01-28 69 | 2036-01-29 70 | 2037-02-15 71 | 2037-02-16 72 | 2038-02-04 73 | 2038-02-05 74 | 2039-01-24 75 | 2039-01-25 76 | 2040-02-12 77 | 2040-02-13 78 | 2041-02-01 79 | 2041-02-02 80 | 2042-01-22 81 | 2042-01-23 82 | 2043-02-10 83 | 2043-02-11 84 | 2044-01-30 85 | 2044-01-31 86 | 2045-02-17 87 | 2045-02-18 88 | 2046-02-06 89 | 2046-02-07 90 | 2047-01-26 91 | 2047-01-27 92 | 2048-02-14 93 | 2048-02-15 94 | 2049-02-02 95 | 2049-02-03 96 | 97 | 98 | 99 | name 100 | Good Friday 101 | dates 102 | 103 | 2024-03-29 104 | 2025-04-18 105 | 2026-04-03 106 | 2027-03-26 107 | 2028-04-14 108 | 2029-03-30 109 | 2030-04-19 110 | 2031-04-11 111 | 2032-03-26 112 | 2033-04-15 113 | 2034-04-07 114 | 2035-03-23 115 | 2036-04-11 116 | 2037-04-03 117 | 2038-04-23 118 | 2039-04-08 119 | 2040-03-30 120 | 2041-04-19 121 | 2042-04-04 122 | 2043-03-27 123 | 2044-04-15 124 | 2045-04-07 125 | 2046-03-23 126 | 2047-04-12 127 | 2048-04-03 128 | 2049-04-16 129 | 130 | 131 | 132 | name 133 | Labour Day 134 | dates 135 | 136 | 2024-05-01 137 | 2025-05-01 138 | 2026-05-01 139 | 2027-05-01 140 | 2028-05-01 141 | 2029-05-01 142 | 2030-05-01 143 | 2031-05-01 144 | 2032-05-01 145 | 2033-05-01 146 | 2034-05-01 147 | 2035-05-01 148 | 2036-05-01 149 | 2037-05-01 150 | 2038-05-01 151 | 2039-05-01 152 | 2040-05-01 153 | 2041-05-01 154 | 2042-05-01 155 | 2043-05-01 156 | 2044-05-01 157 | 2045-05-01 158 | 2046-05-01 159 | 2047-05-01 160 | 2048-05-01 161 | 2049-05-01 162 | 163 | 164 | 165 | name 166 | National Day 167 | dates 168 | 169 | 2024-08-09 170 | 2025-08-09 171 | 2026-08-09 172 | 2027-08-09 173 | 2028-08-09 174 | 2029-08-09 175 | 2030-08-09 176 | 2031-08-09 177 | 2032-08-09 178 | 2033-08-09 179 | 2034-08-09 180 | 2035-08-09 181 | 2036-08-09 182 | 2037-08-09 183 | 2038-08-09 184 | 2039-08-09 185 | 2040-08-09 186 | 2041-08-09 187 | 2042-08-09 188 | 2043-08-09 189 | 2044-08-09 190 | 2045-08-09 191 | 2046-08-09 192 | 2047-08-09 193 | 2048-08-09 194 | 2049-08-09 195 | 196 | 197 | 198 | name 199 | Christmas Day 200 | dates 201 | 202 | 2024-12-25 203 | 2025-12-25 204 | 2026-12-25 205 | 2027-12-25 206 | 2028-12-25 207 | 2029-12-25 208 | 2030-12-25 209 | 2031-12-25 210 | 2032-12-25 211 | 2033-12-25 212 | 2034-12-25 213 | 2035-12-25 214 | 2036-12-25 215 | 2037-12-25 216 | 2038-12-25 217 | 2039-12-25 218 | 2040-12-25 219 | 2041-12-25 220 | 2042-12-25 221 | 2043-12-25 222 | 2044-12-25 223 | 2045-12-25 224 | 2046-12-25 225 | 2047-12-25 226 | 2048-12-25 227 | 2049-12-25 228 | 229 | 230 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/sv.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Swedish (translation provided by andreashenriksson) 10 | "SNOOZE_TIME" = "Snooze-längd"; 11 | "HOURS" = "timmar"; 12 | "MINUTES" = "min"; 13 | "SECONDS" = "sek"; 14 | "RESET_DEFAULT" = "Återställ till standard"; 15 | "DEFAULT_SNOOZE_TIME" = "Standardtiden för snooze är %@."; 16 | "SKIP" = "Hoppa över"; 17 | "SKIP_TIME" = "Hoppa över tid"; 18 | "SKIP_ALARM" = "Hoppa över alarm"; 19 | "SKIP_QUESTION" = "Vill du hoppa över \"%@\" som är planerat att gå igång vid %@?"; 20 | "SKIP_TIME_EXPLANATION" = "Välj en viss tid innan alarmet går igång som du ska bli frågad att hoppa över alarmet."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/tr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Turkish (translation provided by keremy) 10 | "SNOOZE_TIME" = "Erteleme Süresi"; 11 | "HOURS" = "saat"; 12 | "MINUTES" = "dakika"; 13 | "SECONDS" = "saniye"; 14 | "RESET_DEFAULT" = "Varsayılana Sıfırla"; 15 | "DEFAULT_SNOOZE_TIME" = "Varsayılan erteleme saati %@."; 16 | "SKIP" = "Atla"; 17 | "SKIP_TIME" = "Atlama süresi"; 18 | "SKIP_ALARM" = "Alarmı atla"; 19 | "SKIP_QUESTION" = "%@ saatinde çalacak \"%@\"ı atlamak ister misiniz?"; 20 | "SKIP_TIME_EXPLANATION" = "Alarm çalmaya başlamadan alarmı atlayabileceğiniz bir süre seçin."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/vi.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Vietnamese (translation provided by tuancuongit) 10 | "SNOOZE_TIME" = "Thời gian hoãn"; 11 | "HOURS" = "Giờ"; 12 | "MINUTES" = "Phút"; 13 | "SECONDS" = "Giây"; 14 | "RESET_DEFAULT" = "Trả về mặc định"; 15 | "DEFAULT_SNOOZE_TIME" = "Thời gian hoãn mặc định là %@."; 16 | "SKIP" = "Bỏ qua"; 17 | "SKIP_TIME" = "Bỏ qua thời gian"; 18 | "SKIP_ALARM" = "Bỏ qua báo thức"; 19 | "SKIP_QUESTION" = "Bạn có muốn bỏ qua \"%@\", nó sẽ được tắt vào lúc %@"; 20 | "SKIP_TIME_EXPLANATION" = "Chọn khoảng thời gian mà bạn muốn được báo trước khi nó hú."; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/zh_CN.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Simplified Chinese (translation provided by alanbchk) 10 | "SNOOZE_TIME" = "稍后提醒"; 11 | "HOURS" = "时"; 12 | "MINUTES" = "分"; 13 | "SECONDS" = "秒"; 14 | "RESET_DEFAULT" = "重置默认"; 15 | "DEFAULT_SNOOZE_TIME" = "默认稍后提醒时间是 %@."; 16 | "SKIP" = "跳过"; 17 | "SKIP_TIME" = "跳过时间"; 18 | "SKIP_ALARM" = "跳过闹钟"; 19 | "SKIP_QUESTION" = "预计启动%@?你是否想要跳过\"%@\""; 20 | "SKIP_TIME_EXPLANATION" = "选择你会被提示跳过闹钟激发之前的时间量"; -------------------------------------------------------------------------------- /layout/Library/Application Support/Sleeper.bundle/zh_TW.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | 4 | 5 | Created by Joshua Seltzer on 1/21/15. 6 | 7 | */ 8 | 9 | // Traditional Chinese (translation provided by alanbchk) 10 | "SNOOZE_TIME" = "稍後提醒"; 11 | "HOURS" = "時"; 12 | "MINUTES" = "分"; 13 | "SECONDS" = "秒"; 14 | "RESET_DEFAULT" = "重置默認"; 15 | "DEFAULT_SNOOZE_TIME" = "默認稍後提醒時間是 %@."; 16 | "SKIP" = "跳過"; 17 | "SKIP_TIME" = "跳過時間"; 18 | "SKIP_ALARM" = "跳過鬧鐘"; 19 | "SKIP_QUESTION" = "預計啟動%@?你是否想要跳過 \"%@\""; 20 | "SKIP_TIME_EXPLANATION" = "選擇你會被提示跳過鬧鐘激發之前的時間量"; -------------------------------------------------------------------------------- /localized_helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | 6 | # path to the Sleeper bundle which is used to store the holidays and localized strings 7 | SLEEPER_BUNDLE_PATH = "layout/Library/Application Support/Sleeper.bundle" 8 | 9 | # function that will remove x number of lines from the end of the localized string files (to remove the unnecessary holiday names) 10 | def remove_trailing_localized_strings(num_lines): 11 | # list all of the directories in the Sleeper bundle 12 | for (dirpath, dirnames, filenames) in os.walk(SLEEPER_BUNDLE_PATH): 13 | for dirname in dirnames: 14 | # each lproj directory should only contain one file, the localized strings file 15 | string_file_path = os.path.join(SLEEPER_BUNDLE_PATH, dirname, LOCALIZED_STRINGS_FILE) 16 | with open(string_file_path, 'r') as fp: 17 | existing_lines = fp.readlines() 18 | with open(string_file_path, 'w') as fp: 19 | fixed_lines = existing_lines[:-num_lines] 20 | fixed_lines[-1] = fixed_lines[-1].rstrip() 21 | fp.writelines(fixed_lines) 22 | 23 | if __name__== "__main__": 24 | if len(sys.argv) == 3: 25 | if sys.argv[1] == "-r": 26 | # update the localized string files to remove unused localization strings 27 | # e.g. this includes files from v5.0.0 and v5.0.1 (this code was used to fix the files in v6.0.0) 28 | remove_trailing_localized_strings(sys.argv[2]) 29 | else: 30 | print("Incorrect usage!") -------------------------------------------------------------------------------- /ui/SLMTABedtimeViewController.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTABedtimeViewController.x 3 | // The view controller that lets a user configure the sleep alarm (used in iOS 11 and iOS 12). 4 | // 5 | // Created by Joshua Seltzer on 4/1/18. 6 | // 7 | // 8 | 9 | #import "SLUserInterfaceHeaders.h" 10 | #import "../common/SLCommonHeaders.h" 11 | #import "../common/SLCompatibilityHelper.h" 12 | 13 | // interface for the sleep alarm (i.e. Bedtime) view controller 14 | @interface MTABedtimeViewController : UIViewController 15 | 16 | // the options view controller that is used to configure the Bedtime alarm (iOS 12) 17 | @property (retain, nonatomic) MTABedtimeOptionsViewController *optionsController; 18 | 19 | // the data source corresponding to the alarm (iOS 12) 20 | @property (retain, nonatomic) MTAlarmDataSource *dataSource; 21 | 22 | @end 23 | 24 | // custom interface for added properties and methods 25 | @interface MTABedtimeViewController (Sleeper) 26 | 27 | // reset the skip activation status for the sleep alarm when any preferences are changed 28 | - (void)SLResetSkipActivatedStatus; 29 | 30 | @end 31 | 32 | %group iOS12 33 | 34 | %hook MTABedtimeViewController 35 | 36 | - (void)showOptions:(UIBarButtonItem *)optionsBarButtonItem 37 | { 38 | // If the options controller does not have the Sleeper properties set, set them now (iOS 12). On iOS 11, 39 | // the preferences are set when the options view is loaded from the Alarm Manager. 40 | NSString *alarmId = [self.dataSource.sleepAlarm alarmIDString]; 41 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 42 | if (alarmPrefs == nil) { 43 | self.optionsController.SLAlarmPrefs = [[SLAlarmPrefs alloc] initWithAlarmId:alarmId]; 44 | self.optionsController.SLAlarmPrefsChanged = YES; 45 | } else { 46 | self.optionsController.SLAlarmPrefs = alarmPrefs; 47 | self.optionsController.SLAlarmPrefsChanged = NO; 48 | } 49 | [self.optionsController updateDoneButtonEnabled]; 50 | 51 | %orig; 52 | } 53 | 54 | %end 55 | 56 | %end // %group iOS12 57 | 58 | %group iOS11 59 | 60 | %hook MTABedtimeViewController 61 | 62 | // Method that will set the reset the skip activation status when various views are edited. This is not needed 63 | // on iOS 12 since the MTAlarmManager's updateAlarm will be called anytime the sleep timer is edited. 64 | %new 65 | - (void)SLResetSkipActivatedStatus 66 | { 67 | // get the alarm ID for the special sleep alarm 68 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 69 | NSString *alarmId = [SLCompatibilityHelper alarmIdForAlarm:alarmManager.sleepAlarm]; 70 | 71 | // check if we have alarm preferences for this alarm 72 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 73 | if (alarmPrefs || alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 74 | // reset the skip activation status for this alarm 75 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 76 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 77 | } else if (!alarmPrefs) { 78 | alarmPrefs = [[SLAlarmPrefs alloc] initWithAlarmId:alarmId]; 79 | [SLPrefsManager saveAlarmPrefs:alarmPrefs]; 80 | } 81 | } 82 | 83 | - (void)circleViewDidEndEditing:(id)sleepAlarmClockView 84 | { 85 | // reset the skip activation status 86 | [self SLResetSkipActivatedStatus]; 87 | 88 | %orig; 89 | } 90 | 91 | - (void)enableSwitchToggled:(UISwitch *)enableSwitch 92 | { 93 | // reset the skip activation status 94 | [self SLResetSkipActivatedStatus]; 95 | 96 | %orig; 97 | } 98 | 99 | %end 100 | 101 | %end // %group iOS11 102 | 103 | %ctor { 104 | // only initialize this file for particular versions 105 | if (kSLSystemVersioniOS12) { 106 | %init(iOS12) 107 | } else if (kSLSystemVersioniOS11) { 108 | %init(iOS11); 109 | } 110 | } -------------------------------------------------------------------------------- /ui/SLMTASleepDetailViewController.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTASleepDetailViewController.x 3 | // The view controller which allows the user to change the sleep schedule for the bedtime alarm (iOS 13). 4 | // 5 | // Created by Joshua Seltzer on 11/22/19. 6 | // 7 | // 8 | 9 | #import "../common/SLCommonHeaders.h" 10 | #import "../common/SLAlarmPrefs.h" 11 | #import "../common/SLPrefsManager.h" 12 | #import "../common/SLCompatibilityHelper.h" 13 | 14 | // define an enum to reference the sections of the table view 15 | typedef enum SLSleepDetailViewControllerSection : NSUInteger { 16 | kSLSleepDetailViewControllerSectionScheduleToggle, 17 | kSLSleepDetailViewControllerSectionDaysOfWeekActive, 18 | kSLSleepDetailViewControllerNumSections 19 | } SLSleepDetailViewControllerSection; 20 | 21 | @interface MTASleepDetailViewController : UITableViewController 22 | 23 | // define the data source, which will include the sleep alarm 24 | @property (retain, nonatomic) MTAlarmDataSource *dataSource; 25 | 26 | @end 27 | 28 | // custom interface for added properties to the options controller 29 | @interface MTASleepDetailViewController (Sleeper) 30 | 31 | @property (nonatomic, retain) SLAlarmPrefs *SLAlarmPrefs; 32 | 33 | @end 34 | 35 | %hook MTASleepDetailViewController 36 | 37 | // the Sleeper preferences for the special sleep alarm 38 | %property (nonatomic, retain) SLAlarmPrefs *SLAlarmPrefs; 39 | 40 | - (void)viewDidLoad 41 | { 42 | // Load the preferences for the sleep alarm. The only reason we need the alarm preferences for this controller is to 43 | // potentially display the skip explanation string in the footer. 44 | NSString *alarmId = [self.dataSource.sleepAlarm alarmIDString]; 45 | self.SLAlarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 46 | 47 | %orig; 48 | } 49 | 50 | // Override with no implementation to prevent the footer string from being overridden. 51 | // As of iOS 13.2.2, this seems to be unused code / a bug since it is not shown unless we implement the 52 | // "titleForFooterInSection" delegate method. 53 | - (void)updateFooterWithSchedule:(NSInteger)schedule {} 54 | 55 | // potentially customize the footer text depending on whether or not the alarm is going to be skipped 56 | %new 57 | - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section 58 | { 59 | NSString *footerTitle = nil; 60 | if (self.SLAlarmPrefs != nil && section == kSLSleepDetailViewControllerSectionScheduleToggle) { 61 | footerTitle = [self.SLAlarmPrefs skipReasonExplanation]; 62 | } 63 | return footerTitle; 64 | } 65 | 66 | %end 67 | 68 | %ctor { 69 | if (kSLSystemVersioniOS13) { 70 | %init(); 71 | } 72 | } -------------------------------------------------------------------------------- /ui/SLMTSleepAlarmViewController.x: -------------------------------------------------------------------------------- 1 | // 2 | // SLMTSleepAlarmViewController.x 3 | // The view controller that lets a user configure the sleep alarm on iOS 10. 4 | // 5 | // Created by Joshua Seltzer on 2/26/17. 6 | // 7 | // 8 | 9 | #import "../common/SLCommonHeaders.h" 10 | #import "../common/SLAlarmPrefs.h" 11 | #import "../common/SLPrefsManager.h" 12 | #import "../common/SLCompatibilityHelper.h" 13 | 14 | // interface for the sleep alarm view controller 15 | @interface MTSleepAlarmViewController : UIViewController 16 | 17 | // reset the skip activation status for the sleep alarm when any preferences are changed 18 | - (void)SLResetSkipActivatedStatus; 19 | 20 | @end 21 | 22 | %hook MTSleepAlarmViewController 23 | 24 | %new 25 | - (void)SLResetSkipActivatedStatus 26 | { 27 | // get the alarm ID for the special sleep alarm 28 | AlarmManager *alarmManager = (AlarmManager *)[objc_getClass("AlarmManager") sharedManager]; 29 | NSString *alarmId = [SLCompatibilityHelper alarmIdForAlarm:alarmManager.sleepAlarm]; 30 | 31 | // check if we have alarm preferences for this alarm 32 | SLAlarmPrefs *alarmPrefs = [SLPrefsManager alarmPrefsForAlarmId:alarmId]; 33 | if (alarmPrefs && alarmPrefs.skipActivationStatus != kSLSkipActivatedStatusUnknown) { 34 | // reset the skip activation status for this alarm 35 | [SLPrefsManager setSkipActivatedStatusForAlarmId:alarmId 36 | skipActivatedStatus:kSLSkipActivatedStatusUnknown]; 37 | } else if (!alarmPrefs) { 38 | alarmPrefs = [[SLAlarmPrefs alloc] initWithAlarmId:alarmId]; 39 | [SLPrefsManager saveAlarmPrefs:alarmPrefs]; 40 | } 41 | } 42 | 43 | - (void)circleViewDidEndEditing:(id)sleepAlarmClockView 44 | { 45 | // reset the skip activation status 46 | [self SLResetSkipActivatedStatus]; 47 | 48 | %orig; 49 | } 50 | 51 | - (void)enableSwitchToggled:(UISwitch *)enableSwitch 52 | { 53 | // reset the skip activation status 54 | [self SLResetSkipActivatedStatus]; 55 | 56 | %orig; 57 | } 58 | 59 | %end 60 | 61 | %ctor { 62 | // only initialize this file if we are on iOS 10 63 | if (kSLSystemVersioniOS10) { 64 | %init(); 65 | } 66 | } -------------------------------------------------------------------------------- /ui/SLUserInterfaceHeaders.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLUserInterfaceHeaders.h 3 | // Contains all interfaces required for the User Interface project. 4 | // 5 | // Created by Joshua Seltzer on 2/15/20. 6 | // 7 | // 8 | 9 | #import "custom/SLSkipTimeViewController.h" 10 | #import "custom/SLSkipDatesViewController.h" 11 | 12 | // table view controller which configures the settings for the sleep alarm 13 | @interface MTABedtimeOptionsViewController : UITableViewController 14 | 15 | // updates the status of the done button on the view controller 16 | - (void)updateDoneButtonEnabled; 17 | 18 | @end 19 | 20 | // custom interface for added properties to the options controller 21 | @interface MTABedtimeOptionsViewController (Sleeper) 22 | 23 | @property (nonatomic, retain) SLAlarmPrefs *SLAlarmPrefs; 24 | @property (nonatomic, assign) BOOL SLAlarmPrefsChanged; 25 | 26 | @end -------------------------------------------------------------------------------- /ui/custom/SLAutoSetOptionsTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLAutoSetOptionsTableViewController.h 3 | // Table view controller that presents the user with various options to configure the timer to automatically be set. 4 | // 5 | // Created by Joshua Seltzer on 7/1/20. 6 | // Copyright © 2020 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SLEditDateTimeViewController.h" 11 | #import "../../common/SLPrefsManager.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | // forward delcare the view controller class so that we can define it in the delegate 16 | @class SLAutoSetOptionsTableViewController; 17 | 18 | // delegate that will notify the object that holidays have been updated 19 | @protocol SLAutoSetOptionsDelegate 20 | 21 | // passes the updated auto-set selection and options to the delegate 22 | - (void)SLAutoSetOptionsTableViewController:(SLAutoSetOptionsTableViewController *)autoSetOptionsTableViewController 23 | didUpdateAutoSetOption:(SLAutoSetOption)autoSetOption 24 | withAutoSetOffsetOption:(SLAutoSetOffsetOption)autoSetOffsetOption 25 | withAutoSetOffsetHour:(NSInteger)autoSetOffsetHour 26 | withAutoSetOffsetMinute:(NSInteger)autoSetOffsetMinute; 27 | 28 | @end 29 | 30 | @interface SLAutoSetOptionsTableViewController : UITableViewController 31 | 32 | // initialize this controller with the selected auto-set settings 33 | - (instancetype)initWithAutoSetOption:(SLAutoSetOption)autoSetOption 34 | autoSetOffsetOption:(SLAutoSetOffsetOption)autoSetOffsetOption 35 | autoSetOffsetHour:(NSInteger)autoSetOffsetHour 36 | autoSetOffsetMinute:(NSInteger)autoSetOffsetMinute; 37 | 38 | // the delegate of this view controller 39 | @property (nonatomic, weak) id delegate; 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /ui/custom/SLEditDateTimeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLEditDateTimeViewController.h 3 | // 4 | // Created by Joshua Seltzer on 1/3/19. 5 | // Copyright © 2019 Joshua Seltzer. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | // forward delcare the view controller class so that we can define it in the delegate 11 | @class SLEditDateTimeViewController; 12 | 13 | // define the height of the picker view 14 | #define kSLEditDateTimePickerViewHeight 216.0 15 | 16 | // delegate for this controller 17 | @protocol SLEditDateTimeViewControllerDelegate 18 | 19 | // all methods are optional since the delegate methods that are called will differ depending on which type of data is being edited 20 | @optional 21 | 22 | // notify the delegate that the date was saved 23 | - (void)SLEditDateTimeViewController:(SLEditDateTimeViewController *)editDateTimeViewController didSaveDate:(NSDate *)date; 24 | 25 | // notify the delegate that the hours/minutes were saved 26 | - (void)SLEditDateTimeViewController:(SLEditDateTimeViewController *)editDateTimeViewController didSaveHours:(NSInteger)hours andMinutes:(NSInteger)minutes; 27 | 28 | // notify the delegate that the selection was cancelled 29 | - (void)SLEditDateTimeViewControllerDidCancelSelection:(SLEditDateTimeViewController *)editDateTimeViewController; 30 | 31 | @end 32 | 33 | // customized view controller which simply contains a date or time picker view 34 | @interface SLEditDateTimeViewController : UIViewController 35 | 36 | // Initialize this controller with a required title and optional dates. Using this initilizer will put the picker in date mode. 37 | - (instancetype)initWithTitle:(NSString *)title initialDate:(NSDate *)initialDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate; 38 | 39 | // Initialize this controller with a required title and optional hour/minutes. Using this initilizer will put the picker in countdown timer mode. 40 | - (instancetype)initWithTitle:(NSString *)title initialHours:(NSInteger)initialHours initialMinutes:(NSInteger)initialMinutes maximumHours:(NSInteger)maximumHours; 41 | 42 | // the delegate of this view controller 43 | @property (nonatomic, weak) id delegate; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ui/custom/SLHolidaySelectionTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLHolidaySelectionTableViewController.h 3 | // Table view controller that allows the user to pick from a list of holidays. 4 | // 5 | // Created by Joshua Seltzer on 1/12/19. 6 | // Copyright © 2019 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "../../common/SLPrefsManager.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | // forward delcare the view controller class so that we can define it in the delegate 15 | @class SLHolidaySelectionTableViewController; 16 | 17 | // delegate that will notify the object that holidays have been updated 18 | @protocol SLHolidaySelectionDelegate 19 | 20 | // passes the updated holiday selections for the holiday country 21 | - (void)SLHolidaySelectionTableViewController:(SLHolidaySelectionTableViewController *)holidaySelectionTableViewController 22 | didUpdateSelectedHolidays:(NSArray *)selectedHolidays 23 | forHolidayCountry:(SLHolidayCountry)holidayCountry; 24 | 25 | @end 26 | 27 | @interface SLHolidaySelectionTableViewController : UITableViewController 28 | 29 | // initialize this controller with the selected holidays and available holidays for a given holiday country 30 | - (instancetype)initWithSelectedHolidays:(NSArray *)selectedHolidays holidayResource:(NSDictionary *)holidayResource inHolidayCountry:(SLHolidayCountry)holidayCountry; 31 | 32 | // the delegate of this view controller 33 | @property (nonatomic, weak) id delegate; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /ui/custom/SLPartialModalPresentationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLPartialModalPresentationController.h 3 | // 4 | // Created by Joshua Seltzer on 1/3/19. 5 | // Copyright © 2019 Joshua Seltzer. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | // the custom presentation controller which is used to display a partial modal controller 11 | @interface SLPartialModalPresentationController : UIPresentationController 12 | 13 | // create a custom initialization to take in a percentage of how much to show the partial modal on 14 | // the screen and whether or not we can swipe to dismiss the presented controller 15 | - (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController 16 | presentingViewController:(UIViewController *)presentingViewController 17 | partialModalPercentage:(CGFloat)partialModalPercentage 18 | allowSwipeDismissal:(BOOL)allowSwipeDismissal; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ui/custom/SLPartialModalPresentationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SLPartialModalPresentationController.m 3 | // 4 | // Created by Joshua Seltzer on 1/3/19. 5 | // Copyright © 2019 Joshua Seltzer. All rights reserved. 6 | // 7 | 8 | #import "SLPartialModalPresentationController.h" 9 | 10 | @interface SLPartialModalPresentationController () 11 | 12 | // the blurred view that will add blur to the presenting view controller background 13 | @property (nonatomic, strong) UIView *blurredView; 14 | 15 | // the percentage of the screen that should be displayed for this modal controller 16 | @property (nonatomic) CGFloat partialModalPercentage; 17 | 18 | // boolean which signifies whether or not we allow a swipe dismissal for the presented view controller 19 | @property (nonatomic) BOOL allowSwipeDismissal; 20 | 21 | @end 22 | 23 | @implementation SLPartialModalPresentationController 24 | 25 | // create a custom initialization to take in a percentage of how much to show the partial modal on 26 | // the screen 27 | - (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController 28 | presentingViewController:(UIViewController *)presentingViewController 29 | partialModalPercentage:(CGFloat)partialModalPercentage 30 | allowSwipeDismissal:(BOOL)allowSwipeDismissal 31 | { 32 | self = [super initWithPresentedViewController:presentedViewController 33 | presentingViewController:presentingViewController]; 34 | if (self) { 35 | // set the partial modal percentage and swipe ability for this modal presentation 36 | self.partialModalPercentage = partialModalPercentage; 37 | self.allowSwipeDismissal = allowSwipeDismissal; 38 | } 39 | return self; 40 | } 41 | 42 | // override the getter for the blurred view 43 | - (UIView *)blurredView 44 | { 45 | // lazily load the blurred view once 46 | if (_blurredView == nil) { 47 | UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.containerView.bounds.size.width, self.containerView.bounds.size.height)]; 48 | 49 | // create a blur affect on the view 50 | UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; 51 | UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 52 | blurEffectView.frame = view.bounds; 53 | [view addSubview:blurEffectView]; 54 | 55 | // add a swipe gesture to the blurred view to dismiss the presented view controller if enabled 56 | if (self.allowSwipeDismissal) { 57 | UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(blurredViewSwiped:)]; 58 | swipeGesture.direction = UISwipeGestureRecognizerDirectionDown; 59 | [view addGestureRecognizer:swipeGesture]; 60 | } 61 | 62 | _blurredView = view; 63 | } 64 | 65 | return _blurredView; 66 | } 67 | 68 | // invoked when the user swipes down on the blurred view 69 | - (void)blurredViewSwiped:(UITapGestureRecognizer *)tapGesture 70 | { 71 | // dismiss the presented view controller 72 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 73 | } 74 | 75 | - (CGRect)frameOfPresentedViewInContainerView 76 | { 77 | // create the frame for the view that will be presented based off of the modal percentage 78 | return CGRectMake(0.0, 79 | self.containerView.bounds.size.height * (1.0 - self.partialModalPercentage), 80 | self.containerView.bounds.size.width, 81 | self.containerView.bounds.size.height * self.partialModalPercentage); 82 | } 83 | 84 | - (void)presentationTransitionWillBegin 85 | { 86 | if (self.containerView != nil && self.presentingViewController.transitionCoordinator != nil) { 87 | // add the blurred view to the container view 88 | self.blurredView.alpha = 0.0; 89 | [self.containerView addSubview:self.blurredView]; 90 | [self.blurredView addSubview:self.presentedViewController.view]; 91 | 92 | // animate the alpha of the blurred view 93 | [self.presentingViewController.transitionCoordinator animateAlongsideTransition:^(id _Nonnull context) { 94 | self.blurredView.alpha = 1.0; 95 | } 96 | completion:nil]; 97 | } 98 | } 99 | 100 | - (void)dismissalTransitionWillBegin 101 | { 102 | if (self.presentingViewController.transitionCoordinator != nil) { 103 | // animate the alpha of the blurred view 104 | [self.presentingViewController.transitionCoordinator animateAlongsideTransition:^(id _Nonnull context) { 105 | self.blurredView.alpha = 0.0; 106 | } 107 | completion:nil]; 108 | } 109 | } 110 | 111 | - (void)dismissalTransitionDidEnd:(BOOL)completed 112 | { 113 | // once the transition is completed, destroy the blurred view that was created 114 | if (completed) { 115 | [self.blurredView removeFromSuperview]; 116 | self.blurredView = nil; 117 | } 118 | } 119 | 120 | // override to disable showing in full screen for this presentation controller 121 | - (BOOL)shouldPresentInFullscreen 122 | { 123 | return NO; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /ui/custom/SLPickerTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLPickerTableViewController.h 3 | // Custom view controller with a time picker (hours, minutes, and seconds) on top with a table view on the bottom. 4 | // 5 | // Created by Joshua Seltzer on 9/24/15. 6 | // Copyright (c) 2015 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | // forward delcare the view controller class so that we can define it in the delegate 13 | @class SLPickerTableViewController; 14 | 15 | // delegate that will notify the object that the picker times have been updated 16 | @protocol SLPickerSelectionDelegate 17 | 18 | // passes the updated picker times to the delegate 19 | - (void)SLPickerTableViewController:(SLPickerTableViewController *)pickerTableViewController 20 | didUpdateWithHours:(NSInteger)hours 21 | minutes:(NSInteger)minutes 22 | seconds:(NSInteger)seconds; 23 | 24 | @end 25 | 26 | @interface SLPickerTableViewController : UIViewController 27 | 28 | // custom initialization method that sets the picker to the given times 29 | - (id)initWithHours:(NSInteger)hours 30 | minutes:(NSInteger)minutes 31 | seconds:(NSInteger)seconds; 32 | 33 | // move the time picker to the given hour, minute, and second values 34 | - (void)changePickerTimeWithHours:(NSInteger)hours 35 | minutes:(NSInteger)minutes 36 | seconds:(NSInteger)seconds 37 | animated:(BOOL)animated; 38 | 39 | // the options table which will take up the rest of the view 40 | @property (nonatomic, strong) UITableView *optionsTableView; 41 | 42 | // the delegate of this view controller 43 | @property (nonatomic, weak) id delegate; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ui/custom/SLSkipDatesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLSkipDatesViewController.h 3 | // 4 | // Created by Joshua Seltzer on 1/2/19. 5 | // Copyright © 2019 Joshua Seltzer. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "SLEditDateTimeViewController.h" 10 | #import "SLHolidaySelectionTableViewController.h" 11 | #import "../../common/SLAlarmPrefs.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | // forward delcare the view controller class so that we can define it in the delegate 16 | @class SLSkipDatesViewController; 17 | 18 | // delegate that will notify the object that skip dates have been updated 19 | @protocol SLSkipDatesDelegate 20 | 21 | // passes the updated picker times to the delegate 22 | - (void)SLSkipDatesViewController:(SLSkipDatesViewController *)skipDatesViewController 23 | didUpdateCustomSkipDates:(NSArray *)customSkipDates 24 | holidaySkipDates:(NSDictionary *)holidaySkipDates; 25 | 26 | @end 27 | 28 | @interface SLSkipDatesViewController : UITableViewController 29 | 30 | // initialize this controller with the preferences for the given alarm 31 | - (instancetype)initWithAlarmPrefs:(SLAlarmPrefs *)alarmPrefs; 32 | 33 | // the delegate of this view controller 34 | @property (nonatomic, weak) id delegate; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /ui/custom/SLSkipTimeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLSkipTimeViewController.h 3 | // Customized picker table view controller for selecting the skip time. 4 | // 5 | // Created by Joshua Seltzer on 7/19/15. 6 | // Copyright (c) 2015 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import "SLPickerTableViewController.h" 10 | 11 | @interface SLSkipTimeViewController : SLPickerTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ui/custom/SLSkipTimeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SLSkipTimeViewController.m 3 | // Customized picker table view controller for selecting the skip time. 4 | // 5 | // Created by Joshua Seltzer on 7/19/15. 6 | // Copyright (c) 2015 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import "SLSkipTimeViewController.h" 10 | #import "../../common/SLLocalizedStrings.h" 11 | 12 | @implementation SLSkipTimeViewController 13 | 14 | // override to customize the view upon load 15 | - (void)viewDidLoad 16 | { 17 | [super viewDidLoad]; 18 | 19 | // set the title of the view controller 20 | self.title = kSLSkipTimeString; 21 | self.optionsTableView.scrollEnabled = NO; 22 | } 23 | 24 | #pragma mark - UITableViewDataSource 25 | 26 | // returns the number of sections for a table view 27 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 28 | { 29 | // return a single section so that we can display a footer message in the table 30 | return 1; 31 | } 32 | 33 | // returns the number of rows for a table view 34 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 35 | { 36 | // there are no rows for this table 37 | return 0; 38 | } 39 | 40 | // returns a cell for a table at an index path 41 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 42 | { 43 | // Since we are not creating any cells, this function will never get called. Therefore we are 44 | // safe returning nil here. 45 | return nil; 46 | } 47 | 48 | // return a footer view for each table view section 49 | - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section 50 | { 51 | return kSLSkipTimeExplanationString; 52 | } 53 | 54 | #pragma mark - UITableViewDelegate 55 | 56 | // return to include some space between the time picker view and the message we will display in the 57 | // footer 58 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 59 | { 60 | return 5.0f; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /ui/custom/SLSnoozeTimeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SLSnoozeTimeViewController.h 3 | // Customized picker table view controller for selecting the snooze time. 4 | // 5 | // Created by Joshua Seltzer on 10/12/14. 6 | // Copyright (c) 2014 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import "SLPickerTableViewController.h" 10 | 11 | @interface SLSnoozeTimeViewController : SLPickerTableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ui/custom/SLSnoozeTimeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SLSnoozeTimeViewController.m 3 | // Customized picker table view controller for selecting the snooze time. 4 | // 5 | // Created by Joshua Seltzer on 10/12/14. 6 | // Copyright (c) 2014 Joshua Seltzer. All rights reserved. 7 | // 8 | 9 | #import "SLSnoozeTimeViewController.h" 10 | #import "../../common/SLPrefsManager.h" 11 | #import "../../common/SLLocalizedStrings.h" 12 | #import "../../common/SLCompatibilityHelper.h" 13 | 14 | @implementation SLSnoozeTimeViewController 15 | 16 | // override to customize the view upon load 17 | - (void)viewDidLoad 18 | { 19 | [super viewDidLoad]; 20 | 21 | // set the title of the view controller 22 | self.title = kSLSnoozeTimeString; 23 | } 24 | 25 | #pragma mark - UITableViewDataSource 26 | 27 | // returns the number of sections for a table view 28 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 29 | { 30 | return 1; 31 | } 32 | 33 | // returns the number of rows for a table view 34 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 35 | { 36 | return 1; 37 | } 38 | 39 | // returns a cell for a table at an index path 40 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 41 | { 42 | // create an identifier for our table view cell 43 | static NSString *const optionTableButtonCellIdentifier = @"optionTableButtonCellIdentifier"; 44 | 45 | // attempt to dequeue the cell from the table 46 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:optionTableButtonCellIdentifier]; 47 | 48 | // if the cell doesn't exist yet, create a new one 49 | if (!cell) { 50 | // create a new default cell 51 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 52 | reuseIdentifier:optionTableButtonCellIdentifier]; 53 | 54 | // on newer versions of iOS, we need to set the background views for the cell 55 | if (kSLSystemVersioniOS14 || kSLSystemVersioniOS13) { 56 | cell.backgroundColor = [SLCompatibilityHelper tableViewCellBackgroundColor]; 57 | } 58 | 59 | // set the background color of the cell to clear to remove the selection color 60 | if (@available(iOS 10.0, *)) { 61 | UIView *backgroundView = [[UIView alloc] init]; 62 | backgroundView.backgroundColor = [SLCompatibilityHelper tableViewCellSelectedBackgroundColor]; 63 | cell.selectedBackgroundView = backgroundView; 64 | } 65 | } 66 | 67 | // customize the cell 68 | cell.textLabel.text = kSLResetDefaultString; 69 | cell.textLabel.textAlignment = NSTextAlignmentCenter; 70 | 71 | // set the color of the button to the red, destructive color as defined by Apple in other cells 72 | cell.textLabel.textColor = [SLCompatibilityHelper destructiveLabelColor]; 73 | 74 | return cell; 75 | } 76 | 77 | // return a footer view for each table view section 78 | - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section 79 | { 80 | // We only have one section which defines the default snooze button. Display a message indicating 81 | // to the user what the default snooze time is 82 | NSString *defaultSnoozeTime = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)kSLDefaultSnoozeHour, 83 | (long)kSLDefaultSnoozeMinute, (long)kSLDefaultSnoozeSecond]; 84 | return kSLDefaultSnoozeTimeString(defaultSnoozeTime); 85 | } 86 | 87 | #pragma mark - UITableViewDelegate 88 | 89 | // handle table view cell selection 90 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 91 | { 92 | // for now, we only have one button so we can assume it is the one that resets the default snooze 93 | // picker values 94 | [self changePickerTimeWithHours:kSLDefaultSnoozeHour 95 | minutes:kSLDefaultSnoozeMinute 96 | seconds:kSLDefaultSnoozeSecond 97 | animated:YES]; 98 | 99 | // deselect the row with animation 100 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 101 | } 102 | 103 | @end 104 | --------------------------------------------------------------------------------