X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/affeffc797be156742cbd8efe899ba74dd719b0d..807ae6d7d376189cbf17271686d8389c541c7975:/Cydia.mm diff --git a/Cydia.mm b/Cydia.mm index aa809a7d..8d48ac06 100644 --- a/Cydia.mm +++ b/Cydia.mm @@ -36,6 +36,8 @@ */ /* #include Directives {{{ */ +#import "UICaboodle.h" + #include #include @@ -100,12 +102,20 @@ extern "C" { #import "BrowserView.h" #import "ResetView.h" -#import "UICaboodle.h" /* }}} */ //#define _finline __attribute__((force_inline)) #define _finline inline +struct timeval _ltv; +bool _itv; + +#define _limit(count) do { \ + static size_t _count(0); \ + if (++_count == count) \ + exit(0); \ +} while (false) + /* Objective-C Handle<> {{{ */ template class _H { @@ -242,6 +252,84 @@ extern NSString * const kCAFilterNearest; #define ForSaurik 1 #define RecycleWebViews 0 +/* Radix Sort {{{ */ +@interface NSMutableArray (Radix) +- (void) radixUsingSelector:(SEL)selector withObject:(id)object; +@end + +@implementation NSMutableArray (Radix) + +- (void) radixUsingSelector:(SEL)selector withObject:(id)object { + NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"L12@0:4@8"]]); + [invocation setSelector:selector]; + [invocation setArgument:&object atIndex:2]; + + size_t count([self count]); + + struct RadixItem { + size_t index; + uint32_t key; + } *swap(new RadixItem[count * 2]), *lhs(swap), *rhs(swap + count); + + for (size_t i(0); i != count; ++i) { + RadixItem &item(lhs[i]); + item.index = i; + + id object([self objectAtIndex:i]); + [invocation setTarget:object]; + + [invocation invoke]; + [invocation getReturnValue:&item.key]; + } + + static const size_t bits = 11; + static const size_t slots = 1 << bits; + static const size_t passes = (32 + (bits - 1)) / bits; + + size_t *hist(new size_t[slots]); + + for (size_t pass(0); pass != passes; ++pass) { + memset(hist, 0, sizeof(size_t) * slots); + + for (size_t i(0); i != count; ++i) { + uint32_t key(lhs[i].key); + key >>= pass * bits; + key &= _not(uint32_t) >> 32 - bits; + ++hist[key]; + } + + size_t offset(0); + for (size_t i(0); i != slots; ++i) { + size_t local(offset); + offset += hist[i]; + hist[i] = local; + } + + for (size_t i(0); i != count; ++i) { + uint32_t key(lhs[i].key); + key >>= pass * bits; + key &= _not(uint32_t) >> 32 - bits; + rhs[hist[key]++] = lhs[i]; + } + + RadixItem *tmp(lhs); + lhs = rhs; + rhs = tmp; + } + + delete [] hist; + + NSMutableArray *values([NSMutableArray arrayWithCapacity:count]); + for (size_t i(0); i != count; ++i) + [values addObject:[self objectAtIndex:lhs[i].index]]; + [self setArray:values]; + + delete [] swap; +} + +@end +/* }}} */ + typedef enum { kUIControlEventMouseDown = 1 << 0, kUIControlEventMouseMovedInside = 1 << 2, // mouse moved inside control target @@ -548,7 +636,7 @@ NSString *SizeString(double size) { static const char *powers_[] = {"B", "kB", "MB", "GB"}; - return [NSString stringWithFormat:@"%s%.1f%s", (negative ? "-" : ""), size, powers_[power]]; + return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]]; } NSString *StripVersion(NSString *version) { @@ -758,6 +846,8 @@ class Progress : FILE *input_; } ++ (Database *) sharedInstance; + - (void) _readCydia:(NSNumber *)fd; - (void) _readStatus:(NSNumber *)fd; - (void) _readOutput:(NSNumber *)fd; @@ -766,7 +856,6 @@ class Progress : - (Package *) packageWithName:(NSString *)name; -- (Database *) init; - (pkgCacheFile &) cache; - (pkgDepCache::Policy *) policy; - (pkgRecords *) records; @@ -1056,6 +1145,8 @@ NSString *Scour(const char *field, const char *begin, const char *end) { Source *source_; bool cached_; + NSString *section_; + NSString *latest_; NSString *installed_; @@ -1084,7 +1175,10 @@ NSString *Scour(const char *field, const char *begin, const char *end) { - (NSString *) description; - (NSString *) index; +- (NSMutableDictionary *) metadata; - (NSDate *) seen; +- (BOOL) subscribed; +- (BOOL) ignored; - (NSString *) latest; - (NSString *) installed; @@ -1105,7 +1199,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) { - (NSString *) id; - (NSString *) name; - (NSString *) tagline; -- (NSString *) icon; +- (UIImage *) icon; - (NSString *) homepage; - (NSString *) depiction; - (Address *) author; @@ -1123,11 +1217,12 @@ NSString *Scour(const char *field, const char *begin, const char *end) { - (bool) hasSupportingRole; - (BOOL) hasTag:(NSString *)tag; - (NSString *) primaryPurpose; +- (NSArray *) purposes; - (NSComparisonResult) compareByName:(Package *)package; - (NSComparisonResult) compareBySection:(Package *)package; -- (NSComparisonResult) compareBySectionAndName:(Package *)package; -- (NSComparisonResult) compareForChanges:(Package *)package; + +- (uint32_t) compareForChanges; - (void) install; - (void) remove; @@ -1145,6 +1240,9 @@ NSString *Scour(const char *field, const char *begin, const char *end) { if (source_ != nil) [source_ release]; + if (section_ != nil) + [section_ release]; + [latest_ release]; if (installed_ != nil) [installed_ release]; @@ -1175,7 +1273,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) { } + (NSArray *) _attributeKeys { - return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"description", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"maintainer", @"name", @"section", @"size", @"source", @"sponsor", @"tagline", @"warnings", nil]; + return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"description", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"maintainer", @"name", @"purposes", @"section", @"size", @"source", @"sponsor", @"tagline", @"warnings", nil]; } - (NSArray *) attributeKeys { @@ -1192,7 +1290,12 @@ NSString *Scour(const char *field, const char *begin, const char *end) { database_ = database; version_ = [database_ policy]->GetCandidateVer(iterator_); - latest_ = version_.end() ? nil : [StripVersion([NSString stringWithUTF8String:version_.VerStr()]) retain]; + NSString *latest = version_.end() ? nil : [NSString stringWithUTF8String:version_.VerStr()]; + latest_ = [StripVersion(latest) retain]; + + pkgCache::VerIterator current = iterator_.CurrentVer(); + NSString *installed = current.end() ? nil : [NSString stringWithUTF8String:current.VerStr()]; + installed_ = [StripVersion(installed) retain]; if (!version_.end()) file_ = version_.FileList(); @@ -1201,10 +1304,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) { file_ = pkgCache::VerFileIterator(cache, cache.VerFileP); } - pkgCache::VerIterator current = iterator_.CurrentVer(); - installed_ = current.end() ? nil : [StripVersion([NSString stringWithUTF8String:current.VerStr()]) retain]; - - id_ = [[[NSString stringWithUTF8String:iterator_.Name()] lowercaseString] retain]; + id_ = [[NSString stringWithUTF8String:iterator_.Name()] retain]; if (!file_.end()) { pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); @@ -1249,13 +1349,45 @@ NSString *Scour(const char *field, const char *begin, const char *end) { } } - NSMutableDictionary *metadata = [Packages_ objectForKey:id_]; - if (metadata == nil || [metadata count] == 0) { - metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys: + NSString *solid(latest == nil ? installed : latest); + bool changed(false); + + NSString *key([id_ lowercaseString]); + + NSMutableDictionary *metadata = [Packages_ objectForKey:key]; + if (metadata == nil) { + metadata = [[NSMutableDictionary dictionaryWithObjectsAndKeys: now_, @"FirstSeen", - nil]; + nil] mutableCopy]; + + if (solid != nil) + [metadata setObject:solid forKey:@"LastVersion"]; + changed = true; + } else { + NSDate *first([metadata objectForKey:@"FirstSeen"]); + NSDate *last([metadata objectForKey:@"LastSeen"]); + NSString *version([metadata objectForKey:@"LastVersion"]); + + if (first == nil) { + first = last == nil ? now_ : last; + [metadata setObject:first forKey:@"FirstSeen"]; + changed = true; + } - [Packages_ setObject:metadata forKey:id_]; + if (solid != nil) + if (version == nil) { + [metadata setObject:solid forKey:@"LastVersion"]; + changed = true; + } else if (![version isEqualToString:solid]) { + [metadata setObject:solid forKey:@"LastVersion"]; + last = now_; + [metadata setObject:last forKey:@"LastSeen"]; + changed = true; + } + } + + if (changed) { + [Packages_ setObject:metadata forKey:key]; Changed_ = true; } } return self; @@ -1273,6 +1405,9 @@ NSString *Scour(const char *field, const char *begin, const char *end) { } - (NSString *) section { + if (section_ != nil) + return section_; + const char *section = iterator_.Section(); if (section == NULL) return nil; @@ -1286,7 +1421,8 @@ NSString *Scour(const char *field, const char *begin, const char *end) { goto lookup; } - return [name stringByReplacingCharacter:'_' withCharacter:' ']; + section_ = [[name stringByReplacingCharacter:'_' withCharacter:' '] retain]; + return section_; } - (Address *) maintainer { @@ -1325,8 +1461,32 @@ NSString *Scour(const char *field, const char *begin, const char *end) { return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123"; } +- (NSMutableDictionary *) metadata { + return [Packages_ objectForKey:[id_ lowercaseString]]; +} + - (NSDate *) seen { - return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"]; + NSDictionary *metadata([self metadata]); + if ([self subscribed]) + if (NSDate *last = [metadata objectForKey:@"LastSeen"]) + return last; + return [metadata objectForKey:@"FirstSeen"]; +} + +- (BOOL) subscribed { + NSDictionary *metadata([self metadata]); + if (NSNumber *subscribed = [metadata objectForKey:@"IsSubscribed"]) + return [subscribed boolValue]; + else + return false; +} + +- (BOOL) ignored { + NSDictionary *metadata([self metadata]); + if (NSNumber *ignored = [metadata objectForKey:@"IsIgnored"]) + return [ignored boolValue]; + else + return false; } - (NSString *) latest { @@ -1433,8 +1593,21 @@ NSString *Scour(const char *field, const char *begin, const char *end) { return tagline_; } -- (NSString *) icon { - return icon_; +- (UIImage *) icon { + NSString *section = [self section]; + if (section != nil) + section = Simplify(section); + + UIImage *icon(nil); + if (NSString *icon = icon_) + icon = [UIImage imageAtPath:[icon_ substringFromIndex:6]]; + if (icon == nil) if (section != nil) + icon = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]]; + if (icon == nil) if (source_ != nil) if (NSString *icon = [source_ defaultIcon]) + icon = [UIImage imageAtPath:[icon substringFromIndex:6]]; + if (icon == nil) + icon = [UIImage applicationImageNamed:@"unknown.png"]; + return icon; } - (NSString *) homepage { @@ -1605,6 +1778,14 @@ NSString *Scour(const char *field, const char *begin, const char *end) { return nil; } +- (NSArray *) purposes { + NSMutableArray *purposes([NSMutableArray arrayWithCapacity:2]); + for (NSString *tag in tags_) + if ([tag hasPrefix:@"purpose::"]) + [purposes addObject:[tag substringFromIndex:9]]; + return [purposes count] == 0 ? nil : purposes; +} + - (NSComparisonResult) compareByName:(Package *)package { NSString *lhs = [self name]; NSString *rhs = [package name]; @@ -1639,43 +1820,30 @@ NSString *Scour(const char *field, const char *begin, const char *end) { return NSOrderedSame; } -- (NSComparisonResult) compareBySectionAndName:(Package *)package { - NSString *lhs = [self section]; - NSString *rhs = [package section]; - - if (lhs == NULL && rhs != NULL) - return NSOrderedAscending; - else if (lhs != NULL && rhs == NULL) - return NSOrderedDescending; - else if (lhs != NULL && rhs != NULL) { - NSComparisonResult result = [lhs compare:rhs]; - if (result != NSOrderedSame) - return result; - } +- (uint32_t) compareForChanges { + union { + uint32_t key; - return [self compareByName:package]; -} + struct { + uint32_t timestamp : 30; + uint32_t ignored : 1; + uint32_t upgradable : 1; + } bits; + } value; -- (NSComparisonResult) compareForChanges:(Package *)package { - BOOL lhs = [self upgradableAndEssential:YES]; - BOOL rhs = [package upgradableAndEssential:YES]; + value.bits.upgradable = [self upgradableAndEssential:YES] ? 1 : 0; - if (lhs != rhs) - return lhs ? NSOrderedAscending : NSOrderedDescending; - else if (!lhs) { - switch ([[self seen] compare:[package seen]]) { - case NSOrderedAscending: - return NSOrderedDescending; - case NSOrderedSame: - break; - case NSOrderedDescending: - return NSOrderedAscending; - default: - _assert(false); - } + if ([self upgradableAndEssential:YES]) { + value.bits.timestamp = 0; + value.bits.ignored = [self ignored] ? 0 : 1; + value.bits.upgradable = 1; + } else { + value.bits.timestamp = static_cast([[self seen] timeIntervalSince1970]) >> 2; + value.bits.ignored = 0; + value.bits.upgradable = 0; } - return [self compareByName:package]; + return _not(uint32_t) - value.key; } - (void) install { @@ -1805,6 +1973,13 @@ static NSArray *Finishes_; /* Database Implementation {{{ */ @implementation Database ++ (Database *) sharedInstance { + static Database *instance; + if (instance == nil) + instance = [[Database alloc] init]; + return instance; +} + - (void) dealloc { _assert(false); [super dealloc]; @@ -2352,8 +2527,6 @@ static NSArray *Finishes_; [super dealloc]; } -#include "internals.h" - - (void) mailComposeControllerWillAttemptToSend:(MailComposeController *)controller { NSLog(@"will"); } @@ -2378,6 +2551,9 @@ UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:@"Error" bu } - (void) deliverMessage { _pooled + setuid(501); + setgid(501); + if (![controller_ deliverMessage]) [self performSelectorOnMainThread:@selector(showError) withObject:nil waitUntilDone:NO]; } @@ -2425,6 +2601,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end @interface ConfirmationView : BrowserView { + _transient Database *database_; UIActionSheet *essential_; NSArray *changes_; NSArray *issues_; @@ -2483,7 +2660,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (id) initWithBook:(RVBook *)book database:(Database *)database { - if ((self = [super initWithBook:book database:database]) != nil) { + if ((self = [super initWithBook:book]) != nil) { + database_ = database; + NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16]; NSMutableArray *reinstalling = [NSMutableArray arrayWithCapacity:16]; NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16]; @@ -2573,11 +2752,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } return self; } -// XXX: replace with -- (NSString *) title { - return issues_ == nil ? @"Confirm Changes" : @"Cannot Comply"; -} - - (NSString *) backButtonTitle { return @"Confirm"; } @@ -3196,17 +3370,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (section != nil) section = Simplify(section); - icon_ = nil; - if (NSString *icon = [package icon]) - icon_ = [UIImage imageAtPath:[icon substringFromIndex:6]]; - if (icon_ == nil) if (section != nil) - icon_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]]; - if (icon_ == nil) if (NSString *icon = [source defaultIcon]) - icon_ = [UIImage imageAtPath:[icon substringFromIndex:6]]; - if (icon_ == nil) - icon_ = [UIImage applicationImageNamed:@"unknown.png"]; - - icon_ = [icon_ retain]; + icon_ = [[package icon] retain]; name_ = [[package name] retain]; description_ = [[package tagline] retain]; @@ -3386,7 +3550,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { count_ = [[NSString stringWithFormat:@"%d", [section count]] retain]; if (editing_) - [switch_ setValue:isSectionVisible(section_) animated:NO]; + [switch_ setValue:(isSectionVisible(section_) ? 1 : 0) animated:NO]; } } @@ -3549,6 +3713,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Package View {{{ */ @interface PackageView : BrowserView { + _transient Database *database_; Package *package_; NSString *name_; NSMutableArray *buttons_; @@ -3603,7 +3768,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super webView:sender didClearWindowObject:window forFrame:frame]; } -#if 0 - (void) _rightButtonClicked { /*[super _rightButtonClicked]; return;*/ @@ -3627,7 +3791,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]]; } } -#endif - (NSString *) _rightButtonTitle { int count = [buttons_ count]; @@ -3639,7 +3802,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (id) initWithBook:(RVBook *)book database:(Database *)database { - if ((self = [super initWithBook:book database:database]) != nil) { + if ((self = [super initWithBook:book]) != nil) { database_ = database; buttons_ = [[NSMutableArray alloc] initWithCapacity:4]; } return self; @@ -4248,7 +4411,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sources_ removeAllObjects]; [sources_ addObjectsFromArray:[database_ sources]]; + _trace(); [sources_ sortUsingSelector:@selector(compareByNameAndType:)]; + _trace(); int count = [sources_ count]; for (offset_ = 0; offset_ != count; ++offset_) { @@ -4616,9 +4781,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([href hasPrefix:@"apptapp://package/"]) page = [delegate_ pageForPackage:[href substringFromIndex:18]]; - else if ([scheme isEqualToString:@"cydia"]) + else if ([scheme isEqualToString:@"cydia"]) { page = [delegate_ pageForURL:url hasTag:NULL]; - else if (![scheme isEqualToString:@"apptapp"]) + if (page == nil) + return false; + } else if (![scheme isEqualToString:@"apptapp"]) return false; if (page != nil) @@ -4644,6 +4811,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [listener use]; } +- (void) webView:(WebView *)webView decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { + if ([WebView canShowMIMEType:type]) + [listener use]; + else { + // XXX: handle more mime types! + [listener ignore]; + if (frame == [webView mainFrame]) + [UIApp openURL:[request URL]]; + } +} + - (void) webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { NSURL *url([request URL]); @@ -4667,6 +4845,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { int store(_not(int)); if (NSURL *itms = [url itmsURL:&store]) { + NSLog(@"itms#%@#%u#%@", url, store, itms); if ( store == 1 && [capability containsObject:@"com.apple.MobileStore"] || store == 2 && [capability containsObject:@"com.apple.AppStore"] @@ -4720,7 +4899,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (WebView *) _createWebViewWithRequest:(NSURLRequest *)request pushed:(BOOL)pushed { [self setBackButtonTitle:title_]; - BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease]; + BrowserView *browser = [[[BrowserView alloc] initWithBook:book_] autorelease]; [browser setDelegate:delegate_]; if (pushed) { @@ -4825,9 +5004,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #endif } -- (id) initWithBook:(RVBook *)book database:(Database *)database { +- (id) initWithBook:(RVBook *)book { if ((self = [super initWithBook:book]) != nil) { - database_ = database; loading_ = false; struct CGRect bounds = [self bounds]; @@ -4905,7 +5083,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 12, indsize.width, indsize.height)]; [indicator_ setStyle:UIProgressIndicatorStyleMediumWhite]; - Package *package([database_ packageWithName:@"cydia"]); + Package *package([[Database sharedInstance] packageWithName:@"cydia"]); NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed] @@ -4969,6 +5147,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ +/* Cydia Book {{{ */ @interface CYBook : RVBook < ProgressDelegate > { @@ -4990,112 +5169,413 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end -/* Install View {{{ */ -@interface InstallView : RVPage { - _transient Database *database_; - NSMutableArray *sections_; - NSMutableArray *filtered_; - UITransitionView *transition_; - UITable *list_; - UIView *accessory_; - BOOL editing_; -} - -- (id) initWithBook:(RVBook *)book database:(Database *)database; -- (void) reloadData; -- (void) resetView; - -@end - -@implementation InstallView +@implementation CYBook - (void) dealloc { - [list_ setDataSource:nil]; - [list_ setDelegate:nil]; - - [sections_ release]; - [filtered_ release]; - [transition_ release]; - [list_ release]; - [accessory_ release]; + [overlay_ release]; + [indicator_ release]; + [prompt_ release]; + [progress_ release]; + [cancel_ release]; [super dealloc]; } -- (int) numberOfRowsInTable:(UITable *)table { - return editing_ ? [sections_ count] : [filtered_ count] + 1; +- (NSString *) getTitleForPage:(RVPage *)page { + return Simplify([super getTitleForPage:page]); } -- (float) table:(UITable *)table heightForRow:(int)row { - return 45; +- (BOOL) updating { + return updating_; } -- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing { - if (reusing == nil) - reusing = [[[SectionCell alloc] init] autorelease]; - [(SectionCell *)reusing setSection:(editing_ ? - [sections_ objectAtIndex:row] : - (row == 0 ? nil : [filtered_ objectAtIndex:(row - 1)]) - ) editing:editing_]; - return reusing; -} +- (void) update { + [UIView beginAnimations:nil context:NULL]; -- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row { - return !editing_; -} + CGRect ovrframe = [overlay_ frame]; + ovrframe.origin.y = 0; + [overlay_ setFrame:ovrframe]; -- (BOOL) table:(UITable *)table canSelectRow:(int)row { - return !editing_; + CGRect barframe = [navbar_ frame]; + barframe.origin.y += ovrframe.size.height; + [navbar_ setFrame:barframe]; + + CGRect trnframe = [transition_ frame]; + trnframe.origin.y += ovrframe.size.height; + trnframe.size.height -= ovrframe.size.height; + [transition_ setFrame:trnframe]; + + [UIView endAnimations]; + + [indicator_ startAnimation]; + [prompt_ setText:@"Updating Database"]; + [progress_ setProgress:0]; + + received_ = 0; + last_ = [NSDate timeIntervalSinceReferenceDate]; + updating_ = true; + [overlay_ addSubview:cancel_]; + + [NSThread + detachNewThreadSelector:@selector(_update) + toTarget:self + withObject:nil + ]; } -- (void) tableRowSelected:(NSNotification *)notification { - int row = [[notification object] selectedRow]; - if (row == INT_MAX) - return; +- (void) _update_ { + updating_ = false; - Section *section; - NSString *name; - NSString *title; + [indicator_ stopAnimation]; - if (row == 0) { - section = nil; - name = nil; - title = @"All Packages"; - } else { - section = [filtered_ objectAtIndex:(row - 1)]; - name = [section name]; + [UIView beginAnimations:nil context:NULL]; - if (name != nil) - title = name; - else { - name = @""; - title = @"(No Section)"; - } - } + CGRect ovrframe = [overlay_ frame]; + ovrframe.origin.y = -ovrframe.size.height; + [overlay_ setFrame:ovrframe]; - PackageTable *table = [[[PackageTable alloc] - initWithBook:book_ - database:database_ - title:title - filter:@selector(isVisiblyUninstalledInSection:) - with:name - ] autorelease]; + CGRect barframe = [navbar_ frame]; + barframe.origin.y -= ovrframe.size.height; + [navbar_ setFrame:barframe]; - [table setDelegate:delegate_]; + CGRect trnframe = [transition_ frame]; + trnframe.origin.y -= ovrframe.size.height; + trnframe.size.height += ovrframe.size.height; + [transition_ setFrame:trnframe]; - [book_ pushPage:table]; + [UIView commitAnimations]; + + [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0]; } -- (id) initWithBook:(RVBook *)book database:(Database *)database { - if ((self = [super initWithBook:book]) != nil) { +- (id) initWithFrame:(CGRect)frame database:(Database *)database { + if ((self = [super initWithFrame:frame]) != nil) { database_ = database; - sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; - filtered_ = [[NSMutableArray arrayWithCapacity:16] retain]; + CGRect ovrrect = [navbar_ bounds]; + ovrrect.size.height = [UINavigationBar defaultSize].height; + ovrrect.origin.y = -ovrrect.size.height; - transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]]; - [self addSubview:transition_]; + overlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect]; + [self addSubview:overlay_]; - list_ = [[UITable alloc] initWithFrame:[transition_ bounds]]; + ovrrect.origin.y = frame.size.height; + underlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect]; + [underlay_ setTintColor:[UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1]]; + [self addSubview:underlay_]; + + [overlay_ setBarStyle:1]; + [underlay_ setBarStyle:1]; + + int barstyle = [overlay_ _barStyle:NO]; + bool ugly = barstyle == 0; + + UIProgressIndicatorStyle style = ugly ? + UIProgressIndicatorStyleMediumBrown : + UIProgressIndicatorStyleMediumWhite; + + CGSize indsize = [UIProgressIndicator defaultSizeForStyle:style]; + unsigned indoffset = (ovrrect.size.height - indsize.height) / 2; + CGRect indrect = {{indoffset, indoffset}, indsize}; + + indicator_ = [[UIProgressIndicator alloc] initWithFrame:indrect]; + [indicator_ setStyle:style]; + [overlay_ addSubview:indicator_]; + + CGSize prmsize = {215, indsize.height + 4}; + + CGRect prmrect = {{ + indoffset * 2 + indsize.width, +#ifdef __OBJC2__ + -1 + +#endif + unsigned(ovrrect.size.height - prmsize.height) / 2 + }, prmsize}; + + UIFont *font = [UIFont systemFontOfSize:15]; + + prompt_ = [[UITextLabel alloc] initWithFrame:prmrect]; + + [prompt_ setColor:[UIColor colorWithCGColor:(ugly ? Blueish_ : Off_)]]; + [prompt_ setBackgroundColor:[UIColor clearColor]]; + [prompt_ setFont:font]; + + [overlay_ addSubview:prompt_]; + + CGSize prgsize = {75, 100}; + + CGRect prgrect = {{ + ovrrect.size.width - prgsize.width - 10, + (ovrrect.size.height - prgsize.height) / 2 + } , prgsize}; + + progress_ = [[UIProgressBar alloc] initWithFrame:prgrect]; + [progress_ setStyle:0]; + [overlay_ addSubview:progress_]; + + cancel_ = [[UINavigationButton alloc] initWithTitle:@"Cancel" style:UINavigationButtonStyleHighlighted]; + [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside]; + + CGRect frame = [cancel_ frame]; + frame.size.width = 65; + frame.origin.x = ovrrect.size.width - frame.size.width - 5; + frame.origin.y = (ovrrect.size.height - frame.size.height) / 2; + [cancel_ setFrame:frame]; + + [cancel_ setBarStyle:barstyle]; + } return self; +} + +- (void) _onCancel { + updating_ = false; + [cancel_ removeFromSuperview]; +} + +- (void) _update { _pooled + Status status; + status.setDelegate(self); + + [database_ updateWithStatus:status]; + + [self + performSelectorOnMainThread:@selector(_update_) + withObject:nil + waitUntilDone:NO + ]; +} + +- (void) setProgressError:(NSString *)error forPackage:(NSString *)id { + [prompt_ setText:[NSString stringWithFormat:@"Error: %@", error]]; +} + +- (void) setProgressTitle:(NSString *)title { + [self + performSelectorOnMainThread:@selector(_setProgressTitle:) + withObject:title + waitUntilDone:YES + ]; +} + +- (void) setProgressPercent:(float)percent { + [self + performSelectorOnMainThread:@selector(_setProgressPercent:) + withObject:[NSNumber numberWithFloat:percent] + waitUntilDone:YES + ]; +} + +- (void) startProgress { +} + +- (void) addProgressOutput:(NSString *)output { + [self + performSelectorOnMainThread:@selector(_addProgressOutput:) + withObject:output + waitUntilDone:YES + ]; +} + +- (bool) isCancelling:(size_t)received { + NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; + if (received_ != received) { + received_ = received; + last_ = now; + } else if (now - last_ > 15) + return true; + return !updating_; +} + +- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { + [sheet dismiss]; +} + +- (void) _setProgressTitle:(NSString *)title { + [prompt_ setText:title]; +} + +- (void) _setProgressPercent:(NSNumber *)percent { + [progress_ setProgress:[percent floatValue]]; +} + +- (void) _addProgressOutput:(NSString *)output { +} + +@end +/* }}} */ +/* Cydia:// Protocol {{{ */ +@interface CydiaURLProtocol : NSURLProtocol { +} + +@end + +@implementation CydiaURLProtocol + ++ (BOOL) canInitWithRequest:(NSURLRequest *)request { + NSURL *url([request URL]); + if (url == nil) + return NO; + NSString *scheme([[url scheme] lowercaseString]); + if (scheme == nil || ![scheme isEqualToString:@"cydia"]) + return NO; + return YES; +} + ++ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request { + return request; +} + +- (void) startLoading { + id<NSURLProtocolClient> client([self client]); + NSURLRequest *request([self request]); + + NSURL *url([request URL]); + NSString *href([url absoluteString]); + + NSString *path([href substringFromIndex:8]); + NSRange slash([path rangeOfString:@"/"]); + + NSString *command; + if (slash.location == NSNotFound) { + command = path; + path = nil; + } else { + command = [path substringToIndex:slash.location]; + path = [path substringFromIndex:(slash.location + 1)]; + } + + Database *database([Database sharedInstance]); + + if ([command isEqualToString:@"package-icon"]) { + if (path == nil) + goto fail; + Package *package([database packageWithName:path]); + if (package == nil) + goto fail; + + NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil] autorelease]); + + UIImage *icon([package icon]); + NSData *data(UIImagePNGRepresentation(icon)); + + [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + [client URLProtocol:self didLoadData:data]; + [client URLProtocolDidFinishLoading:self]; + } else fail: { + [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]]; + } +} + +- (void) stopLoading { +} + +@end +/* }}} */ + +/* Install View {{{ */ +@interface InstallView : RVPage { + _transient Database *database_; + NSMutableArray *sections_; + NSMutableArray *filtered_; + UITransitionView *transition_; + UITable *list_; + UIView *accessory_; + BOOL editing_; +} + +- (id) initWithBook:(RVBook *)book database:(Database *)database; +- (void) reloadData; +- (void) resetView; + +@end + +@implementation InstallView + +- (void) dealloc { + [list_ setDataSource:nil]; + [list_ setDelegate:nil]; + + [sections_ release]; + [filtered_ release]; + [transition_ release]; + [list_ release]; + [accessory_ release]; + [super dealloc]; +} + +- (int) numberOfRowsInTable:(UITable *)table { + return editing_ ? [sections_ count] : [filtered_ count] + 1; +} + +- (float) table:(UITable *)table heightForRow:(int)row { + return 45; +} + +- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing { + if (reusing == nil) + reusing = [[[SectionCell alloc] init] autorelease]; + [(SectionCell *)reusing setSection:(editing_ ? + [sections_ objectAtIndex:row] : + (row == 0 ? nil : [filtered_ objectAtIndex:(row - 1)]) + ) editing:editing_]; + return reusing; +} + +- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row { + return !editing_; +} + +- (BOOL) table:(UITable *)table canSelectRow:(int)row { + return !editing_; +} + +- (void) tableRowSelected:(NSNotification *)notification { + int row = [[notification object] selectedRow]; + if (row == INT_MAX) + return; + + Section *section; + NSString *name; + NSString *title; + + if (row == 0) { + section = nil; + name = nil; + title = @"All Packages"; + } else { + section = [filtered_ objectAtIndex:(row - 1)]; + name = [section name]; + + if (name != nil) + title = name; + else { + name = @""; + title = @"(No Section)"; + } + } + + PackageTable *table = [[[PackageTable alloc] + initWithBook:book_ + database:database_ + title:title + filter:@selector(isVisiblyUninstalledInSection:) + with:name + ] autorelease]; + + [table setDelegate:delegate_]; + + [book_ pushPage:table]; +} + +- (id) initWithBook:(RVBook *)book database:(Database *)database { + if ((self = [super initWithBook:book]) != nil) { + database_ = database; + + sections_ = [[NSMutableArray arrayWithCapacity:16] retain]; + filtered_ = [[NSMutableArray arrayWithCapacity:16] retain]; + + transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]]; + [self addSubview:transition_]; + + list_ = [[UITable alloc] initWithFrame:[transition_ bounds]]; [transition_ transition:0 toView:list_]; UITableColumn *column = [[[UITableColumn alloc] @@ -5126,6 +5606,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSMutableArray *filtered = [NSMutableArray arrayWithCapacity:[packages count]]; NSMutableDictionary *sections = [NSMutableDictionary dictionaryWithCapacity:32]; + _trace(); for (size_t i(0); i != [packages count]; ++i) { Package *package([packages objectAtIndex:i]); NSString *name([package section]); @@ -5141,11 +5622,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([package valid] && [package installed] == nil && [package visible]) [filtered addObject:package]; } + _trace(); [sections_ addObjectsFromArray:[sections allValues]]; [sections_ sortUsingSelector:@selector(compareByName:)]; + _trace(); [filtered sortUsingSelector:@selector(compareBySection:)]; + _trace(); Section *section = nil; for (size_t offset = 0, count = [filtered count]; offset != count; ++offset) { @@ -5161,8 +5645,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [section addToCount]; } + _trace(); [list_ reloadData]; + _trace(); } - (void) resetView { @@ -5177,10 +5663,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) _rightButtonClicked { if ((editing_ = !editing_)) [list_ reloadData]; - else { + else [delegate_ updateData]; - } - [book_ reloadTitleForPage:self]; [book_ reloadButtonsForPage:self]; } @@ -5323,6 +5807,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [packages_ removeAllObjects]; [sections_ removeAllObjects]; + _trace(); for (size_t i(0); i != [packages count]; ++i) { Package *package([packages objectAtIndex:i]); @@ -5333,43 +5818,46 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [packages_ addObject:package]; } - [packages_ sortUsingSelector:@selector(compareForChanges:)]; + _trace(); + [packages_ radixUsingSelector:@selector(compareForChanges) withObject:nil]; + _trace(); Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades"] autorelease]; + Section *ignored = [[[Section alloc] initWithName:@"Ignored Upgrades"] autorelease]; Section *section = nil; + NSDate *last = nil; upgrades_ = 0; bool unseens = false; CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); + _trace(); for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) { Package *package = [packages_ objectAtIndex:offset]; - if ([package upgradableAndEssential:YES]) { - ++upgrades_; - [upgradable addToCount]; - } else { + if (![package upgradableAndEssential:YES]) { unseens = true; NSDate *seen = [package seen]; - NSString *name; + if (section == nil || last != seen && (seen == nil || [seen compare:last] != NSOrderedSame)) { + last = seen; - if (seen == nil) - name = [@"n/a ?" retain]; - else { - name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen); - } - - if (section == nil || ![[section name] isEqualToString:name]) { + NSString *name(seen == nil ? [@"n/a ?" retain] : (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen)); section = [[[Section alloc] initWithName:name row:offset] autorelease]; [sections_ addObject:section]; + [name release]; } - [name release]; [section addToCount]; + } else if ([package ignored]) + [ignored addToCount]; + else { + ++upgrades_; + [upgradable addToCount]; } } + _trace(); CFRelease(formatter); @@ -5380,6 +5868,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sections_ removeLastObject]; } + if ([ignored count] != 0) + [sections_ insertObject:ignored atIndex:0]; if (upgrades_ != 0) [sections_ insertObject:upgradable atIndex:0]; @@ -5667,237 +6157,236 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ -@implementation CYBook - -- (void) dealloc { - [overlay_ release]; - [indicator_ release]; - [prompt_ release]; - [progress_ release]; - [cancel_ release]; - [super dealloc]; -} - -- (NSString *) getTitleForPage:(RVPage *)page { - return Simplify([super getTitleForPage:page]); -} - -- (BOOL) updating { - return updating_; +@interface SettingsView : RVPage { + _transient Database *database_; + NSString *name_; + Package *package_; + UIPreferencesTable *table_; + _UISwitchSlider *subscribedSwitch_; + _UISwitchSlider *ignoredSwitch_; + UIPreferencesControlTableCell *subscribedCell_; + UIPreferencesControlTableCell *ignoredCell_; } -- (void) update { - [UIView beginAnimations:nil context:NULL]; - - CGRect ovrframe = [overlay_ frame]; - ovrframe.origin.y = 0; - [overlay_ setFrame:ovrframe]; +- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package; - CGRect barframe = [navbar_ frame]; - barframe.origin.y += ovrframe.size.height; - [navbar_ setFrame:barframe]; +@end - CGRect trnframe = [transition_ frame]; - trnframe.origin.y += ovrframe.size.height; - trnframe.size.height -= ovrframe.size.height; - [transition_ setFrame:trnframe]; +@implementation SettingsView - [UIView endAnimations]; +- (void) dealloc { + [table_ setDataSource:nil]; - [indicator_ startAnimation]; - [prompt_ setText:@"Updating Database"]; - [progress_ setProgress:0]; + [name_ release]; + if (package_ != nil) + [package_ release]; + [table_ release]; + [subscribedSwitch_ release]; + [ignoredSwitch_ release]; + [subscribedCell_ release]; + [ignoredCell_ release]; + [super dealloc]; +} - received_ = 0; - last_ = [NSDate timeIntervalSinceReferenceDate]; - updating_ = true; - [overlay_ addSubview:cancel_]; +- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table { + if (package_ == nil) + return 0; - [NSThread - detachNewThreadSelector:@selector(_update) - toTarget:self - withObject:nil - ]; + return 2; } -- (void) _update_ { - updating_ = false; +- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group { + if (package_ == nil) + return nil; - [indicator_ stopAnimation]; + switch (group) { + case 0: return nil; + case 1: return nil; - [UIView beginAnimations:nil context:NULL]; + default: _assert(false); + } - CGRect ovrframe = [overlay_ frame]; - ovrframe.origin.y = -ovrframe.size.height; - [overlay_ setFrame:ovrframe]; + return nil; +} - CGRect barframe = [navbar_ frame]; - barframe.origin.y -= ovrframe.size.height; - [navbar_ setFrame:barframe]; +- (BOOL) preferencesTable:(UIPreferencesTable *)table isLabelGroup:(int)group { + if (package_ == nil) + return NO; - CGRect trnframe = [transition_ frame]; - trnframe.origin.y -= ovrframe.size.height; - trnframe.size.height += ovrframe.size.height; - [transition_ setFrame:trnframe]; + switch (group) { + case 0: return NO; + case 1: return YES; - [UIView commitAnimations]; + default: _assert(false); + } - [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0]; + return NO; } -- (id) initWithFrame:(CGRect)frame database:(Database *)database { - if ((self = [super initWithFrame:frame]) != nil) { - database_ = database; +- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group { + if (package_ == nil) + return 0; - CGRect ovrrect = [navbar_ bounds]; - ovrrect.size.height = [UINavigationBar defaultSize].height; - ovrrect.origin.y = -ovrrect.size.height; + switch (group) { + case 0: return 1; + case 1: return 1; - overlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect]; - [self addSubview:overlay_]; + default: _assert(false); + } - ovrrect.origin.y = frame.size.height; - underlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect]; - [underlay_ setTintColor:[UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1]]; - [self addSubview:underlay_]; + return 0; +} - [overlay_ setBarStyle:1]; - [underlay_ setBarStyle:1]; +- (void) onSomething:(UIPreferencesControlTableCell *)cell withKey:(NSString *)key { + if (package_ == nil) + return; - int barstyle = [overlay_ _barStyle:NO]; - bool ugly = barstyle == 0; + _UISwitchSlider *slider([cell control]); + // XXX: this is just weird + BOOL value([slider value] != 0); + NSMutableDictionary *metadata([package_ metadata]); - UIProgressIndicatorStyle style = ugly ? - UIProgressIndicatorStyleMediumBrown : - UIProgressIndicatorStyleMediumWhite; + BOOL before; + if (NSNumber *number = [metadata objectForKey:key]) + before = [number boolValue]; + else + before = NO; + NSLog(@"%@:%@ %@:%@ : %u:%u", cell, slider, name_, key, value, before); - CGSize indsize = [UIProgressIndicator defaultSizeForStyle:style]; - unsigned indoffset = (ovrrect.size.height - indsize.height) / 2; - CGRect indrect = {{indoffset, indoffset}, indsize}; + if (value != before) { + [metadata setObject:[NSNumber numberWithBool:value] forKey:key]; + Changed_ = true; + //[delegate_ performSelector:@selector(updateData) withObject:nil afterDelay:0]; + [delegate_ updateData]; + } +} - indicator_ = [[UIProgressIndicator alloc] initWithFrame:indrect]; - [indicator_ setStyle:style]; - [overlay_ addSubview:indicator_]; +- (void) onSubscribed:(UIPreferencesControlTableCell *)cell { + [self onSomething:cell withKey:@"IsSubscribed"]; +} - CGSize prmsize = {215, indsize.height + 4}; +- (void) onIgnored:(UIPreferencesControlTableCell *)cell { + [self onSomething:cell withKey:@"IsIgnored"]; +} - CGRect prmrect = {{ - indoffset * 2 + indsize.width, -#ifdef __OBJC2__ - -1 + -#endif - unsigned(ovrrect.size.height - prmsize.height) / 2 - }, prmsize}; +- (id) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group { + if (package_ == nil) + return nil; - UIFont *font = [UIFont systemFontOfSize:15]; + switch (group) { + case 0: switch (row) { + case 0: + return subscribedCell_; + case 1: + return ignoredCell_; + default: _assert(false); + } break; + + case 1: switch (row) { + case 0: { + UIPreferencesControlTableCell *cell([[[UIPreferencesControlTableCell alloc] init] autorelease]); + [cell setTitle:@"Changes only shows upgrades to installed packages. This minimizes spam from packagers. Activate this to see upgrades to this package even when it is not installed."]; + return cell; + } - prompt_ = [[UITextLabel alloc] initWithFrame:prmrect]; + default: _assert(false); + } break; - [prompt_ setColor:[UIColor colorWithCGColor:(ugly ? Blueish_ : Off_)]]; - [prompt_ setBackgroundColor:[UIColor clearColor]]; - [prompt_ setFont:font]; + default: _assert(false); + } - [overlay_ addSubview:prompt_]; + return nil; +} - CGSize prgsize = {75, 100}; +- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package { + if ((self = [super initWithBook:book])) { + database_ = database; + name_ = [package retain]; - CGRect prgrect = {{ - ovrrect.size.width - prgsize.width - 10, - (ovrrect.size.height - prgsize.height) / 2 - } , prgsize}; + table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]]; + [self addSubview:table_]; - progress_ = [[UIProgressBar alloc] initWithFrame:prgrect]; - [progress_ setStyle:0]; - [overlay_ addSubview:progress_]; + subscribedSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)]; + [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:kUIControlEventMouseUpInside]; - cancel_ = [[UINavigationButton alloc] initWithTitle:@"Cancel" style:UINavigationButtonStyleHighlighted]; - [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside]; + ignoredSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)]; + [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:kUIControlEventMouseUpInside]; - CGRect frame = [cancel_ frame]; - frame.size.width = 65; - frame.origin.x = ovrrect.size.width - frame.size.width - 5; - frame.origin.y = (ovrrect.size.height - frame.size.height) / 2; - [cancel_ setFrame:frame]; + subscribedCell_ = [[UIPreferencesControlTableCell alloc] init]; + [subscribedCell_ setTitle:@"Show All Changes"]; + [subscribedCell_ setControl:subscribedSwitch_]; - [cancel_ setBarStyle:barstyle]; + ignoredCell_ = [[UIPreferencesControlTableCell alloc] init]; + [ignoredCell_ setTitle:@"Ignore Upgrades"]; + [ignoredCell_ setControl:ignoredSwitch_]; + + [table_ setDataSource:self]; + [self reloadData]; } return self; } -- (void) _onCancel { - updating_ = false; - [cancel_ removeFromSuperview]; +- (void) resetViewAnimated:(BOOL)animated { + [table_ resetViewAnimated:animated]; } -- (void) _update { _pooled - Status status; - status.setDelegate(self); - - [database_ updateWithStatus:status]; +- (void) reloadData { + if (package_ != nil) + [package_ autorelease]; + package_ = [database_ packageWithName:name_]; + if (package_ != nil) { + [package_ retain]; + [subscribedSwitch_ setValue:([package_ subscribed] ? 1 : 0) animated:NO]; + [ignoredSwitch_ setValue:([package_ ignored] ? 1 : 0) animated:NO]; + } - [self - performSelectorOnMainThread:@selector(_update_) - withObject:nil - waitUntilDone:NO - ]; + [table_ reloadData]; } -- (void) setProgressError:(NSString *)error forPackage:(NSString *)id { - [prompt_ setText:[NSString stringWithFormat:@"Error: %@", error]]; +- (NSString *) title { + return @"Settings"; } -- (void) setProgressTitle:(NSString *)title { - [self - performSelectorOnMainThread:@selector(_setProgressTitle:) - withObject:title - waitUntilDone:YES - ]; -} +@end -- (void) setProgressPercent:(float)percent { - [self - performSelectorOnMainThread:@selector(_setProgressPercent:) - withObject:[NSNumber numberWithFloat:percent] - waitUntilDone:YES - ]; +/* Signature View {{{ */ +@interface SignatureView : BrowserView { + _transient Database *database_; + NSString *package_; } -- (void) startProgress { -} +- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package; -- (void) addProgressOutput:(NSString *)output { - [self - performSelectorOnMainThread:@selector(_addProgressOutput:) - withObject:output - waitUntilDone:YES - ]; -} +@end -- (bool) isCancelling:(size_t)received { - NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; - if (received_ != received) { - received_ = received; - last_ = now; - } else if (now - last_ > 15) - return true; - return !updating_; +@implementation SignatureView + +- (void) dealloc { + [package_ release]; + [super dealloc]; } -- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { - [sheet dismiss]; +- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { + // XXX: dude! + [super webView:sender didClearWindowObject:window forFrame:frame]; } -- (void) _setProgressTitle:(NSString *)title { - [prompt_ setText:title]; +- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package { + if ((self = [super initWithBook:book]) != nil) { + database_ = database; + package_ = [package retain]; + [self reloadData]; + } return self; } -- (void) _setProgressPercent:(NSNumber *)percent { - [progress_ setProgress:[percent floatValue]]; +- (void) resetViewAnimated:(BOOL)animated { } -- (void) _addProgressOutput:(NSString *)output { +- (void) reloadData { + [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"signature" ofType:@"html"]]]; } @end +/* }}} */ @interface Cydia : UIApplication < ConfirmationViewDelegate, @@ -5978,7 +6467,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [overlay_ addSubview:hud]; [hud show:YES];*/ + _trace(); [database_ reloadData]; + _trace(); size_t changes(0); @@ -6029,7 +6520,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) _saveConfig { if (Changed_) { + _trace(); _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES); + _trace(); Changed_ = false; } } @@ -6038,11 +6531,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _saveConfig]; /* XXX: this is just stupid */ - if (tag_ != 2) + if (tag_ != 2 && install_ != nil) [install_ reloadData]; - if (tag_ != 3) + if (tag_ != 3 && changes_ != nil) [changes_ reloadData]; - if (tag_ != 5) + if (tag_ != 5 && search_ != nil) [search_ reloadData]; [book_ reloadData]; @@ -6186,7 +6679,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (RVPage *) _pageForURL:(NSURL *)url withClass:(Class)_class { - BrowserView *browser = [[[_class alloc] initWithBook:book_ database:database_] autorelease]; + BrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease]; [browser loadURL:url]; return browser; } @@ -6357,6 +6850,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [[UIKeyboardImpl sharedInstance] setSoundsEnabled:(Sounds_Keyboard_ ? YES : NO)]; [overlay_ addSubview:keyboard_]; + if (!bootstrap_) + [underlay_ addSubview:overlay_]; + + [self reloadData]; + install_ = [[InstallView alloc] initWithBook:book_ database:database_]; changes_ = [[ChangesView alloc] initWithBook:book_ database:database_]; search_ = [[SearchView alloc] initWithBook:book_ database:database_]; @@ -6366,11 +6864,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { withClass:[ManageView class] ] retain]; - if (!bootstrap_) - [underlay_ addSubview:overlay_]; - - [self reloadData]; - if (bootstrap_) [self bootstrap]; else @@ -6489,7 +6982,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) openMailToURL:(NSURL *)url { +// XXX: this makes me sad +#if 0 [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease]; +#else + [UIApp openURL:url]; +#endif } - (RVPage *) pageForPackage:(NSString *)name { @@ -6531,6 +7029,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [self _pageForURL:[NSURL URLWithString:[href substringFromIndex:12]] withClass:[BrowserView class]]; else if ([href hasPrefix:@"cydia://launch/"]) [self launchApplicationWithIdentifier:[href substringFromIndex:15] suspended:NO]; + else if ([href hasPrefix:@"cydia://package-settings/"]) + return [[[SettingsView alloc] initWithBook:book_ database:database_ package:[href substringFromIndex:25]] autorelease]; + else if ([href hasPrefix:@"cydia://package-signature/"]) + return [[[SignatureView alloc] initWithBook:book_ database:database_ package:[href substringFromIndex:26]] autorelease]; else if ([href hasPrefix:@"cydia://package/"]) return [self pageForPackage:[href substringFromIndex:16]]; else if ([href hasPrefix:@"cydia://files/"]) { @@ -6571,6 +7073,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { essential_ = [[NSMutableArray alloc] initWithCapacity:4]; broken_ = [[NSMutableArray alloc] initWithCapacity:4]; + [NSURLProtocol registerClass:[CydiaURLProtocol class]]; + CGRect screenrect = [UIHardware fullScreenApplicationContentRect]; window_ = [[UIWindow alloc] initWithContentRect:screenrect]; @@ -6578,7 +7082,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [window_ makeKey:self]; [window_ setHidden:NO]; - database_ = [[Database alloc] init]; + database_ = [Database sharedInstance]; progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] database:database_ delegate:self]; [database_ setDelegate:progress_]; [window_ setContentView:progress_]; @@ -6621,7 +7125,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } + (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { - NSLog(@"exc:%s", sel_getName(selector)); return selector != @selector(supports:); }