From 545370d8377a9e8267cf20d49ab29d9f5c5678ff Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sat, 7 Nov 2009 22:48:32 +0000 Subject: [PATCH] Checkpoint for Optimo test. --- CydgetCentral.plist | 2 + CydgetSettings.mm | 356 ++++++++++++++++++++++++++++++++ CydgetSettings.plist | 19 ++ Index.html | 74 ++++++- LockScreen.mm | 7 + SearchResultsCheckmarkClear.png | Bin 0 -> 73 bytes Tweak.mm | 75 +++++++ control | 2 +- makefile | 15 +- 9 files changed, 543 insertions(+), 7 deletions(-) create mode 100644 CydgetSettings.mm create mode 100644 CydgetSettings.plist create mode 100644 SearchResultsCheckmarkClear.png diff --git a/CydgetCentral.plist b/CydgetCentral.plist index dfbce56..ba2e841 100644 --- a/CydgetCentral.plist +++ b/CydgetCentral.plist @@ -1,5 +1,7 @@ Plugin = "WebCycriptLockScreen"; + Configuration = { Homepage = "file:///System/Library/LockCydgets/CydgetCentral.cydget/Index.html"; Cycript = "YES"; + Scrollable = "NO"; }; diff --git a/CydgetSettings.mm b/CydgetSettings.mm new file mode 100644 index 0000000..5d79fd9 --- /dev/null +++ b/CydgetSettings.mm @@ -0,0 +1,356 @@ +/* WinterBoard - Theme Manager for the iPhone + * Copyright (C) 2009 Jay Freeman (saurik) +*/ + +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#import +#import +#import +#import +#import +#import + +extern NSString *PSTableCellKey; +extern "C" UIImage *_UIImageWithName(NSString *); + +static UIImage *checkImage; +static UIImage *uncheckedImage; + +static BOOL settingsChanged; +static NSMutableDictionary *_settings; +static NSString *_plist; + +/* Theme Settings Controller {{{ */ +@interface WBSThemesController: PSViewController { + UITableView *_tableView; + NSMutableArray *_themes; +} + +@property (nonatomic, retain) NSMutableArray *themes; + ++ (void) load; + +- (id) initForContentSize:(CGSize)size; +- (id) view; +- (id) navigationTitle; +- (void) themesChanged; + +- (int) numberOfSectionsInTableView:(UITableView *)tableView; +- (id) tableView:(UITableView *)tableView titleForHeaderInSection:(int)section; +- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(int)section; +- (id) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; +- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; +- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath; +- (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL) tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL) tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; + +@end + +@implementation WBSThemesController + +@synthesize themes = _themes; + ++ (void) load { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + checkImage = [_UIImageWithName(@"UIPreferencesBlueCheck.png") retain]; + uncheckedImage = [[UIImage imageWithContentsOfFile:@"/System/Library/PreferenceBundles/WinterBoardSettings.bundle/SearchResultsCheckmarkClear.png"] retain]; + [pool release]; +} + +- (id) initForContentSize:(CGSize)size { + if ((self = [super initForContentSize:size]) != nil) { + self.themes = [_settings objectForKey:@"Themes"]; + if (!_themes) { + if (NSString *theme = [_settings objectForKey:@"Theme"]) { + self.themes = [NSMutableArray arrayWithObject: + [NSMutableDictionary dictionaryWithObjectsAndKeys: + theme, @"Name", + [NSNumber numberWithBool:YES], @"Active", nil]]; + [_settings removeObjectForKey:@"Theme"]; + } + if (!_themes) + self.themes = [NSMutableArray array]; + [_settings setObject:_themes forKey:@"Themes"]; + } + + NSMutableArray *themesOnDisk([NSMutableArray array]); + + [themesOnDisk + addObjectsFromArray:[[NSFileManager defaultManager] + contentsOfDirectoryAtPath:@"/Library/Themes" error:NULL] + ]; + + [themesOnDisk addObjectsFromArray:[[NSFileManager defaultManager] + contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%@/Library/SummerBoard/Themes", NSHomeDirectory()] + error:NULL + ]]; + + for (int i = 0, count = [themesOnDisk count]; i < count; i++) { + NSString *theme = [themesOnDisk objectAtIndex:i]; + if ([theme hasSuffix:@".theme"]) + [themesOnDisk replaceObjectAtIndex:i withObject:[theme stringByDeletingPathExtension]]; + } + + NSMutableSet *themesSet([NSMutableSet set]); + + for (int i = 0, count = [_themes count]; i < count; i++) { + NSDictionary *theme([_themes objectAtIndex:i]); + NSString *name([theme objectForKey:@"Name"]); + + if (!name || ![themesOnDisk containsObject:name]) { + [_themes removeObjectAtIndex:i]; + i--; + count--; + } else { + [themesSet addObject:name]; + } + } + + for (NSString *theme in themesOnDisk) { + if ([themesSet containsObject:theme]) + continue; + [themesSet addObject:theme]; + + [_themes insertObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: + theme, @"Name", + [NSNumber numberWithBool:NO], @"Active", + nil] atIndex:0]; + } + + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480-64) style:UITableViewStyleGrouped]; + [_tableView setDataSource:self]; + [_tableView setDelegate:self]; + [_tableView setEditing:YES]; + [_tableView setAllowsSelectionDuringEditing:YES]; + [self showLeftButton:@"WinterBoard" withStyle:1 rightButton:nil withStyle:0]; + } + return self; +} + +- (void) dealloc { + [_tableView release]; + [_themes release]; + [super dealloc]; +} + +- (id) navigationTitle { + return @"Themes"; +} + +- (id) view { + return _tableView; +} + +- (void) themesChanged { + settingsChanged = YES; +} + +/* UITableViewDelegate / UITableViewDataSource Methods {{{ */ +- (int) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (id) tableView:(UITableView *)tableView titleForHeaderInSection:(int)section { + return nil; +} + +- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(int)section { + return _themes.count; +} + +- (id) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ThemeCell"]; + if (!cell) { + cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 100, 100) reuseIdentifier:@"ThemeCell"] autorelease]; + //[cell setTableViewStyle:UITableViewCellStyleDefault]; + } + + NSDictionary *theme([_themes objectAtIndex:indexPath.row]); + cell.text = [theme objectForKey:@"Name"]; + cell.hidesAccessoryWhenEditing = NO; + NSNumber *active([theme objectForKey:@"Active"]); + BOOL inactive(active == nil || ![active boolValue]); + [cell setImage:(inactive ? uncheckedImage : checkImage)]; + return cell; +} + +- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; + NSMutableDictionary *theme = [_themes objectAtIndex:indexPath.row]; + NSNumber *active = [theme objectForKey:@"Active"]; + BOOL inactive = active == nil || ![active boolValue]; + [theme setObject:[NSNumber numberWithBool:inactive] forKey:@"Active"]; + [cell setImage:(!inactive ? uncheckedImage : checkImage)]; + [tableView deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:YES]; + [self themesChanged]; +} + +- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { + NSUInteger fromIndex = [fromIndexPath row]; + NSUInteger toIndex = [toIndexPath row]; + if (fromIndex == toIndex) + return; + NSMutableDictionary *theme = [[[_themes objectAtIndex:fromIndex] retain] autorelease]; + [_themes removeObjectAtIndex:fromIndex]; + [_themes insertObject:theme atIndex:toIndex]; + [self themesChanged]; +} + +- (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewCellEditingStyleNone; +} + +- (BOOL) tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath { + return NO; +} + +- (BOOL) tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + return YES; +} +/* }}} */ +@end +/* }}} */ + +@interface WBSettingsController: PSListController { +} + +- (id) initForContentSize:(CGSize)size; +- (void) dealloc; +- (void) suspend; +- (void) navigationBarButtonClicked:(int)buttonIndex; +- (void) viewWillRedisplay; +- (void) pushController:(id)controller; +- (id) specifiers; +- (void) settingsChanged; +- (NSString *) title; +- (void) setPreferenceValue:(id)value specifier:(PSSpecifier *)spec; +- (id) readPreferenceValue:(PSSpecifier *)spec; + +@end + +@implementation WBSettingsController + +- (id) initForContentSize:(CGSize)size { + if ((self = [super initForContentSize:size]) != nil) { + _plist = [[NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.WinterBoard.plist", NSHomeDirectory()] retain]; + _settings = [([NSMutableDictionary dictionaryWithContentsOfFile:_plist] ?: [NSMutableDictionary dictionary]) retain]; + } return self; +} + +- (void) dealloc { + [_settings release]; + [_plist release]; + [super dealloc]; +} + +- (void) suspend { + if (!settingsChanged) + return; + + NSData *data([NSPropertyListSerialization dataFromPropertyList:_settings format:NSPropertyListBinaryFormat_v1_0 errorDescription:NULL]); + if (!data) + return; + if (![data writeToFile:_plist options:NSAtomicWrite error:NULL]) + return; + + unlink("/User/Library/Caches/com.apple.springboard-imagecache-icons"); + unlink("/User/Library/Caches/com.apple.springboard-imagecache-icons.plist"); + unlink("/User/Library/Caches/com.apple.springboard-imagecache-smallicons"); + unlink("/User/Library/Caches/com.apple.springboard-imagecache-smallicons.plist"); + // XXX: recursively delete directory!! + unlink("/User/Library/Caches/SpringBoardIconCache"); + unlink("/User/Library/Caches/SpringBoardIconCache-small"); + system("killall SpringBoard"); +} + +- (void) navigationBarButtonClicked:(int)buttonIndex { + if (!settingsChanged) { + [super navigationBarButtonClicked:buttonIndex]; + return; + } + + if (buttonIndex == 0) + settingsChanged = NO; + + [self suspend]; + [self.rootController popController]; +} + +- (void) viewWillRedisplay { + if (settingsChanged) + [self settingsChanged]; + [super viewWillRedisplay]; +} + +- (void) pushController:(id)controller { + [self hideNavigationBarButtons]; + [super pushController:controller]; +} + +- (id) specifiers { + if (!_specifiers) + _specifiers = [[self loadSpecifiersFromPlistName:@"WinterBoard" target:self] retain]; + return _specifiers; +} + +- (void) settingsChanged { + [self showLeftButton:@"Respring" withStyle:2 rightButton:@"Cancel" withStyle:0]; + settingsChanged = YES; +} + +- (NSString *) title { + return @"WinterBoard"; +} + +- (void) setPreferenceValue:(id)value specifier:(PSSpecifier *)spec { + if ([[spec propertyForKey:@"negate"] boolValue]) + value = [NSNumber numberWithBool:(![value boolValue])]; + [_settings setValue:value forKey:[spec propertyForKey:@"key"]]; + [self settingsChanged]; +} + +- (id) readPreferenceValue:(PSSpecifier *)spec { + NSString *key([spec propertyForKey:@"key"]); + id defaultValue([spec propertyForKey:@"default"]); + id plistValue([_settings objectForKey:key]); + if (!plistValue) + return defaultValue; + if ([[spec propertyForKey:@"negate"] boolValue]) + plistValue = [NSNumber numberWithBool:(![plistValue boolValue])]; + return plistValue; +} + +@end diff --git a/CydgetSettings.plist b/CydgetSettings.plist new file mode 100644 index 0000000..9bfcc18 --- /dev/null +++ b/CydgetSettings.plist @@ -0,0 +1,19 @@ + + + + + entry + + bundle + CydgetSettings + cell + PSLinkCell + isController + + icon + icon.png + label + Cydget + + + diff --git a/Index.html b/Index.html index bfca301..33f98a5 100644 --- a/Index.html +++ b/Index.html @@ -1,7 +1,71 @@ - - - -

testing the stuffs

-

testing the stuffs

+ + +
+

+ +

Lock Cydget Example

+
+ + diff --git a/LockScreen.mm b/LockScreen.mm index 5207b15..76c6cdc 100644 --- a/LockScreen.mm +++ b/LockScreen.mm @@ -237,6 +237,8 @@ static Class $CydgetController(objc_getClass("CydgetController")); UIWebDocumentView *document_; bool cycript_; + bool scrollable_; + float width_; CGSize size_; bool editing_; @@ -481,7 +483,12 @@ static Class $CydgetController(objc_getClass("CydgetController")); [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; NSDictionary *configuration([$CydgetController currentConfiguration]); + cycript_ = [[configuration objectForKey:@"Cycript"] boolValue]; + + scrollable_ = [[configuration objectForKey:@"Scrollable"] boolValue]; + [scroller_ setScrollingEnabled:scrollable_]; + NSString *homepage([configuration objectForKey:@"Homepage"]); [self loadURL:[NSURL URLWithString:homepage]]; } return self; diff --git a/SearchResultsCheckmarkClear.png b/SearchResultsCheckmarkClear.png new file mode 100644 index 0000000000000000000000000000000000000000..4bd94910855ec9d273080824dc3cdf322a7344a5 GIT binary patch literal 73 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa0Z$jl5RHk+2@zopr0HLuBCjbBd literal 0 HcmV?d00001 diff --git a/Tweak.mm b/Tweak.mm index 9ac3ba0..6702a7f 100644 --- a/Tweak.mm +++ b/Tweak.mm @@ -39,6 +39,7 @@ #include #include +#include #import #import @@ -146,9 +147,83 @@ MSInstanceMessageHook1(void, SBAwayController, _finishedUnlockAttemptWithStatus, MSOldCall(status); } +/* Cydget:// Protocol {{{ */ +@interface CydgetURLProtocol : NSURLProtocol { +} + +@end + +@implementation CydgetURLProtocol + ++ (BOOL) canInitWithRequest:(NSURLRequest *)request { + NSURL *url([request URL]); + if (url == nil) + return NO; + NSString *scheme([[url scheme] lowercaseString]); + if (scheme == nil || ![scheme isEqualToString:@"cydget"]) + return NO; + return YES; +} + ++ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request { + return request; +} + +- (void) _returnPNGWithImage:(UIImage *)icon forRequest:(NSURLRequest *)request { + id client([self client]); + if (icon == nil) + [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]]; + else { + NSData *data(UIImagePNGRepresentation(icon)); + + NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil] autorelease]); + [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + [client URLProtocol:self didLoadData:data]; + [client URLProtocolDidFinishLoading:self]; + } +} + +- (void) startLoading { + id client([self client]); + NSURLRequest *request([self request]); + + NSURL *url([request URL]); + NSString *href([url absoluteString]); + + NSString *path([href substringFromIndex:9]); + NSRange slash([path rangeOfString:@"/"]); + + NSString *command; + if (slash.location == NSNotFound) { + command = path; + path = nil; + } else { + command = [path substringToIndex:slash.location]; + path = [path substringFromIndex:(slash.location + 1)]; + } + + if ([command isEqualToString:@"_UIImageWithName"]) { + if (path == nil) + goto fail; + path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + UIImage *icon(_UIImageWithName(path)); + [self _returnPNGWithImage:icon forRequest:request]; + } else fail: { + [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]]; + } +} + +- (void) stopLoading { +} + +@end +/* }}} */ + #define Cydgets_ @"/System/Library/LockCydgets" MSInitialize { _pooled + [NSURLProtocol registerClass:[CydgetURLProtocol class]]; + cydgets_ = [NSMutableArray arrayWithCapacity:4]; for (NSString *folder in [[NSFileManager defaultManager] directoryContentsAtPath:Cydgets_]) diff --git a/control b/control index a8b276b..159e3be 100644 --- a/control +++ b/control @@ -6,7 +6,7 @@ Architecture: iphoneos-arm Version: 0.9.3076-1 Description: framework for managing lock screen plugins Name: Cydget -Depends: mobilesubstrate (>= 0.9.2587-1) +Depends: mobilesubstrate (>= 0.9.2587-1), cycript (>= 0.9.252) Replaces: cydialer (<< 0.9.17) Author: Jay Freeman (saurik) Depiction: http://cydia.saurik.com/info/cydget/ diff --git a/makefile b/makefile index 73efca9..f88b187 100644 --- a/makefile +++ b/makefile @@ -5,7 +5,14 @@ include $(base)/tweak.mk webcore := WebCore-514 jscore := JavaScriptCore-521 -all: WebCycriptLockScreen +all: WebCycriptLockScreen CydgetSettings + +clean:: + rm -f CydgetSettings WebCycriptLockScreen + +CydgetSettings: CydgetSettings.mm makefile + $(target)g++ -dynamiclib -g0 -O2 -Wall -o $@ $(filter %.mm,$^) -framework UIKit -framework CoreFoundation -framework Foundation -lobjc -framework CoreGraphics -framework Preferences -F$(PKG_ROOT)/System/Library/PrivateFrameworks + ldid -S $@ WebCycriptLockScreen: LockScreen.mm makefile $(base)/../mobilesubstrate/substrate.h $(target)g++ -F. -bundle -mthumb -g0 -O2 -Wall -Werror -o $@ $(filter %.mm,$^) -lobjc -I$(base)/../mobilesubstrate $(link) $(flags) -framework CoreGraphics -framework QuartzCore -framework SpringBoardUI -framework WebCore -framework JavaScriptCore -framework GraphicsServices -framework TelephonyUI -I$(jscore) -iquote$(webcore)/{bindings/js,dom,loader,platform{,/animation,/cf,/network{,/cf},/text},/rendering/style} -iquote$(jscore)/{bytecode,debugger,interpreter,jit,parser,runtime} @@ -18,3 +25,9 @@ extra: mkdir -p package/System/Library/SpringBoardPlugins/WebCycriptLockScreen.bundle cp -a Info.plist package/System/Library/SpringBoardPlugins/WebCycriptLockScreen.bundle cp -a WebCycriptLockScreen package/System/Library/SpringBoardPlugins/WebCycriptLockScreen.bundle + mkdir -p package/Library/PreferenceLoader/Preferences + mkdir -p package/System/Library/PreferenceBundles + cp -a CydgetSettings.plist package/Library/PreferenceLoader/Preferences + cp -a CydgetSettings.bundle package/System/Library/PreferenceBundles + cp -a Icon-Small.png package/System/Library/PreferenceBundles/CydgetSettings.bundle/icon.png + cp -a SearchResultsCheckmarkClear.png CydgetSettings package/System/Library/PreferenceBundles/CydgetSettings.bundle -- 2.45.2