From 80ca7b6ff0a27795341c717060591c503d2a5de1 Mon Sep 17 00:00:00 2001 From: Gil Shahar Date: Mon, 7 Jan 2019 08:09:57 +0200 Subject: [PATCH] Version 1.0 --- DuplexCalendar.plist | 1 + Makefile | 17 ++ Tweak.xm | 147 ++++++++++++++++++ control | 9 ++ duplexcalendarprefs/DCPRootListController.h | 5 + duplexcalendarprefs/DCPRootListController.m | 40 +++++ duplexcalendarprefs/Makefile | 13 ++ duplexcalendarprefs/Resources/Info.plist | 24 +++ duplexcalendarprefs/Resources/Root.plist | 69 ++++++++ duplexcalendarprefs/entry.plist | 21 +++ ...hahar7.duplexcalendar_1.0_iphoneos-arm.deb | Bin 0 -> 20728 bytes 11 files changed, 346 insertions(+) create mode 100644 DuplexCalendar.plist create mode 100644 Makefile create mode 100644 Tweak.xm create mode 100644 control create mode 100644 duplexcalendarprefs/DCPRootListController.h create mode 100644 duplexcalendarprefs/DCPRootListController.m create mode 100644 duplexcalendarprefs/Makefile create mode 100644 duplexcalendarprefs/Resources/Info.plist create mode 100644 duplexcalendarprefs/Resources/Root.plist create mode 100644 duplexcalendarprefs/entry.plist create mode 100644 packages/com.gilshahar7.duplexcalendar_1.0_iphoneos-arm.deb diff --git a/DuplexCalendar.plist b/DuplexCalendar.plist new file mode 100644 index 0000000..10dc654 --- /dev/null +++ b/DuplexCalendar.plist @@ -0,0 +1 @@ +{ Filter = { Bundles = ( "com.apple.springboard" ); }; } diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..103e6a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ + +GO_EASY_ON_ME = 1 + +ARCHS = arm64 armv7 + +include $(THEOS)/makefiles/common.mk + +TWEAK_NAME = DuplexCalendar +DuplexCalendar_FILES = Tweak.xm +DuplexCalendar_FRAMEWORKS = CoreTelephony AudioToolbox + +include $(THEOS_MAKE_PATH)/tweak.mk + +after-install:: + install.exec "killall -9 SpringBoard" +SUBPROJECTS += duplexcalendarprefs +include $(THEOS_MAKE_PATH)/aggregate.mk diff --git a/Tweak.xm b/Tweak.xm new file mode 100644 index 0000000..f468603 --- /dev/null +++ b/Tweak.xm @@ -0,0 +1,147 @@ +#define kScreenWidth [[UIScreen mainScreen] bounds].size.width +#import +#import +@interface SBTodayTableHeaderView : UIView +-(NSString *)lunarDateHeaderString; +@end + +@interface SBFLockScreenDateView : UIView +@property (nonatomic, assign) UILabel *duplexCalendarLabel; +@property (nonatomic, assign) SBTodayTableHeaderView *todayHeaderView; +@property (nonatomic, assign) NSString *todayHeaderViewText; +@property bool dateHidden; +-(id)_dateFont; +-(id)_dateColor; +-(BOOL)isDateHidden; +-(void)layoutDuplexCalendarLabel; +@end + + +@interface _UILegibilityView : UIView +@end + +@interface _UILegibilityLabel : _UILegibilityView +@property (nonatomic, assign) NSString* string; +@property (nonatomic, assign) UIFont* font; + +@end + +extern "C" CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void); +static NSString *myObserver=@"duplexcalendarObserver"; +static NSString *settingsPath = @"/var/mobile/Library/Preferences/com.gilshahar7.duplexcalendarprefs.plist"; +static NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath]; + +static void savePressed(){ + prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath]; +} + +static void savePressed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo){ + prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsPath]; +} + +static SBTodayTableHeaderView *stattodayHeaderView; +static float originx = 0.0; +static float originy = 0.0; +static float sizewidth = 0.0; +static float sizeheight = 0.0; + +%hook SBTodayTableHeaderView +-(SBTodayTableHeaderView *)initWithFrame:(CGRect)arg1{ + stattodayHeaderView = %orig(); + return stattodayHeaderView; +} +%end + +%hook SBFLockScreenDateView +%property (nonatomic, assign) UILabel *duplexCalendarLabel; +%property (nonatomic, assign) NSString *todayHeaderViewText; +-(SBFLockScreenDateView *)initWithFrame:(id)arg1{ + SBFLockScreenDateView *origself = %orig(arg1); + if(!self.duplexCalendarLabel){ + self.duplexCalendarLabel = [[UILabel alloc] initWithFrame:CGRectMake(originx-50, originy + 19, sizewidth+100, sizeheight)]; + self.duplexCalendarLabel.font = [[self _dateFont] fontWithSize:16]; + [self addSubview:self.duplexCalendarLabel]; + self.duplexCalendarLabel.textColor = [self _dateColor]; + self.duplexCalendarLabel.textAlignment = 1; + } + return origself; +} + +%new +-(void)layoutDuplexCalendarLabel{ + NSString *offsetXTextField = [prefs objectForKey:@"offsetXTextField"]; + NSString *offsetYTextField = [prefs objectForKey:@"offsetYTextField"]; + NSString *FontSizeTextField = [prefs objectForKey:@"FontSizeTextField"]; + + if(originx <= 0.0) + { + UILabel *originalLabel = MSHookIvar(self, "_dateLabel"); + originx = originalLabel.frame.origin.x; + originy = originalLabel.frame.origin.y; + sizewidth = originalLabel.frame.size.width; + sizeheight = originalLabel.frame.size.height; + } + [self.duplexCalendarLabel setFrame:CGRectMake(originx-50+ [offsetXTextField floatValue], originy + 19 + [offsetYTextField floatValue], sizewidth+100, sizeheight)]; + UIFont *font = self.duplexCalendarLabel.font; + if([FontSizeTextField floatValue] == 0){ + self.duplexCalendarLabel.font = [font fontWithSize:16.0]; + }else{ + self.duplexCalendarLabel.font = [font fontWithSize:[FontSizeTextField floatValue]]; + } + if(self.duplexCalendarLabel){ + if([self isDateHidden]){ + self.duplexCalendarLabel.hidden = true; + }else{ + self.duplexCalendarLabel.hidden = false; + } + } +} + +-(void)_updateLabels{ + [self layoutDuplexCalendarLabel]; + if(!self.todayHeaderViewText){ + self.todayHeaderViewText = [stattodayHeaderView lunarDateHeaderString]; + } + self.duplexCalendarLabel.text = self.todayHeaderViewText; + + + %orig; + +} +-(void)_layoutDateLabel { + [self layoutDuplexCalendarLabel]; + %orig; + _UILegibilityLabel *originalLegibilityLabel = MSHookIvar<_UILegibilityLabel *>(self, "_legibilityDateLabel"); + [originalLegibilityLabel setFrame:CGRectMake(originx, originy - 3, sizewidth, sizeheight)]; +} +-(void)updateFormat{ + [self layoutDuplexCalendarLabel]; + %orig; +} +-(void)layoutSubviews { + [self layoutDuplexCalendarLabel]; + %orig; +} + + +-(void)setDateHidden:(bool)arg1{ + %orig(arg1); + + if(self.duplexCalendarLabel){ + self.duplexCalendarLabel.hidden = arg1; + } +} + + +%end + + +%ctor{ + CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), + (void*)myObserver, + savePressed, + CFSTR("duplexcalendar.savepressed"), + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + savePressed(); +} diff --git a/control b/control new file mode 100644 index 0000000..f7b1df6 --- /dev/null +++ b/control @@ -0,0 +1,9 @@ +Package: com.gilshahar7.duplexcalendar +Name: DuplexCalendar +Depends: mobilesubstrate +Version: 1.0 +Architecture: iphoneos-arm +Description: Add the alternate calendar label to the LockScreen on iOS 9. +Maintainer: gilshahar7 +Author: gilshahar7 +Section: Tweaks diff --git a/duplexcalendarprefs/DCPRootListController.h b/duplexcalendarprefs/DCPRootListController.h new file mode 100644 index 0000000..10f31b1 --- /dev/null +++ b/duplexcalendarprefs/DCPRootListController.h @@ -0,0 +1,5 @@ +#import + +@interface DCPRootListController : PSListController + +@end diff --git a/duplexcalendarprefs/DCPRootListController.m b/duplexcalendarprefs/DCPRootListController.m new file mode 100644 index 0000000..67a3299 --- /dev/null +++ b/duplexcalendarprefs/DCPRootListController.m @@ -0,0 +1,40 @@ +#import +#include "DCPRootListController.h" + +@implementation DCPRootListController + +- (id)readPreferenceValue:(PSSpecifier*)specifier { + NSString *path = [NSString stringWithFormat:@"/User/Library/Preferences/%@.plist", specifier.properties[@"defaults"]]; + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:path]]; + return (settings[specifier.properties[@"key"]]) ?: specifier.properties[@"default"]; +} + +- (void)setPreferenceValue:(id)value specifier:(PSSpecifier*)specifier { + NSString *path = [NSString stringWithFormat:@"/User/Library/Preferences/%@.plist", specifier.properties[@"defaults"]]; + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:path]]; + [settings setObject:value forKey:specifier.properties[@"key"]]; + [settings writeToFile:path atomically:YES]; + CFStringRef notificationName = (CFStringRef)specifier.properties[@"PostNotification"]; + if (notificationName) { + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), notificationName, NULL, NULL, YES); + } +} + +- (NSArray *)specifiers { + if (!_specifiers) { + _specifiers = [[self loadSpecifiersFromPlistName:@"Root" target:self] retain]; + } + + return _specifiers; +} + +-(void)save +{ + [self.view endEditing:YES]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("duplexcalendar.savepressed"), NULL, NULL, YES); +} + + +@end diff --git a/duplexcalendarprefs/Makefile b/duplexcalendarprefs/Makefile new file mode 100644 index 0000000..b100ffa --- /dev/null +++ b/duplexcalendarprefs/Makefile @@ -0,0 +1,13 @@ +include $(THEOS)/makefiles/common.mk + +BUNDLE_NAME = DuplexCalendarPrefs +DuplexCalendarPrefs_FILES = DCPRootListController.m +DuplexCalendarPrefs_INSTALL_PATH = /Library/PreferenceBundles +DuplexCalendarPrefs_FRAMEWORKS = UIKit +DuplexCalendarPrefs_PRIVATE_FRAMEWORKS = Preferences + +include $(THEOS_MAKE_PATH)/bundle.mk + +internal-stage:: + $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) + $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/DuplexCalendarPrefs.plist$(ECHO_END) diff --git a/duplexcalendarprefs/Resources/Info.plist b/duplexcalendarprefs/Resources/Info.plist new file mode 100644 index 0000000..d49ef6e --- /dev/null +++ b/duplexcalendarprefs/Resources/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + DuplexCalendarPrefs + CFBundleIdentifier + com.gilshahar7.duplexcalendarprefs + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSPrincipalClass + DCPRootListController + + diff --git a/duplexcalendarprefs/Resources/Root.plist b/duplexcalendarprefs/Resources/Root.plist new file mode 100644 index 0000000..6e44499 --- /dev/null +++ b/duplexcalendarprefs/Resources/Root.plist @@ -0,0 +1,69 @@ + + + + + items + + + cell + PSGroupCell + label + DuplexCalendar's Options + + + cell + PSEditTextCell + placeholder + 0 + bestGuess + 0 + defaults + com.gilshahar7.duplexcalendarprefs + key + offsetXTextField + label + X Offset: + + + cell + PSEditTextCell + placeholder + 0 + bestGuess + 0 + defaults + com.gilshahar7.duplexcalendarprefs + key + offsetYTextField + label + Y Offset: + + + cell + PSEditTextCell + placeholder + 16 + bestGuess + 16 + defaults + com.gilshahar7.duplexcalendarprefs + isDecimalPad + + key + FontSizeTextField + label + Font Size: + + + cell + PSButtonCell + label + Save + action + save + + + title + DuplexCalendar + + diff --git a/duplexcalendarprefs/entry.plist b/duplexcalendarprefs/entry.plist new file mode 100644 index 0000000..b4ea673 --- /dev/null +++ b/duplexcalendarprefs/entry.plist @@ -0,0 +1,21 @@ + + + + + entry + + bundle + DuplexCalendarPrefs + cell + PSLinkCell + detail + DCPRootListController + icon + icon.png + isController + + label + DuplexCalendarPrefs + + + diff --git a/packages/com.gilshahar7.duplexcalendar_1.0_iphoneos-arm.deb b/packages/com.gilshahar7.duplexcalendar_1.0_iphoneos-arm.deb new file mode 100644 index 0000000000000000000000000000000000000000..a85870d9494013ab6d111fc558d37c57582fda22 GIT binary patch literal 20728 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¥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 O+e