X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/c713af59c5ade19907804670a8c98381124aca6d..c9132db418f017e9f72d31b1aeb9ef31bd6e0de8:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index 7a7a6a7f..2b6bd1e0 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -1,5 +1,5 @@ /* Cydia - iPhone UIKit Front-End for Debian APT - * Copyright (C) 2008-2010 Jay Freeman (saurik) + * Copyright (C) 2008-2011 Jay Freeman (saurik) */ /* Modified BSD License {{{ */ @@ -217,14 +217,6 @@ union SplitHash { static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); -void NSLogPoint(const char *fix, const CGPoint &point) { - NSLog(@"%s(%g,%g)", fix, point.x, point.y); -} - -void NSLogRect(const char *fix, const CGRect &rect) { - NSLog(@"%s(%g,%g)+(%g,%g)", fix, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); -} - static _finline NSString *CydiaURL(NSString *path) { char page[25]; page[0] = 'h'; page[1] = 't'; page[2] = 't'; page[3] = 'p'; page[4] = ':'; @@ -309,15 +301,15 @@ static _finline void UpdateExternalStatus(uint64_t newStatus) { @end /* }}} */ -/* Cydia Action Sheet {{{ */ -@interface CYActionSheet : UIAlertView { +/* Cydia Alert View {{{ */ +@interface CYAlertView : UIAlertView { unsigned button_; } - (int) yieldToPopupAlertAnimated:(BOOL)animated; @end -@implementation CYActionSheet +@implementation CYAlertView - (id) initWithTitle:(NSString *)title buttons:(NSArray *)buttons defaultButtonIndex:(int)index { if ((self = [super init])) { @@ -363,32 +355,6 @@ static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSC static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering; -/* Information Dictionaries {{{ */ -@interface NSMutableArray (Cydia) -- (void) addInfoDictionary:(NSDictionary *)info; -@end - -@implementation NSMutableArray (Cydia) - -- (void) addInfoDictionary:(NSDictionary *)info { - [self addObject:info]; -} - -@end - -@interface NSMutableDictionary (Cydia) -- (void) addInfoDictionary:(NSDictionary *)info; -@end - -@implementation NSMutableDictionary (Cydia) - -- (void) addInfoDictionary:(NSDictionary *)info { - [self setObject:info forKey:[info objectForKey:@"CFBundleIdentifier"]]; -} - -@end -/* }}} */ - #define lprintf(args...) fprintf(stderr, args) #define ForRelease 1 @@ -400,8 +366,8 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | #define TrackResize (0 && !ForRelease) #define ManualRefresh (1 && !ForRelease) #define ShowInternals (0 && !ForRelease) -#define IgnoreInstall (0 && !ForRelease) #define AlwaysReload (0 && !ForRelease) +#define TryIndexedCollation (0 && !ForRelease) #if !TraceLogging #undef _trace @@ -1013,6 +979,8 @@ class CYColor { /* Random Global Variables {{{ */ static const int PulseInterval_ = 50000; +static const NSString *UI_; + static int Finish_; static NSArray *Finishes_; @@ -1071,7 +1039,8 @@ static _transient NSMutableDictionary *Sources_; static bool Changed_; static time_t now_; -static bool IsWildcat_; +bool IsWildcat_; +static CGFloat ScreenScale_; /* }}} */ /* Display Helpers {{{ */ @@ -1184,7 +1153,6 @@ bool isSectionVisible(NSString *section) { @protocol CydiaDelegate - (void) retainNetworkActivityIndicator; - (void) releaseNetworkActivityIndicator; -- (void) setPackageController:(CYPackageController *)view; - (void) clearPackage:(Package *)package; - (void) installPackage:(Package *)package; - (void) installPackages:(NSArray *)packages; @@ -1461,7 +1429,7 @@ struct MetaValue : static Cytore::File MetaFile_; // }}} // Cytore Helper Functions {{{ -static PackageValue *PackageFind(const char *name, size_t length) { +static PackageValue *PackageFind(const char *name, size_t length, bool *fail = NULL) { SplitHash nhash = { hashlittle(name, length) }; PackageValue *metadata; @@ -1471,6 +1439,14 @@ static PackageValue *PackageFind(const char *name, size_t length) { *offset = MetaFile_.New(length + 1); metadata = &MetaFile_.Get(*offset); + if (metadata == NULL) { + if (fail != NULL) + *fail = true; + + metadata = new PackageValue(); + memset(metadata, 0, sizeof(*metadata)); + } + memcpy(metadata->name_, name, length + 1); metadata->nhash_ = nhash.u16[1]; } else { @@ -1486,13 +1462,15 @@ static PackageValue *PackageFind(const char *name, size_t length) { } static void PackageImport(const void *key, const void *value, void *context) { + bool &fail(*reinterpret_cast(context)); + char buffer[1024]; if (!CFStringGetCString((CFStringRef) key, buffer, sizeof(buffer), kCFStringEncodingUTF8)) { NSLog(@"failed to import package %@", key); return; } - PackageValue *metadata(PackageFind(buffer, strlen(buffer))); + PackageValue *metadata(PackageFind(buffer, strlen(buffer), &fail)); NSDictionary *package((NSDictionary *) value); if (NSNumber *subscribed = [package objectForKey:@"IsSubscribed"]) @@ -2735,6 +2713,8 @@ struct PackageNameOrdering : if (range.location != NSNotFound) return YES; + [self parse]; + range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_]; if (range.location != NSNotFound) return YES; @@ -3375,7 +3355,7 @@ static NSString *Warning_; NSString *title(UCLocalize("DATABASE")); _trace(); - if (!cache_.Open(progress_, true)) { pop: + while (!cache_.Open(progress_, true)) { pop: std::string error; bool warning(!_error->PopMessage(error)); lprintf("cache_.Open():[%s]\n", error.c_str()); @@ -3385,15 +3365,17 @@ static NSString *Warning_; else if (error == "The package lists or status file could not be parsed or opened.") [delegate_ repairWithSelector:@selector(update)]; // else if (error == "Could not open lock file /var/lib/dpkg/lock - open (13 Permission denied)") - // else if (error == "Could not get lock /var/lib/dpkg/lock - open (35 Resource temporarily unavailable)") + else if (error == "Could not get lock /var/lib/dpkg/lock - open (35 Resource temporarily unavailable)") + [delegate_ _setProgressError:[NSString stringWithUTF8String:error.c_str()] withTitle:[NSString stringWithFormat:Colon_, Error_, title]]; // else if (error == "The list of sources could not be read.") - else + else { [delegate_ _setProgressError:[NSString stringWithUTF8String:error.c_str()] withTitle:[NSString stringWithFormat:Colon_, warning ? Warning_ : Error_, title]]; + return; + } if (warning) goto pop; _error->Discard(); - return; } _trace(); @@ -3951,7 +3933,7 @@ static NSString *Warning_; id values[count]; for (unsigned i(0); i != count; ++i) values[i] = [arguments objectAtIndex:i]; - return [[[NSString alloc] initWithFormat:format arguments:*(reinterpret_cast(&values))] autorelease]; + return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast(values)] autorelease]; } - (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table { @@ -4030,7 +4012,11 @@ static NSString *Warning_; @end /* }}} */ /* Emulated Loading Controller {{{ */ -@interface CYEmulatedLoadingController : UIViewController { +@interface CYEmulatedLoadingController : CYViewController < + ProgressDelegate, + ConfigurationDelegate +> { + _transient Database *database_; CYLoadingIndicator *indicator_; UITabBar *tabbar_; UINavigationBar *navbar_; @@ -4039,31 +4025,74 @@ static NSString *Warning_; @implementation CYEmulatedLoadingController -- (CYEmulatedLoadingController *) init { +- (void) dealloc { + [self releaseSubviews]; + [database_ setDelegate:nil]; + + [super dealloc]; +} + +- (void) setProgressError:(NSString *)error withTitle:(NSString *)title { + CYAlertView *sheet([[[CYAlertView alloc] + initWithTitle:title + buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil] + defaultButtonIndex:0 + ] autorelease]); + + [sheet setMessage:error]; + [sheet yieldToPopupAlertAnimated:YES]; + [sheet dismiss]; +} + +- (void) setProgressTitle:(NSString *)title { } +- (void) setProgressPercent:(float)percent { } +- (void) startProgress { } +- (void) addProgressOutput:(NSString *)output { } +- (bool) isCancelling:(size_t)received { return NO; } +- (void) setConfigurationData:(NSString *)data { } + +- (void) repairWithSelector:(SEL)selector { + [[indicator_ label] performSelectorOnMainThread:@selector(setText:) withObject:[NSString stringWithFormat:Elision_, UCLocalize("REPAIRING"), nil] waitUntilDone:YES]; + [database_ performSelector:selector]; + sleep(10); + [[indicator_ label] performSelectorOnMainThread:@selector(setText:) withObject:[NSString stringWithFormat:Elision_, UCLocalize("LOADING"), nil] waitUntilDone:YES]; +} + +- (id) initWithDatabase:(Database *)database { if ((self = [super init])) { - [[self view] setBackgroundColor:[UIColor pinStripeColor]]; - - indicator_ = [[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]]; - [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:indicator_]; - [indicator_ release]; - - tabbar_ = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)]; - [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)]; - [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:tabbar_]; - [tabbar_ release]; - - navbar_ = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)]; - [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)]; - [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:navbar_]; - [navbar_ release]; + database_ = database; + [database_ setDelegate:self]; } return self; } -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { - return (IsWildcat_ || orientation == UIInterfaceOrientationPortrait); +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + [[self view] setBackgroundColor:[UIColor pinStripeColor]]; + + indicator_ = [[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]]; + [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [[self view] addSubview:indicator_]; + + tabbar_ = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)]; + [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)]; + [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth]; + [[self view] addSubview:tabbar_]; + + navbar_ = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)]; + [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)]; + [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth]; + [[self view] addSubview:navbar_]; +} + +- (void) releaseSubviews { + [indicator_ release]; + indicator_ = nil; + + [tabbar_ release]; + tabbar_ = nil; + + [navbar_ release]; + navbar_ = nil; } @end @@ -4083,6 +4112,10 @@ static NSString *Warning_; [super dealloc]; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[[webview_ request] URL] absoluteString]]]; +} + - (void) setHeaders:(NSDictionary *)headers forHost:(NSString *)host { } @@ -4091,18 +4124,16 @@ static NSString *Warning_; WebDataSource *source([frame dataSource]); NSURLResponse *response([source response]); + NSURL *url([response URL]); NSString *scheme([url scheme]); - - NSHTTPURLResponse *http; - if (scheme != nil && ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"])) - http = (NSHTTPURLResponse *) response; - else - http = nil; - - NSDictionary *headers([http allHeaderFields]); NSString *host([url host]); - [self setHeaders:headers forHost:host]; + + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *http((NSHTTPURLResponse *) response); + NSDictionary *headers([http allHeaderFields]); + [self setHeaders:headers forHost:host]; + } if ( [host isEqualToString:@"cydia.saurik.com"] || @@ -4251,8 +4282,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ((self = [super init]) != nil) { database_ = database; - [[self navigationItem] setTitle:UCLocalize("CONFIRM")]; - NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16]; NSMutableArray *reinstalling = [NSMutableArray arrayWithCapacity:16]; NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16]; @@ -4299,7 +4328,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:UCLocalize("REMOVING_ESSENTIALS_EX") delegate:self cancelButtonTitle:[NSString stringWithFormat:parenthetical, UCLocalize("CANCEL_OPERATION"), UCLocalize("SAFE")] - otherButtonTitles:[NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")], nil + otherButtonTitles: + [NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")], + nil ]; [essential_ setContext:@"remove"]; @@ -4332,11 +4363,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { SizeString([database_ fetcher].PartialPresent()), nil]; - [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"confirm" ofType:@"html"]]]; + [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/confirm/", UI_]]]; [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithTitle:UCLocalize("CANCEL") - // OLD: [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("CANCEL"), UCLocalize("QUEUE")] style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonClicked) @@ -4345,11 +4375,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) applyRightButton { -#if !AlwaysReload && !IgnoreInstall +#if !AlwaysReload if (issues_ == nil && ![self isLoading]) [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithTitle:UCLocalize("CONFIRM") - style:UIBarButtonItemStylePlain + style:UIBarButtonItemStyleDone target:self action:@selector(confirmButtonClicked) ] autorelease]]; @@ -4367,9 +4397,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #if !AlwaysReload - (void) confirmButtonClicked { -#if IgnoreInstall - return; -#endif if (essential_ != nil) [essential_ show]; else { @@ -4485,7 +4512,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { //[status_ setFont:font]; output_ = [[UITextView alloc] init]; - [output_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; //[output_ setTextFont:@"Courier New"]; [output_ setFont:[[output_ font] fontWithSize:12]]; @@ -4531,7 +4557,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { 10, 20, bounds.size.width - 20, - bounds.size.height - 62 + bounds.size.height - 96 )]; [close_ setFrame:CGRectMake( (bounds.size.width - closewidth) / 2, @@ -4741,7 +4767,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) setProgressError:(NSString *)error withTitle:(NSString *)title { - CYActionSheet *sheet([[[CYActionSheet alloc] + CYAlertView *sheet([[[CYAlertView alloc] initWithTitle:title buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil] defaultButtonIndex:0 @@ -4799,8 +4825,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile] delegate:self cancelButtonTitle:UCLocalize("KEEP_OLD_COPY") - otherButtonTitles:UCLocalize("ACCEPT_NEW_COPY"), - // XXX: UCLocalize("SEE_WHAT_CHANGED"), + otherButtonTitles: + UCLocalize("ACCEPT_NEW_COPY"), + // XXX: UCLocalize("SEE_WHAT_CHANGED"), nil ] autorelease]; @@ -4985,16 +5012,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } return self; } -- (void) _setBackgroundColor { - UIColor *color; - if (NSString *mode = [package_ mode]) { - bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]); - color = remove ? RemovingColor_ : InstallingColor_; - } else - color = [UIColor whiteColor]; - - [content_ setBackgroundColor:color]; - [self setNeedsDisplay]; +- (NSString *) accessibilityLabel { + return [NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), name_, description_]; } - (void) setPackage:(Package *)package { @@ -5043,11 +5062,36 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ((badge_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Purposes/%@.png", App_, purpose]]) != nil) badge_ = [badge_ retain]; - if ([package installed] != nil) - if ((placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/installed.png", App_]]) != nil) + UIColor *color; + NSString *placard; + + if (NSString *mode = [package_ mode]) { + if ([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]) { + color = RemovingColor_; + //placard = @"removing"; + } else { + color = InstallingColor_; + //placard = @"installing"; + } + + // XXX: the removing/installing placards are not @2x + placard = nil; + } else { + color = [UIColor whiteColor]; + + if ([package installed] != nil) + placard = @"installed"; + else + placard = nil; + } + + [content_ setBackgroundColor:color]; + + if (placard != nil) + if ((placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]]) != nil) placard_ = [placard_ retain]; - [self _setBackgroundColor]; + [self setNeedsDisplay]; [content_ setNeedsDisplay]; } @@ -5225,6 +5269,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [switch_ setFrame:CGRectMake(frame.size.width - 102, 9, rect.size.width, rect.size.height)]; } +- (NSString *) accessibilityLabel { + return name_; +} + - (void) drawContentRect:(CGRect)rect { bool highlighted(highlighted_ && !editing_); @@ -5271,12 +5319,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation FileTable - (void) dealloc { - if (package_ != nil) - [package_ release]; - if (name_ != nil) - [name_ release]; + [self releaseSubviews]; + + [package_ release]; + [name_ release]; [files_ release]; - [list_ release]; + [super dealloc]; } @@ -5302,21 +5350,35 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return cell; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/files", [package_ id]]]; +} + +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + + list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [list_ setRowHeight:24.0f]; + [list_ setDataSource:self]; + [list_ setDelegate:self]; + [[self view] addSubview:list_]; +} + +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")]; +} + +- (void) releaseSubviews { + [list_ release]; + list_ = nil; +} + - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")]; - files_ = [[NSMutableArray arrayWithCapacity:32] retain]; - - list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:24.0f]; - [[self view] addSubview:list_]; - - [list_ setDataSource:self]; - [list_ setDelegate:self]; } return self; } @@ -5366,6 +5428,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) reloadData { + [super reloadData]; + [self setPackage:[database_ packageWithName:name_]]; } @@ -5383,8 +5447,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIBarButtonItem *button_; } -- (id) initWithDatabase:(Database *)database; -- (void) setPackage:(Package *)package; +- (id) initWithDatabase:(Database *)database forPackage:(NSString *)name; @end @@ -5404,10 +5467,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super dealloc]; } -- (void) release { - if ([self retainCount] == 1) - [delegate_ setPackageController:self]; - [super release]; +- (NSURL *) navigationURL { + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", name_]]; } /* XXX: this is not safe at all... localization of /fail/ */ @@ -5438,11 +5499,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } -- (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { - [super webView:view didClearWindowObject:window forFrame:frame]; - [window setValue:package_ forKey:@"package"]; -} - - (bool) _allowJavaScriptPanel { return commercial_; } @@ -5503,33 +5559,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } #endif -- (id) initWithDatabase:(Database *)database { +- (id) initWithDatabase:(Database *)database forPackage:(NSString *)name { if ((self = [super init]) != nil) { database_ = database; buttons_ = [[NSMutableArray alloc] initWithCapacity:4]; - [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"package" ofType:@"html"]]]; + name_ = [[NSString alloc] initWithString:name]; } return self; } -- (void) setPackage:(Package *)package { - if (package_ != nil) { - [package_ autorelease]; - package_ = nil; - } +- (void) reloadData { + [super reloadData]; - if (name_ != nil) { - [name_ release]; - name_ = nil; - } + if (package_ != nil) + [package_ autorelease]; + package_ = [database_ packageWithName:name_]; [buttons_ removeAllObjects]; - if (package != nil) { - [package parse]; + if (package_ != nil) { + [package_ parse]; - package_ = [package retain]; - name_ = [[package id] retain]; - commercial_ = [package isCommercial]; + package_ = [package_ retain]; + commercial_ = [package_ isCommercial]; if ([package_ mode] != nil) [buttons_ addObject:UCLocalize("CLEAR")]; @@ -5561,22 +5612,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { action:@selector(customButtonClicked) ]; - [self reloadURL]; + [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/package/#!/%@", UI_, name_]]]; } - (bool) isLoading { return commercial_ ? [super isLoading] : false; } -- (void) reloadData { - [self setPackage:[database_ packageWithName:name_]]; -} - @end /* }}} */ -/* Package Table {{{ */ -@interface PackageTable : UIView < +/* Package List Controller {{{ */ +@interface PackageListController : CYViewController < UITableViewDataSource, UITableViewDelegate > { @@ -5587,29 +5634,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UITableView *list_; NSMutableArray *index_; NSMutableDictionary *indices_; - // XXX: this target_ seems to be delegate_. :( - _transient id target_; - SEL action_; - // XXX: why do we even have this delegate_? - _transient id delegate_; + NSString *title_; } -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action; - +- (id) initWithDatabase:(Database *)database title:(NSString *)title; - (void) setDelegate:(id)delegate; - -- (void) reloadData; - (void) resetCursor; -- (UITableView *) list; - -- (void) setShouldHideHeaderInShortLists:(BOOL)hide; - -- (void) deselectWithAnimation:(BOOL)animated; - @end -@implementation PackageTable +@implementation PackageListController - (void) dealloc { [packages_ release]; @@ -5617,13 +5651,97 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ release]; [index_ release]; [indices_ release]; + [title_ release]; [super dealloc]; } +- (void) deselectWithAnimation:(BOOL)animated { + [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated]; +} + +- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve { + CGRect base = [[self view] bounds]; + base.size.height -= bounds.size.height; + base.origin = [list_ frame].origin; + + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationCurve:curve]; + [UIView setAnimationDuration:duration]; + [list_ setFrame:base]; + [UIView commitAnimations]; +} + +- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration { + [self resizeForKeyboardBounds:bounds duration:duration curve:UIViewAnimationCurveLinear]; +} + +- (void) resizeForKeyboardBounds:(CGRect)bounds { + [self resizeForKeyboardBounds:bounds duration:0]; +} + +- (void) keyboardWillShow:(NSNotification *)notification { + CGRect bounds; + CGPoint center; + NSTimeInterval duration; + UIViewAnimationCurve curve; + [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds]; + [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:¢er]; + [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; + [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + + CGRect kbframe = CGRectMake(round(center.x - bounds.size.width / 2.0), round(center.y - bounds.size.height / 2.0), bounds.size.width, bounds.size.height); + UIViewController *base = self; + while ([base parentViewController] != nil) + base = [base parentViewController]; + CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]]; + CGRect intersection = CGRectIntersection(viewframe, kbframe); + + [self resizeForKeyboardBounds:intersection duration:duration curve:curve]; +} + +- (void) keyboardWillHide:(NSNotification *)notification { + NSTimeInterval duration; + UIViewAnimationCurve curve; + [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; + [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + + [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve]; +} + +- (void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self resizeForKeyboardBounds:CGRectZero]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; +} + +- (void) viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self resizeForKeyboardBounds:CGRectZero]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; +} + +- (void) viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self deselectWithAnimation:animated]; +} + +- (void) didSelectPackage:(Package *)package { + CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id]] autorelease]); + [view setDelegate:delegate_]; + [[self navigationController] pushViewController:view animated:YES]; +} + +#if TryIndexedCollation + (BOOL) hasIndexedCollation { return NO; // XXX: objc_getClass("UILocalizedIndexedCollation") != nil; } +#endif - (NSInteger) numberOfSectionsInTableView:(UITableView *)list { NSInteger count([sections_ count]); @@ -5661,15 +5779,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return cell; } -- (void) deselectWithAnimation:(BOOL)animated { - [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated]; -} - -- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path { +- (void) tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)path { Package *package([self packageAtIndexPath:path]); package = [database_ packageWithName:[package id]]; - [target_ performSelector:action_ withObject:package]; - return path; + [self didSelectPackage:package]; } - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView { @@ -5678,32 +5791,37 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { +#if TryIndexedCollation if ([[self class] hasIndexedCollation]) { return [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionForSectionIndexTitleAtIndex:index]; } +#endif return index; } -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action { - if ((self = [super initWithFrame:frame]) != nil) { +- (id) initWithDatabase:(Database *)database title:(NSString *)title { + if ((self = [super init]) != nil) { database_ = database; + title_ = [title copy]; + [[self navigationItem] setTitle:title_]; - target_ = target; - action_ = action; +#if TryIndexedCollation + if ([[self class] hasIndexedCollation]) + index_ = [[[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles] retain] + else +#endif + index_ = [[NSMutableArray alloc] initWithCapacity:32]; - index_ = [[self class] hasIndexedCollation] - ? [[[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles] retain] - : [[NSMutableArray alloc] initWithCapacity:32]; indices_ = [[NSMutableDictionary alloc] initWithCapacity:32]; packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; - list_ = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStylePlain]; + list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain]; [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [list_ setRowHeight:73]; - [self addSubview:list_]; + [[self view] addSubview:list_]; [list_ setDataSource:self]; [list_ setDelegate:self]; @@ -5719,6 +5837,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) reloadData { + [super reloadData]; + era_ = [database_ era]; NSArray *packages = [database_ packages]; @@ -5735,6 +5855,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Section *section = nil; +#if TryIndexedCollation if ([[self class] hasIndexedCollation]) { id collation = [objc_getClass("UILocalizedIndexedCollation") currentCollation]; NSArray *titles = [collation sectionIndexTitles]; @@ -5765,7 +5886,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [section addToCount]; } _end - } else { + } else +#endif + { [index_ removeAllObjects]; _profile(PackageTable$reloadData$Section) @@ -5805,18 +5928,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:NO]; } -- (UITableView *) list { - return list_; -} - -- (void) setShouldHideHeaderInShortLists:(BOOL)hide { - //XXX:[list_ setShouldHideHeaderInShortLists:hide]; -} - @end /* }}} */ -/* Filtered Package Table {{{ */ -@interface FilteredPackageTable : PackageTable { +/* Filtered Package List Controller {{{ */ +@interface FilteredPackageListController : PackageListController { SEL filter_; IMP imp_; id object_; @@ -5825,11 +5940,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) setObject:(id)object; - (void) setObject:(id)object forFilter:(SEL)filter; -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action filter:(SEL)filter with:(id)object; +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object; @end -@implementation FilteredPackageTable +@implementation FilteredPackageListController - (void) dealloc { if (object_ != nil) @@ -5867,92 +5982,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _end } -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action filter:(SEL)filter with:(id)object { - if ((self = [super initWithFrame:frame database:database target:target action:action]) != nil) { +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { + if ((self = [super initWithDatabase:database title:title]) != nil) { [self setFilter:filter]; - object_ = [object retain]; + [self setObject:object]; [self reloadData]; } return self; } @end /* }}} */ -/* Filtered Package Controller {{{ */ -@interface FilteredPackageController : CYViewController { - _transient Database *database_; - FilteredPackageTable *packages_; - NSString *title_; -} - -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object; +/* Home Controller {{{ */ +@interface HomeController : CYBrowserController { +} @end -@implementation FilteredPackageController - -- (void) dealloc { - [packages_ release]; - [title_ release]; +@implementation HomeController - [super dealloc]; ++ (BOOL) shouldHideNavigationBar { + return NO; } -- (void) viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - [packages_ deselectWithAnimation:animated]; -} - -- (void) didSelectPackage:(Package *)package { - CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]); - [view setPackage:package]; - [view setDelegate:delegate_]; - [[self navigationController] pushViewController:view animated:YES]; -} - -- (NSString *) title { return title_; } - -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { - if ((self = [super init]) != nil) { - database_ = database; - title_ = [title copy]; - [[self navigationItem] setTitle:title_]; - - packages_ = [[FilteredPackageTable alloc] - initWithFrame:[[self view] bounds] - database:database - target:self - action:@selector(didSelectPackage:) - filter:filter - with:object - ]; - - [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:packages_]; - } return self; -} - -- (void) reloadData { - [packages_ reloadData]; -} - -- (void) setDelegate:(id)delegate { - [super setDelegate:delegate]; - [packages_ setDelegate:delegate]; -} - -@end - -/* }}} */ - -/* Home Controller {{{ */ -@interface HomeController : CYBrowserController { -} -@end - -@implementation HomeController - -+ (BOOL)shouldHideNavigationBar { - return NO; +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://home"]; } - (void) _setMoreHeaders:(NSMutableURLRequest *)request { @@ -5974,7 +6027,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [alert setCancelButtonIndex:0]; [alert setMessage: - @"Copyright (C) 2008-2010\n" + @"Copyright (C) 2008-2011\n" "Jay Freeman (saurik)\n" "saurik@saurik.com\n" "http://www.saurik.com/" @@ -5983,13 +6036,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [alert show]; } -- (void) viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - if ([[self class] shouldHideNavigationBar]) - [[self navigationController] setNavigationBarHidden:YES animated:animated]; -} - - (void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; @@ -5997,17 +6043,23 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [[self navigationController] setNavigationBarHidden:NO animated:animated]; } -- (id) init { - if ((self = [super init]) != nil) { - [self loadURL:[NSURL URLWithString:CydiaURL(@"")]]; +- (void) viewWillAppear:(BOOL)animated { + if (![self hasLoaded]) + [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/home/", UI_]]]; - [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] - initWithTitle:UCLocalize("ABOUT") - style:UIBarButtonItemStylePlain - target:self - action:@selector(aboutButtonClicked) - ] autorelease]]; - } return self; + [super viewWillAppear:animated]; + + if ([[self class] shouldHideNavigationBar]) + [[self navigationController] setNavigationBarHidden:YES animated:animated]; +} + +- (void) viewDidLoad { + [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] + initWithTitle:UCLocalize("ABOUT") + style:UIBarButtonItemStylePlain + target:self + action:@selector(aboutButtonClicked) + ] autorelease]]; } @end @@ -6021,21 +6073,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation ManageController -- (id) init { - if ((self = [super init]) != nil) { - [[self navigationItem] setTitle:UCLocalize("MANAGE")]; +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://manage"]; +} - [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]]; +- (void) viewWillAppear:(BOOL)animated { + if (![self hasLoaded]) + [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/manage/", UI_]]]; - [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] - initWithTitle:UCLocalize("SETTINGS") - style:UIBarButtonItemStylePlain - target:self - action:@selector(settingsButtonClicked) - ] autorelease]]; + [super viewWillAppear:animated]; +} - [self queueStatusDidChange]; - } return self; +- (void) viewDidLoad { + [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] + initWithTitle:UCLocalize("SETTINGS") + style:UIBarButtonItemStylePlain + target:self + action:@selector(settingsButtonClicked) + ] autorelease]]; + + [self queueStatusDidChange]; } - (void) settingsButtonClicked { @@ -6048,11 +6105,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) applyLoadingTitle { - // No "Loading" title. + // Disable "Loading" title. } - (void) applyRightButton { - // No right button. + // Disable right button. } #endif @@ -6072,6 +6129,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (bool) isLoading { + // Never show as loading. return false; } @@ -6198,6 +6256,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* Cydia Tab Bar Controller {{{ */ @interface CYTabBarController : UITabBarController < + UITabBarControllerDelegate, ProgressDelegate > { _transient Database *database_; @@ -6209,8 +6268,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _transient NSObject *updatedelegate_; id root_; + UIViewController *remembered_; + _transient UIViewController *transient_; } +- (NSArray *) navigationURLCollection; - (void) dropBar:(BOOL)animated; - (void) beginUpdate; - (void) raiseBar:(BOOL)animated; @@ -6220,19 +6282,68 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation CYTabBarController -- (void) reloadData { - size_t count([[self viewControllers] count]); - for (size_t i(0); i != count; ++i) { - CYNavigationController *page([[self viewControllers] objectAtIndex:(count - i - 1)]); - [page reloadData]; +- (void) setUnselectedViewController:(UIViewController *)transient { + NSMutableArray *controllers = [[self viewControllers] mutableCopy]; + if (transient != nil) { + if (transient_ == nil) + remembered_ = [[controllers objectAtIndex:0] retain]; + transient_ = transient; + [transient_ setTabBarItem:[remembered_ tabBarItem]]; + [controllers replaceObjectAtIndex:0 withObject:transient_]; + [self setSelectedIndex:0]; + [self setViewControllers:controllers]; + [self concealTabBarSelection]; + } else if (remembered_ != nil) { + [remembered_ setTabBarItem:[transient_ tabBarItem]]; + transient_ = transient; + [controllers replaceObjectAtIndex:0 withObject:remembered_]; + [remembered_ release]; + remembered_ = nil; + [self setViewControllers:controllers]; + [self revealTabBarSelection]; } +} + +- (UIViewController *) unselectedViewController { + return transient_; +} - [(CYNavigationController *) [self transientViewController] reloadData]; +- (void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { + if ([self unselectedViewController]) + [self setUnselectedViewController:nil]; +} + +- (NSArray *) navigationURLCollection { + NSMutableArray *items([NSMutableArray array]); + + // XXX: Should this deal with transient view controllers? + for (id navigation in [self viewControllers]) { + NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)]; + if (stack != nil) + [items addObject:stack]; + } + + return items; +} + +- (void) reloadData { + for (CYViewController *controller in [self viewControllers]) + [controller reloadData]; + + [(CYNavigationController *)[self unselectedViewController] reloadData]; +} + +- (void) dealloc { + [refreshbar_ release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; } - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; + [self setDelegate:self]; [[self view] setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil]; @@ -6241,10 +6352,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } return self; } -- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { - return IsWildcat_ || orientation == UIInterfaceOrientationPortrait; -} - - (void) setUpdate:(NSDate *)date { [self beginUpdate]; } @@ -6378,7 +6485,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CGRect barframe([refreshbar_ frame]); - if (false) // XXX: _UIApplicationLinkedOnOrAfter(4) + if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4) barframe.origin.y = [self statusBarHeight]; else barframe.origin.y = 0; @@ -6458,12 +6565,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } -- (void) dealloc { - [refreshbar_ release]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; -} - @end /* }}} */ /* Cydia Navigation Controller {{{ */ @@ -6472,6 +6573,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _transient id delegate_; } +- (NSArray *) navigationURLCollection; - (id) initWithDatabase:(Database *)database; - (void) reloadData; @@ -6480,26 +6582,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation CYNavigationController -- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { - // Inherit autorotation settings for modal parents. - if ([self parentViewController] && [[self parentViewController] modalViewController] == self) { - return [[self parentViewController] shouldAutorotateToInterfaceOrientation:orientation]; - } else if ([self parentViewController]) { - return [[self parentViewController] shouldAutorotateToInterfaceOrientation:orientation]; - } else { - return [super shouldAutorotateToInterfaceOrientation:orientation]; +- (NSArray *) navigationURLCollection { + NSMutableArray *stack([NSMutableArray array]); + + for (CYViewController *controller in [self viewControllers]) { + NSString *url = [[controller navigationURL] absoluteString]; + if (url != nil) + [stack addObject:url]; } -} -- (void) dealloc { - [super dealloc]; + return stack; } - (void) reloadData { - size_t count([[self viewControllers] count]); - for (size_t i(0); i != count; ++i) { - CYViewController *page([[self viewControllers] objectAtIndex:(count - i - 1)]); - [page reloadData]; + for (CYViewController *page in [self viewControllers]) { + // Only reload controllers that have already loaded. + // This prevents a page from accidentally loading too + // early if it hasn't been shown on the screen yet. + if ([page hasLoaded]) + [page reloadData]; } } @@ -6618,7 +6719,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Section Controller {{{ */ -@interface SectionController : FilteredPackageController { +@interface SectionController : FilteredPackageListController { + NSString *section_; } - (id) initWithDatabase:(Database *)database section:(NSString *)section; @@ -6627,34 +6729,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SectionController -- (void) dealloc { - [super dealloc]; +- (NSURL *) navigationURL { + NSString *name = section_; + if (name == nil) + name = @"all"; + + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sections/%@", name]]; } - (id) initWithDatabase:(Database *)database section:(NSString *)name { NSString *title; - - if (name == nil) { + if (name == nil) title = UCLocalize("ALL_PACKAGES"); - } else if (![name isEqual:@""]) { + else if (![name isEqual:@""]) title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"]; - } else { + else title = UCLocalize("NO_SECTION"); - } if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:) with:name]) != nil) { + section_ = name; } return self; } -- (void) reloadData { - [packages_ reloadData]; -} - -- (void) setDelegate:(id)delegate { - [super setDelegate:delegate]; - [packages_ setDelegate:delegate]; -} - @end /* }}} */ /* Sections Controller {{{ */ @@ -6666,14 +6762,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSMutableArray *sections_; NSMutableArray *filtered_; UITableView *list_; - UIView *accessory_; BOOL editing_; } - (id) initWithDatabase:(Database *)database; -- (void) reloadData; -- (void) resetView; - - (void) editButtonClicked; @end @@ -6681,25 +6773,41 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SectionsController - (void) dealloc { - [list_ setDataSource:nil]; - [list_ setDelegate:nil]; - + [self releaseSubviews]; [sections_ release]; [filtered_ release]; - [list_ release]; - [accessory_ release]; + [super dealloc]; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://sections"]; +} + +- (void) updateNavigationItem { + [[self navigationItem] setTitle:editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS")]; + if ([sections_ count] == 0) { + [[self navigationItem] setRightBarButtonItem:nil]; + } else { + [[self navigationItem] setRightBarButtonItem:[[UIBarButtonItem alloc] + initWithBarButtonSystemItem:(editing_ ? UIBarButtonSystemItemDone : UIBarButtonSystemItemEdit) + target:self + action:@selector(editButtonClicked) + ] animated:([[self navigationItem] rightBarButtonItem] != nil)]; + } +} + +- (BOOL) isEditing { + return editing_; +} + - (void) setEditing:(BOOL)editing { if ((editing_ = editing)) [list_ reloadData]; else [delegate_ updateData]; - [[self navigationItem] setTitle:editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS")]; - [[[self navigationItem] rightBarButtonItem] setTitle:[sections_ count] == 0 ? nil : editing_ ? UCLocalize("DONE") : UCLocalize("EDIT")]; - [[[self navigationItem] rightBarButtonItem] setStyle:editing_ ? UIBarButtonItemStyleDone : UIBarButtonItemStylePlain]; + [self updateNavigationItem]; } - (void) viewDidAppear:(BOOL)animated { @@ -6728,7 +6836,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *reuseIdentifier = @"SectionCell"; - SectionCell *cell = (SectionCell *) [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; + SectionCell *cell = (SectionCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; if (cell == nil) cell = [[[SectionCell alloc] initWithFrame:CGRectZero reuseIdentifier:reuseIdentifier] autorelease]; @@ -6752,28 +6860,38 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [[self navigationController] pushViewController:controller animated:YES]; } +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + + list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [list_ setRowHeight:45.0f]; + [list_ setDataSource:self]; + [list_ setDelegate:self]; + [[self view] addSubview:list_]; +} + +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("SECTIONS")]; +} + +- (void) releaseSubviews { + [list_ release]; + list_ = nil; +} + - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - [[self navigationItem] setTitle:UCLocalize("SECTIONS")]; - sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; filtered_ = [[NSMutableArray arrayWithCapacity:16] retain]; - - list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:45.0f]; - [[self view] addSubview:list_]; - - [list_ setDataSource:self]; - [list_ setDelegate:self]; - - [self reloadData]; } return self; } - (void) reloadData { + [super reloadData]; + NSArray *packages = [database_ packages]; [sections_ removeAllObjects]; @@ -6792,7 +6910,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { section = [sections objectForKey:key]; if (section == nil) { _profile(SectionsView$reloadData$Section$Allocate) - section = [[[Section alloc] initWithName:name localize:YES] autorelease]; + section = [[[Section alloc] initWithName:key localize:YES] autorelease]; [sections setObject:section forKey:key]; _end } @@ -6823,30 +6941,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [filtered_ addObject:section]; } - [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] - initWithTitle:([sections_ count] == 0 ? nil : UCLocalize("EDIT")) - style:UIBarButtonItemStylePlain - target:self - action:@selector(editButtonClicked) - ] autorelease] animated:([[self navigationItem] rightBarButtonItem] != nil)]; - + [self updateNavigationItem]; [list_ reloadData]; _trace(); } -- (void) resetView { - if (editing_) - [self editButtonClicked]; -} - - (void)editButtonClicked { [self setEditing:!editing_]; } -- (UIView *) accessoryView { - return accessory_; -} - @end /* }}} */ @@ -6864,26 +6967,33 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { BOOL hasSentFirstLoad_; } -- (id) initWithDatabase:(Database *)database delegate:(id)delegate; -- (void) reloadData; +- (id) initWithDatabase:(Database *)database; @end @implementation ChangesController - (void) dealloc { - [list_ setDelegate:nil]; - [list_ setDataSource:nil]; - + [self releaseSubviews]; CFRelease(packages_); - [sections_ release]; - [list_ release]; + [super dealloc]; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://changes"]; +} + +- (void) viewWillAppear:(BOOL)animated { + // Loads after it appears, so don't load beforehand. + loaded_ = YES; + [super viewWillAppear:animated]; +} + - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; + if (!hasSentFirstLoad_) { hasSentFirstLoad_ = YES; [self performSelector:@selector(reloadData) withObject:nil afterDelay:0.0]; @@ -6936,9 +7046,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path { Package *package([self packageAtIndexPath:path]); - CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]); + CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id]] autorelease]); [view setDelegate:delegate_]; - [view setPackage:package]; [[self navigationController] pushViewController:view animated:YES]; return path; } @@ -6952,26 +7061,32 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [delegate_ distUpgrade]; } -- (NSString *) title { return UCLocalize("CHANGES"); } +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; -- (id) initWithDatabase:(Database *)database delegate:(id)delegate { + list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [list_ setRowHeight:73]; + [list_ setDataSource:self]; + [list_ setDelegate:self]; + [[self view] addSubview:list_]; +} + +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("CHANGES")]; +} + +- (void) releaseSubviews { + [list_ release]; + list_ = nil; +} + +- (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - [[self navigationItem] setTitle:UCLocalize("CHANGES")]; packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); - sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; - - list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:73]; - [[self view] addSubview:list_]; - - [list_ setDataSource:self]; - [list_ setDelegate:self]; - - delegate_ = delegate; } return self; } @@ -7093,10 +7208,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ /* Search Controller {{{ */ -@interface SearchController : FilteredPackageController < +@interface SearchController : FilteredPackageListController < UISearchBarDelegate > { UISearchBar *search_; + BOOL searchloaded_; } - (id) initWithDatabase:(Database *)database; @@ -7112,29 +7228,41 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super dealloc]; } +- (NSURL *) navigationURL { + if ([search_ text] == nil || [[search_ text] isEqualToString:@""]) + return [NSURL URLWithString:@"cydia://search"]; + else + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://search/%@", [search_ text]]]; +} + - (void) setSearchTerm:(NSString *)searchTerm { [search_ setText:searchTerm]; + [self reloadData]; } - (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar { - [packages_ setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; + [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; [search_ resignFirstResponder]; [self reloadData]; } - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text { - [packages_ setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)]; + [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)]; [self reloadData]; } - (id) initWithDatabase:(Database *)database { - return [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil]; + if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil])) { + search_ = [[UISearchBar alloc] init]; + } return self; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - if (!search_) { - search_ = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)]; + + if (!searchloaded_) { + searchloaded_ = YES; + [search_ setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)]; [search_ layoutSubviews]; [search_ setPlaceholder:UCLocalize("SEARCH_EX")]; @@ -7151,15 +7279,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } -- (void) _reloadData { -} - - (void) reloadData { - _profile(SearchController$reloadData) - [packages_ reloadData]; - _end - PrintTimes(); - [packages_ resetCursor]; + [self setObject:[search_ text]]; + [super reloadData]; + [self resetCursor]; } - (void) didSelectPackage:(Package *)package { @@ -7191,18 +7314,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation PackageSettingsController - (void) dealloc { + [self releaseSubviews]; [name_ release]; - if (package_ != nil) - [package_ release]; - [table_ release]; - [subscribedSwitch_ release]; - [ignoredSwitch_ release]; - [subscribedCell_ release]; - [ignoredCell_ release]; + [package_ release]; [super dealloc]; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/settings", [package_ id]]]; +} + - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { if (package_ == nil) return 0; @@ -7251,48 +7373,69 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return nil; } -- (NSString *) title { return UCLocalize("SETTINGS"); } +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; -- (id) initWithDatabase:(Database *)database package:(NSString *)package { - if ((self = [super init])) { - database_ = database; - name_ = [package retain]; + table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped]; + [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [table_ setDataSource:self]; + [table_ setDelegate:self]; + [[self view] addSubview:table_]; - [[self navigationItem] setTitle:UCLocalize("SETTINGS")]; + subscribedSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)]; + [subscribedSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; + [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventValueChanged]; - table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped]; - [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:table_]; + ignoredSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)]; + [ignoredSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; + [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventValueChanged]; + // Disable this switch, since it only reflects (not modifies) the ignored state. + [ignoredSwitch_ setUserInteractionEnabled:NO]; - subscribedSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)]; - [subscribedSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; - [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventValueChanged]; + subscribedCell_ = [[UITableViewCell alloc] init]; + [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")]; + [subscribedCell_ setAccessoryView:subscribedSwitch_]; + [subscribedCell_ setSelectionStyle:UITableViewCellSelectionStyleNone]; - ignoredSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)]; - [ignoredSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; - [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventValueChanged]; - // Disable this switch, since it only reflects (not modifies) the ignored state. - [ignoredSwitch_ setUserInteractionEnabled:NO]; + ignoredCell_ = [[UITableViewCell alloc] init]; + [ignoredCell_ setText:UCLocalize("IGNORE_UPGRADES")]; + [ignoredCell_ setAccessoryView:ignoredSwitch_]; + [ignoredCell_ setSelectionStyle:UITableViewCellSelectionStyleNone]; + // FIXME: Ignored state is not saved. + [ignoredCell_ setUserInteractionEnabled:NO]; +} - subscribedCell_ = [[UITableViewCell alloc] init]; - [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")]; - [subscribedCell_ setAccessoryView:subscribedSwitch_]; - [subscribedCell_ setSelectionStyle:UITableViewCellSelectionStyleNone]; +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("SETTINGS")]; +} - ignoredCell_ = [[UITableViewCell alloc] init]; - [ignoredCell_ setText:UCLocalize("IGNORE_UPGRADES")]; - [ignoredCell_ setAccessoryView:ignoredSwitch_]; - [ignoredCell_ setSelectionStyle:UITableViewCellSelectionStyleNone]; - // FIXME: Ignored state is not saved. - [ignoredCell_ setUserInteractionEnabled:NO]; +- (void) releaseSubviews { + [ignoredCell_ release]; + ignoredCell_ = nil; - [table_ setDataSource:self]; - [table_ setDelegate:self]; - [self reloadData]; + [subscribedCell_ release]; + subscribedCell_ = nil; + + [table_ release]; + table_ = nil; + + [ignoredSwitch_ release]; + ignoredSwitch_ = nil; + + [subscribedSwitch_ release]; + subscribedSwitch_ = nil; +} + +- (id) initWithDatabase:(Database *)database package:(NSString *)package { + if ((self = [super init])) { + database_ = database; + name_ = [package retain]; } return self; } - (void) reloadData { + [super reloadData]; + if (package_ != nil) [package_ autorelease]; package_ = [database_ packageWithName:name_]; @@ -7305,47 +7448,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [table_ reloadData]; } -@end -/* }}} */ -/* Signature Controller {{{ */ -@interface SignatureController : CYBrowserController { - _transient Database *database_; - NSString *package_; -} - -- (id) initWithDatabase:(Database *)database package:(NSString *)package; - -@end - -@implementation SignatureController - -- (void) dealloc { - [package_ release]; - [super dealloc]; -} - -- (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { - // XXX: dude! - [super webView:view didClearWindowObject:window forFrame:frame]; -} - -- (id) initWithDatabase:(Database *)database package:(NSString *)package { - if ((self = [super init]) != nil) { - database_ = database; - package_ = [package retain]; - [self reloadData]; - } return self; -} - -- (void) reloadData { - [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"signature" ofType:@"html"]]]; -} - @end /* }}} */ /* Installed Controller {{{ */ -@interface InstalledController : FilteredPackageController { +@interface InstalledController : FilteredPackageListController { BOOL expert_; } @@ -7362,7 +7469,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super dealloc]; } -- (NSString *) title { return UCLocalize("INSTALLED"); } +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://installed"]; +} - (id) initWithDatabase:(Database *)database { if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) { @@ -7394,10 +7503,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #endif } -- (void) reloadData { - [packages_ reloadData]; -} - - (void) updateRoleButton { if (Role_ != nil && ![Role_ isEqualToString:@"Developer"]) [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] @@ -7409,18 +7514,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) roleButtonClicked { - [packages_ setObject:[NSNumber numberWithBool:expert_]]; - [packages_ reloadData]; + [self setObject:[NSNumber numberWithBool:expert_]]; + [self reloadData]; expert_ = !expert_; [self updateRoleButton]; } -- (void) setDelegate:(id)delegate { - [super setDelegate:delegate]; - [packages_ setDelegate:delegate]; -} - @end /* }}} */ @@ -7484,6 +7584,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } return self; } +- (NSString *) accessibilityLabel { + return label_; +} + - (void) drawContentRect:(CGRect)rect { bool highlighted(highlighted_); float width(rect.size.width); @@ -7505,7 +7609,31 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ -/* Source Table {{{ */ +/* Source Controller {{{ */ +@interface SourceController : FilteredPackageListController { + Source *source_; +} + +- (id) initWithDatabase:(Database *)database source:(Source *)source; + +@end + +@implementation SourceController + +- (NSURL *) navigationURL { + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sources/%@", [source_ name]]]; +} + +- (id) initWithDatabase:(Database *)database source:(Source *)source { + source_ = source; + + if ((self = [super initWithDatabase:database title:[source label] filter:@selector(isVisibleInSource:) with:source]) != nil) { + } return self; +} + +@end +/* }}} */ +/* Sources Controller {{{ */ @interface SourcesController : CYViewController < UITableViewDataSource, UITableViewDelegate @@ -7529,7 +7657,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (id) initWithDatabase:(Database *)database; - - (void) updateButtonsForEditingStatus:(BOOL)editing animated:(BOOL)animated; @end @@ -7545,12 +7672,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) dealloc { - if (href_ != nil) - [href_ release]; - if (hud_ != nil) - [hud_ release]; - if (error_ != nil) - [error_ release]; + [self releaseSubviews]; + + [href_ release]; + [hud_ release]; + [error_ release]; //[self _releaseConnection:installer_]; [self _releaseConnection:trivial_]; @@ -7559,10 +7685,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { //[self _releaseConnection:automatic_]; [sources_ release]; - [list_ release]; [super dealloc]; } +- (NSURL *) navigationURL { + return [NSURL URLWithString:@"cydia://sources"]; +} + - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated]; @@ -7608,27 +7737,22 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { SourceCell *cell = (SourceCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if(cell == nil) cell = [[[SourceCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease]; [cell setSource:[self sourceAtIndexPath:indexPath]]; + [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; return cell; } -- (UITableViewCellAccessoryType) tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath { - return UITableViewCellAccessoryDisclosureIndicator; -} - - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { Source *source = [self sourceAtIndexPath:indexPath]; - FilteredPackageController *packages = [[[FilteredPackageController alloc] + SourceController *controller = [[[SourceController alloc] initWithDatabase:database_ - title:[source label] - filter:@selector(isVisibleInSource:) - with:source + source:source ] autorelease]; - [packages setDelegate:delegate_]; + [controller setDelegate:delegate_]; - [[self navigationController] pushViewController:packages animated:YES]; + [[self navigationController] pushViewController:controller animated:YES]; } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { @@ -7701,7 +7825,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:warning delegate:self cancelButtonTitle:UCLocalize("CANCEL") - otherButtonTitles:UCLocalize("ADD_ANYWAY"), nil + otherButtonTitles: + UCLocalize("ADD_ANYWAY"), + nil ] autorelease]; [alert setContext:@"warning"]; @@ -7769,8 +7895,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _endConnection:connection]; } -- (NSString *) title { return UCLocalize("SOURCES"); } - - (NSURLConnection *) _requestHRef:(NSString *)href method:(NSString *)method { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:href] @@ -7848,27 +7972,37 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } -- (id) initWithDatabase:(Database *)database { - if ((self = [super init]) != nil) { - [[self navigationItem] setTitle:UCLocalize("SOURCES")]; - [self updateButtonsForEditingStatus:NO animated:NO]; +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - database_ = database; - sources_ = [[NSMutableArray arrayWithCapacity:16] retain]; + list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [list_ setRowHeight:56]; + [list_ setDataSource:self]; + [list_ setDelegate:self]; + [[self view] addSubview:list_]; +} - list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:56]; - [[self view] addSubview:list_]; +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("SOURCES")]; + [self updateButtonsForEditingStatus:NO animated:NO]; +} - [list_ setDataSource:self]; - [list_ setDelegate:self]; +- (void) releaseSubviews { + [list_ release]; + list_ = nil; +} - [self reloadData]; +- (id) initWithDatabase:(Database *)database { + if ((self = [super init]) != nil) { + database_ = database; + sources_ = [[NSMutableArray arrayWithCapacity:16] retain]; } return self; } - (void) reloadData { + [super reloadData]; + pkgSourceList list; if (!list.ReadMainList()) return; @@ -7898,7 +8032,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:nil delegate:self cancelButtonTitle:UCLocalize("CANCEL") - otherButtonTitles:UCLocalize("ADD_SOURCE"), nil + otherButtonTitles: + UCLocalize("ADD_SOURCE"), + nil ] autorelease]; [alert setContext:@"source"]; @@ -7977,48 +8113,63 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end @implementation SettingsController + - (void) dealloc { + [self releaseSubviews]; + + [super dealloc]; +} + +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + + table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped]; + [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [table_ setDelegate:self]; + [table_ setDataSource:self]; + [[self view] addSubview:table_]; + + NSArray *items = [NSArray arrayWithObjects: + UCLocalize("USER"), + UCLocalize("HACKER"), + UCLocalize("DEVELOPER"), + nil]; + segment_ = [[UISegmentedControl alloc] initWithItems:items]; + container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)]; + [container_ addSubview:segment_]; +} + +- (void) viewDidLoad { + [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")]; + + int index = -1; + if ([Role_ isEqualToString:@"User"]) index = 0; + if ([Role_ isEqualToString:@"Hacker"]) index = 1; + if ([Role_ isEqualToString:@"Developer"]) index = 2; + if (index != -1) { + [segment_ setSelectedSegmentIndex:index]; + [self showDoneButton]; + } + + [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged]; + [self resizeSegmentedControl]; +} + +- (void) releaseSubviews { [table_ release]; + table_ = nil; + [segment_ release]; - [container_ release]; + segment_ = nil; - [super dealloc]; + [container_ release]; + container_ = nil; } - (id) initWithDatabase:(Database *)database delegate:(id)delegate { if ((self = [super init])) { database_ = database; roledelegate_ = delegate; - - [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")]; - - NSArray *items = [NSArray arrayWithObjects: - UCLocalize("USER"), - UCLocalize("HACKER"), - UCLocalize("DEVELOPER"), - nil]; - segment_ = [[UISegmentedControl alloc] initWithItems:items]; - container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)]; - [container_ addSubview:segment_]; - - int index = -1; - if ([Role_ isEqualToString:@"User"]) index = 0; - if ([Role_ isEqualToString:@"Hacker"]) index = 1; - if ([Role_ isEqualToString:@"Developer"]) index = 2; - if (index != -1) { - [segment_ setSelectedSegmentIndex:index]; - [self showDoneButton]; - } - - [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged]; - [self resizeSegmentedControl]; - - table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped]; - [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [table_ setDelegate:self]; - [table_ setDataSource:self]; - [[self view] addSubview:table_]; - [table_ reloadData]; } return self; } @@ -8133,66 +8284,84 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return section == 3 ? container_ : nil; } +- (void) reloadData { + [super reloadData]; + [table_ reloadData]; +} + @end /* }}} */ /* Stash Controller {{{ */ @interface StashController : CYViewController { - // XXX: just delete these things - _transient UIActivityIndicatorView *spinner_; - _transient UILabel *status_; - _transient UILabel *caption_; + UIActivityIndicatorView *spinner_; + UILabel *status_; + UILabel *caption_; } @end @implementation StashController -- (id) init { - if ((self = [super init])) { - [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]]; - spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease]; - CGRect spinrect = [spinner_ frame]; - spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2); - spinrect.origin.y = [[self view] frame].size.height - 80.0f; - [spinner_ setFrame:spinrect]; - [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin]; - [[self view] addSubview:spinner_]; - [spinner_ startAnimating]; +- (void) dealloc { + [self releaseSubviews]; - CGRect captrect; - captrect.size.width = [[self view] frame].size.width; - captrect.size.height = 40.0f; - captrect.origin.x = 0; - captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2); - caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease]; - [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")]; - [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin]; - [caption_ setFont:[UIFont boldSystemFontOfSize:28.0f]]; - [caption_ setTextColor:[UIColor whiteColor]]; - [caption_ setBackgroundColor:[UIColor clearColor]]; - [caption_ setShadowColor:[UIColor blackColor]]; - [caption_ setTextAlignment:UITextAlignmentCenter]; - [[self view] addSubview:caption_]; - - CGRect statusrect; - statusrect.size.width = [[self view] frame].size.width; - statusrect.size.height = 30.0f; - statusrect.origin.x = 0; - statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height; - status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease]; - [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin]; - [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")]; - [status_ setFont:[UIFont systemFontOfSize:16.0f]]; - [status_ setTextColor:[UIColor whiteColor]]; - [status_ setBackgroundColor:[UIColor clearColor]]; - [status_ setShadowColor:[UIColor blackColor]]; - [status_ setTextAlignment:UITextAlignmentCenter]; - [[self view] addSubview:status_]; - } return self; + [super dealloc]; +} + +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]]; + + spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease]; + CGRect spinrect = [spinner_ frame]; + spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2); + spinrect.origin.y = [[self view] frame].size.height - 80.0f; + [spinner_ setFrame:spinrect]; + [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin]; + [[self view] addSubview:spinner_]; + [spinner_ startAnimating]; + + CGRect captrect; + captrect.size.width = [[self view] frame].size.width; + captrect.size.height = 40.0f; + captrect.origin.x = 0; + captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2); + caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease]; + [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")]; + [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin]; + [caption_ setFont:[UIFont boldSystemFontOfSize:28.0f]]; + [caption_ setTextColor:[UIColor whiteColor]]; + [caption_ setBackgroundColor:[UIColor clearColor]]; + [caption_ setShadowColor:[UIColor blackColor]]; + [caption_ setTextAlignment:UITextAlignmentCenter]; + [[self view] addSubview:caption_]; + + CGRect statusrect; + statusrect.size.width = [[self view] frame].size.width; + statusrect.size.height = 30.0f; + statusrect.origin.x = 0; + statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height; + status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease]; + [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin]; + [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")]; + [status_ setFont:[UIFont systemFontOfSize:16.0f]]; + [status_ setTextColor:[UIColor whiteColor]]; + [status_ setBackgroundColor:[UIColor clearColor]]; + [status_ setShadowColor:[UIColor blackColor]]; + [status_ setTextAlignment:UITextAlignmentCenter]; + [[self view] addSubview:status_]; } -- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation { - return IsWildcat_ || orientation == UIInterfaceOrientationPortrait; +- (void) releaseSubviews { + [spinner_ release]; + spinner_ = nil; + + [status_ release]; + status_ = nil; + + [caption_ release]; + caption_ = nil; } + @end /* }}} */ @@ -8246,7 +8415,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:UCLocalize("HALFINSTALLED_PACKAGE_EX") delegate:self cancelButtonTitle:UCLocalize("FORCIBLY_CLEAR") - otherButtonTitles:UCLocalize("TEMPORARY_IGNORE"), nil + otherButtonTitles: + UCLocalize("TEMPORARY_IGNORE"), + nil ] autorelease]; [alert setContext:@"fixhalf"]; @@ -8259,7 +8430,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { message:UCLocalize("ESSENTIAL_UPGRADE_EX") delegate:self cancelButtonTitle:UCLocalize("TEMPORARY_IGNORE") - otherButtonTitles:UCLocalize("UPGRADE_ESSENTIAL"), UCLocalize("COMPLETE_UPGRADE"), nil + otherButtonTitles: + UCLocalize("UPGRADE_ESSENTIAL"), + UCLocalize("COMPLETE_UPGRADE"), + nil ] autorelease]; [alert setContext:@"upgrade"]; @@ -8328,8 +8502,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (recently || loaded_ || ManualRefresh) { [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO]; - // If we are cancelling due to ManualRefresh or a recent refresh - // we need to make sure it knows it's already loaded. + // If we are cancelling, we need to make sure it knows it's already loaded. loaded_ = true; return; } else { @@ -8564,41 +8737,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self complete]; } -- (void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { - CYNavigationController *controller = (CYNavigationController *) viewController; - - if ([[controller viewControllers] count] == 0) { - int index = [tabbar_ selectedIndex]; - CYViewController *root = nil; - - if (index == 0) - root = [[[HomeController alloc] init] autorelease]; - else if (index == 1) - root = [[[SectionsController alloc] initWithDatabase:database_] autorelease]; - else if (index == 2) - root = [[[ChangesController alloc] initWithDatabase:database_ delegate:self] autorelease]; - - if (IsWildcat_) { - if (index == 3) - root = [[[InstalledController alloc] initWithDatabase:database_] autorelease]; - else if (index == 4) - root = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; - else if (index == 5) - root = [[[SearchController alloc] initWithDatabase:database_] autorelease]; - } else { - if (index == 3) - root = [[[ManageController alloc] init] autorelease]; - else if (index == 4) - root = [[[SearchController alloc] initWithDatabase:database_] autorelease]; - } - - [root setDelegate:self]; - - if (root != nil) - [controller setViewControllers:[NSArray arrayWithObject:root]]; - } -} - - (void) showSettings { SettingsController *role = [[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease]; CYNavigationController *nav = [[[CYNavigationController alloc] initWithRootViewController:role] autorelease]; @@ -8617,12 +8755,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self setNetworkActivityIndicatorVisible:NO]; } -- (void) setPackageController:(CYPackageController *)view { - WebThreadLock(); - [view setPackage:nil]; - WebThreadUnlock(); -} - - (void) cancelAndClear:(bool)clear { @synchronized (self) { if (clear) { @@ -8640,7 +8772,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSString *context([alert context]); if ([context isEqualToString:@"fixhalf"]) { - if (button == [alert firstOtherButtonIndex]) { + if (button == [alert cancelButtonIndex]) { @synchronized (self) { for (Package *broken in broken_) { [broken remove]; @@ -8655,7 +8787,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self resolve]; [self perform]; } - } else if (button == [alert cancelButtonIndex]) { + } else if (button == [alert firstOtherButtonIndex]) { [broken_ removeAllObjects]; [self _loaded]; } @@ -8743,17 +8875,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (CYViewController *) pageForPackage:(NSString *)name { - if (Package *package = [database_ packageWithName:name]) { - CYPackageController *view = [[[CYPackageController alloc] initWithDatabase:database_] autorelease]; - [view setPackage:package]; - return view; - } else { - NSURL *url([NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"unknown" ofType:@"html"]]); - url = [NSURL URLWithString:[[url absoluteString] stringByAppendingString:[NSString stringWithFormat:@"?%@", name]]]; - CYBrowserController *browser = [[[CYBrowserController alloc] init] autorelease]; - [browser loadURL:url]; - return browser; - } + return [[[CYPackageController alloc] initWithDatabase:database_ forPackage:name] autorelease]; } - (CYViewController *) pageForURL:(NSURL *)url { @@ -8763,7 +8885,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSString *path([[url absoluteString] substringFromIndex:[scheme length] + 3]); NSArray *components([path pathComponents]); - if ([scheme isEqualToString:@"apptapp"] && [components count] && [[components objectAtIndex:0] isEqualToString:@"package"]) + if ([scheme isEqualToString:@"apptapp"] && [components count] > 0 && [[components objectAtIndex:0] isEqualToString:@"package"]) return [self pageForPackage:[components objectAtIndex:1]]; if ([components count] < 1 || ![scheme isEqualToString:@"cydia"]) @@ -8771,82 +8893,76 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSString *base([components objectAtIndex:0]); - if ([components count] == 1) { - if ([base isEqualToString:@"storage"]) { - CYBrowserController *browser = [[[CYBrowserController alloc] init] autorelease]; - [browser loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]]]; - return browser; + CYViewController *controller = nil; + + if ([base isEqualToString:@"url"]) { + // This kind of URL can contain slashes in the argument, so we can't parse them below. + NSString *destination = [[url absoluteString] substringFromIndex:([scheme length] + [@"://" length] + [base length] + [@"/" length])]; + controller = [[[CYBrowserController alloc] initWithURL:[NSURL URLWithString:destination]] autorelease]; + } else if ([components count] == 1) { + if ([base isEqualToString:@"manage"]) { + controller = [[[ManageController alloc] init] autorelease]; } if ([base isEqualToString:@"sources"]) { - SourcesController *source = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; - return source; + controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; } if ([base isEqualToString:@"home"]) { - HomeController *home = [[[HomeController alloc] init] autorelease]; - return home; + controller = [[[HomeController alloc] init] autorelease]; } if ([base isEqualToString:@"sections"]) { - SectionsController *sections = [[[SectionsController alloc] initWithDatabase:database_] autorelease]; - return sections; + controller = [[[SectionsController alloc] initWithDatabase:database_] autorelease]; } if ([base isEqualToString:@"search"]) { - SearchController *search = [[[SearchController alloc] initWithDatabase:database_] autorelease]; - return search; + controller = [[[SearchController alloc] initWithDatabase:database_] autorelease]; } if ([base isEqualToString:@"changes"]) { - ChangesController *changes = [[[ChangesController alloc] initWithDatabase:database_ delegate:self] autorelease]; - return changes; + controller = [[[ChangesController alloc] initWithDatabase:database_] autorelease]; } if ([base isEqualToString:@"installed"]) { - InstalledController *installed = [[[InstalledController alloc] initWithDatabase:database_] autorelease]; - return installed; + controller = [[[InstalledController alloc] initWithDatabase:database_] autorelease]; } } else if ([components count] == 2) { NSString *argument = [components objectAtIndex:1]; if ([base isEqualToString:@"package"]) { - CYViewController *package = [self pageForPackage:argument]; - return package; + controller = [self pageForPackage:argument]; } if ([base isEqualToString:@"search"]) { - SearchController *search = [[[SearchController alloc] initWithDatabase:database_] autorelease]; - [search setSearchTerm:argument]; - return search; + controller = [[[SearchController alloc] initWithDatabase:database_] autorelease]; + [(SearchController *)controller setSearchTerm:argument]; } if ([base isEqualToString:@"sections"]) { if ([argument isEqualToString:@"all"]) argument = nil; - SectionController *section = [[[SectionController alloc] initWithDatabase:database_ section:argument] autorelease]; - [section setDelegate:self]; - return section; + controller = [[[SectionController alloc] initWithDatabase:database_ section:argument] autorelease]; } if ([base isEqualToString:@"sources"]) { if ([argument isEqualToString:@"add"]) { - SourcesController *source = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; - [source showAddSourcePrompt]; - return source; + controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; + [(SourcesController *)controller showAddSourcePrompt]; } else { - // XXX: Create page of the source specfified. + NSArray *sources = [database_ sources]; + for (Source *source in sources) { + if ([[source name] caseInsensitiveCompare:argument] == NSOrderedSame) { + controller = [[[SourceController alloc] initWithDatabase:database_ source:source] autorelease]; + break; + } + } } } - if ([base isEqualToString:@"url"]) { - CYBrowserController *browser = [[[CYBrowserController alloc] init] autorelease]; - [browser loadURL:[NSURL URLWithString:argument]]; - return browser; - } - if ([base isEqualToString:@"launch"]) { [self launchApplicationWithIdentifier:argument suspended:NO]; + return nil; } } else if ([components count] == 3) { NSString *arg1 = [components objectAtIndex:1]; @@ -8854,20 +8970,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([base isEqualToString:@"package"]) { if ([arg2 isEqualToString:@"settings"]) { - return [[[PackageSettingsController alloc] initWithDatabase:database_ package:arg1] autorelease]; - } else if ([arg2 isEqualToString:@"signature"]) { - return [[[SignatureController alloc] initWithDatabase:database_ package:arg1] autorelease]; + controller = [[[PackageSettingsController alloc] initWithDatabase:database_ package:arg1] autorelease]; } else if ([arg2 isEqualToString:@"files"]) { if (Package *package = [database_ packageWithName:arg1]) { - FileTable *files = [[[FileTable alloc] initWithDatabase:database_] autorelease]; - [files setPackage:package]; - return files; + controller = [[[FileTable alloc] initWithDatabase:database_] autorelease]; + [(FileTable *)controller setPackage:package]; } } } } - return nil; + [controller setDelegate:self]; + return controller; } - (BOOL) openCydiaURL:(NSURL *)url { @@ -8876,7 +8990,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (page != nil) { CYNavigationController *nav = [[[CYNavigationController alloc] init] autorelease]; [nav setViewControllers:[NSArray arrayWithObject:page]]; - [tabbar_ setTransientViewController:nav]; + [tabbar_ setUnselectedViewController:nav]; } return page != nil; @@ -8898,6 +9012,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super applicationWillResignActive:application]; } +- (void) applicationWillTerminate:(UIApplication *)application { + Changed_ = true; + [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"]; + [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"]; + [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"]; + + [self _saveConfig]; +} + - (void) addStashController { ++locked_; stash_ = [[StashController alloc] init]; @@ -8932,7 +9055,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) setupViewControllers { tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_]; - [tabbar_ setDelegate:self]; NSMutableArray *items([NSMutableArray arrayWithObjects: [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:0] autorelease], @@ -8957,16 +9079,22 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [tabbar_ setViewControllers:controllers]; [tabbar_ setUpdateDelegate:self]; - [window_ addSubview:[tabbar_ view]]; } -- (void)showEmulatedLoadingControllerInView:(UIView *)view { - static CYEmulatedLoadingController *fake = [[CYEmulatedLoadingController alloc] init]; +- (CYEmulatedLoadingController *)showEmulatedLoadingControllerInView:(UIView *)view { + static CYEmulatedLoadingController *fake = nil; + if (view != nil) { + if (fake == nil) + fake = [[CYEmulatedLoadingController alloc] initWithDatabase:database_]; [view addSubview:[fake view]]; } else { [[fake view] removeFromSuperview]; + [fake release]; + fake = nil; } + + return fake; } - (void) applicationDidFinishLaunching:(id)unused { @@ -9033,19 +9161,79 @@ _trace(); - (void) loadData { _trace(); if (Role_ == nil) { - [self showSettings]; + [window_ setUserInteractionEnabled:YES]; + + SettingsController *role = [[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease]; + CYNavigationController *nav = [[[CYNavigationController alloc] initWithRootViewController:role] autorelease]; + if (IsWildcat_) + [nav setModalPresentationStyle:UIModalPresentationFormSheet]; + [[self showEmulatedLoadingControllerInView:window_] presentModalViewController:nav animated:YES]; + return; + } else { + if ([[self showEmulatedLoadingControllerInView:window_] modalViewController] != nil) + [[self showEmulatedLoadingControllerInView:window_] dismissModalViewControllerAnimated:YES]; + [window_ setUserInteractionEnabled:NO]; } [self reloadData]; PrintTimes(); + [window_ addSubview:[tabbar_ view]]; [self showEmulatedLoadingControllerInView:nil]; [window_ setUserInteractionEnabled:YES]; - // Show the home page. - CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:0]; - [navigation setViewControllers:[NSArray arrayWithObject:[[[HomeController alloc] init] autorelease]]]; + int selectedIndex = 0; + NSMutableArray *items = nil; + + bool recently = false; + NSDate *closed([Metadata_ objectForKey:@"LastClosed"]); + if (closed != nil) { + NSTimeInterval interval([closed timeIntervalSinceNow]); + // XXX: Is 15 minutes the optimal time here? + if (interval <= 0 && interval > -(15*60)) + recently = true; + } + + items = [[Metadata_ objectForKey:@"InterfaceState"] mutableCopy]; + selectedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue]; + + BOOL enough = YES; + for (NSArray *entry in items) + if ([entry count] <= 0) + enough = NO; + + if (!recently || !items || !enough) { + selectedIndex = 0; + items = [NSMutableArray array]; + [items addObject:[NSArray arrayWithObject:@"cydia://home"]]; + [items addObject:[NSArray arrayWithObject:@"cydia://sections"]]; + [items addObject:[NSArray arrayWithObject:@"cydia://changes"]]; + if (!IsWildcat_) { + [items addObject:[NSArray arrayWithObject:@"cydia://manage"]]; + } else { + [items addObject:[NSArray arrayWithObject:@"cydia://installed"]]; + [items addObject:[NSArray arrayWithObject:@"cydia://sources"]]; + } + [items addObject:[NSArray arrayWithObject:@"cydia://search"]]; + } + + [tabbar_ setSelectedIndex:selectedIndex]; + for (unsigned int tab = 0; tab < [[tabbar_ viewControllers] count]; tab++) { + NSArray *stack = [items objectAtIndex:tab]; + CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:tab]; + NSMutableArray *current = [NSMutableArray array]; + + for (unsigned int nav = 0; nav < [stack count]; nav++) { + NSString *addr = [stack objectAtIndex:nav]; + NSURL *url = [NSURL URLWithString:addr]; + CYViewController *page = [self pageForURL:url]; + if (page != nil) + [current addObject:page]; + } + + [navigation setViewControllers:current]; + } // (Try to) show the startup URL. if (starturl_ != nil) { @@ -9108,6 +9296,33 @@ MSHook(void, UIHardware$_playSystemSound$, Class self, SEL _cmd, int sound) { } } +Class $UIApplication; + +MSHook(void, UIApplication$_updateApplicationAccessibility, UIApplication *self, SEL _cmd) { + static BOOL initialized = NO; + static BOOL started = NO; + + NSDictionary *dict([[[NSDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.Accessibility.plist"] autorelease]); + BOOL enabled = [[dict objectForKey:@"VoiceOverTouchEnabled"] boolValue] || [[dict objectForKey:@"VoiceOverTouchEnabledByiTunes"] boolValue]; + + if ([self respondsToSelector:@selector(_accessibilityBundlePrincipalClass)]) { + id bundle = [self performSelector:@selector(_accessibilityBundlePrincipalClass)]; + if (![bundle respondsToSelector:@selector(_accessibilityStopServer)]) return; + if (![bundle respondsToSelector:@selector(_accessibilityStartServer)]) return; + + if (initialized && !enabled) { + initialized = NO; + [bundle performSelector:@selector(_accessibilityStopServer)]; + } else if (enabled) { + initialized = YES; + if (!started) { + started = YES; + [bundle performSelector:@selector(_accessibilityStartServer)]; + } + } + } +} + int main(int argc, char *argv[]) { _pooled _trace(); @@ -9117,6 +9332,18 @@ int main(int argc, char *argv[]) { _pooled } else IsWildcat_ = false; + UIScreen *screen([UIScreen mainScreen]); + if ([screen respondsToSelector:@selector(scale)]) + ScreenScale_ = [screen scale]; + else + ScreenScale_ = 1; + + NSMutableArray *parts([NSMutableArray arrayWithCapacity:2]); + if (ScreenScale_ > 1) + [parts addObject:@"@2x"]; + [parts addObject:(IsWildcat_ ? @"~ipad" : @"~iphone")]; + UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios%@", [parts componentsJoinedByString:@""]]); + PackageName = reinterpret_cast(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname)))); /* Library Hacks {{{ */ @@ -9135,6 +9362,13 @@ int main(int argc, char *argv[]) { _pooled _UIHardware$_playSystemSound$ = reinterpret_cast(method_getImplementation(UIHardware$_playSystemSound$)); method_setImplementation(UIHardware$_playSystemSound$, reinterpret_cast(&$UIHardware$_playSystemSound$)); } + + $UIApplication = objc_getClass("UIApplication"); + Method UIApplication$_updateApplicationAccessibility(class_getInstanceMethod($UIApplication, @selector(_updateApplicationAccessibility))); + if (UIApplication$_updateApplicationAccessibility != NULL) { + _UIApplication$_updateApplicationAccessibility = reinterpret_cast(method_getImplementation(UIApplication$_updateApplicationAccessibility)); + method_setImplementation(UIApplication$_updateApplicationAccessibility, reinterpret_cast(&$UIApplication$_updateApplicationAccessibility)); + } /* }}} */ /* Set Locale {{{ */ Locale_ = CFLocaleCopyCurrent(); @@ -9308,11 +9542,15 @@ int main(int argc, char *argv[]) { _pooled _trace(); if (Packages_ != nil) { - CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, NULL); + bool fail(false); + CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, &fail); _trace(); - [Metadata_ removeObjectForKey:@"Packages"]; - Packages_ = nil; - Changed_ = true; + + if (!fail) { + [Metadata_ removeObjectForKey:@"Packages"]; + Packages_ = nil; + Changed_ = true; + } } Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];