]> git.saurik.com Git - cydia.git/commitdiff
Merge commit '664d95c4bf793f6206d94a366caf31c90cd9fd00' into tab-backup
authorGrant Paul <chpwn@chpwn.com>
Sun, 23 Jan 2011 00:18:08 +0000 (16:18 -0800)
committerGrant Paul <chpwn@chpwn.com>
Sun, 23 Jan 2011 00:18:08 +0000 (16:18 -0800)
1  2 
MobileCydia.mm

diff --combined MobileCydia.mm
index c1324aab7fb3a292838588285bb06dfba4c3a383,6cbb164740018c76ee7432124180f497d489b122..44b2c1cfccdd4e68664f3818c4e83458b2ea10c1
@@@ -1179,12 -1179,12 +1179,12 @@@ bool isSectionVisible(NSString *section
  - (void) setConfigurationData:(NSString *)data;
  @end
  
 -@class PackageController;
 +@class CYPackageController;
  
  @protocol CydiaDelegate
  - (void) retainNetworkActivityIndicator;
  - (void) releaseNetworkActivityIndicator;
 -- (void) setPackageController:(PackageController *)view;
 +- (void) setPackageController:(CYPackageController *)view;
  - (void) clearPackage:(Package *)package;
  - (void) installPackage:(Package *)package;
  - (void) installPackages:(NSArray *)packages;
  - (UIProgressHUD *) addProgressHUD;
  - (void) removeProgressHUD:(UIProgressHUD *)hud;
  - (CYViewController *) pageForPackage:(NSString *)name;
 -- (PackageController *) packageController;
  - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
  @end
  
@@@ -4044,45 -4045,6 +4044,45 @@@ bool DepSubstrate(const pkgCache::VerIt
  - (UILabel *)label { return label_; }
  - (UIActivityIndicatorView *)activityIndicatorView { return spinner_; }
  
 +@end
 +/* }}} */
 +/* Emulated Loading Controller {{{ */
 +@interface CYEmulatedLoadingController : UIViewController {
 +    CYLoadingIndicator *indicator_;
 +    UITabBar *tabbar_;
 +    UINavigationBar *navbar_;
 +}
 +@end
 +
 +@implementation CYEmulatedLoadingController
 +
 +- (CYEmulatedLoadingController *) init {
 +    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];
 +    } return self;
 +}
 +
 +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
 +    return (IsWildcat_ || orientation == UIInterfaceOrientationPortrait);
 +}
 +
  @end
  /* }}} */
  
  @end
  /* }}} */
  /* Package Controller {{{ */
 -@interface PackageController : CYBrowserController <
 +@interface CYPackageController : CYBrowserController <
      UIActionSheetDelegate
  > {
      _transient Database *database_;
  
  @end
  
 -@implementation PackageController
 +@implementation CYPackageController
  
  - (void) dealloc {
      if (package_ != nil)
  }
  
  - (void) didSelectPackage:(Package *)package {
 -    PackageController *view([delegate_ packageController]);
 +    CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]);
      [view setPackage:package];
      [view setDelegate:delegate_];
      [[self navigationController] pushViewController:view animated:YES];
  > {
      UIImage *icon_;
      NSString *origin_;
-     NSString *description_;
      NSString *label_;
  }
  
  - (void) clearSource {
      [icon_ release];
      [origin_ release];
-     [description_ release];
      [label_ release];
  
      icon_ = nil;
      origin_ = nil;
-     description_ = nil;
      label_ = nil;
  }
  
  
      origin_ = [[source name] retain];
      label_ = [[source uri] retain];
-     description_ = [[source description] retain];
  
      [content_ setNeedsDisplay];
  }
      if (!highlighted)
          UISetColor(Blue_);
      [label_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation];
-     if (!highlighted)
-         UISetColor(Gray_);
-     [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 40) withFont:Font14_ lineBreakMode:UILineBreakModeTailTruncation];
  }
  
  @end
  /* }}} */
  /* Source Table {{{ */
 -@interface SourceController : CYViewController <
 +@interface SourcesController : CYViewController <
      UITableViewDataSource,
      UITableViewDelegate
  > {
  
  @end
  
 -@implementation SourceController
 +@implementation SourcesController
  
  - (void) _releaseConnection:(NSURLConnection *)connection {
      if (connection != nil) {
      return [sources_ objectAtIndex:idx];
  }
  
- - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
-     Source *source = [self sourceAtIndexPath:indexPath];
-     return [source description] == nil ? 56 : 73;
- }
  - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      static NSString *cellIdentifier = @"SourceCell";
  
  
          list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
          [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+         [list_ setRowHeight:56];
          [[self view] addSubview:list_];
  
          [list_ setDataSource:self];
      [list_ reloadData];
  }
  
 -- (void) addButtonClicked {
 -    /*[book_ pushPage:[[[AddSourceController alloc]
 -        initWithBook:book_
 -        database:database_
 -    ] autorelease]];*/
 -
 +- (void) showAddSourcePrompt {
      UIAlertView *alert = [[[UIAlertView alloc]
          initWithTitle:UCLocalize("ENTER_APT_URL")
          message:nil
      [alert show];
  }
  
 +- (void) addButtonClicked {
 +    [self showAddSourcePrompt];
 +}
 +
  - (void) updateButtonsForEditingStatus:(BOOL)editing animated:(BOOL)animated {
      [[self navigationItem] setLeftBarButtonItem:(editing ? [[[UIBarButtonItem alloc]
          initWithTitle:UCLocalize("ADD")
      [packages_ setDelegate:delegate];
  }
  
 +@end
 +/* }}} */
 +/* Section Controller {{{ */
 +@interface CYSectionController : FilteredPackageController {
 +}
 +
 +- (id) initWithDatabase:(Database *)database section:(NSString *)section;
 +
 +@end
 +
 +@implementation CYSectionController
 +
 +- (void) dealloc {
 +    [super dealloc];
 +}
 +
 +- (id) initWithDatabase:(Database *)database section:(NSString *)name {
 +    NSString *title;
 +
 +    if (name == nil) {
 +        title = UCLocalize("ALL_PACKAGES");
 +    } else if (![name isEqual:@""]) {
 +        title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"];
 +    } else {
 +        title = UCLocalize("NO_SECTION");
 +    }
 +
 +    if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:) with:name]) != nil) {
 +    } 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
  
  - (id) init {
      if ((self = [super init]) != nil) {
 +        [self loadURL:[NSURL URLWithString:CydiaURL(@"")]];
 +
          [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
              initWithTitle:UCLocalize("ABOUT")
              style:UIBarButtonItemStylePlain
      if ((self = [super init]) != nil) {
          [[self navigationItem] setTitle:UCLocalize("MANAGE")];
  
 +        [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]];
 +
          [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
              initWithTitle:UCLocalize("SETTINGS")
              style:UIBarButtonItemStylePlain
  
  @implementation CYTabBarController
  
 -/* XXX: some logic should probably go here related to
 -freeing the view controllers on tab change */
 -
  - (void) reloadData {
      size_t count([[self viewControllers] count]);
      for (size_t i(0); i != count; ++i) {
  @end
  /* }}} */
  
 +/* Section Controller {{{ */
 +@interface SectionController : FilteredPackageController {
 +}
 +
 +- (id) initWithDatabase:(Database *)database section:(NSString *)section;
 +
 +@end
 +
 +@implementation SectionController
 +
 +- (void) dealloc {
 +    [super dealloc];
 +}
 +
 +- (id) initWithDatabase:(Database *)database section:(NSString *)name {
 +    NSString *title;
 +
 +    if (name == nil) {
 +        title = UCLocalize("ALL_PACKAGES");
 +    } else if (![name isEqual:@""]) {
 +        title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"];
 +    } else {
 +        title = UCLocalize("NO_SECTION");
 +    }
 +
 +    if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:) with:name]) != nil) {
 +    } return self;
 +}
 +
 +- (void) reloadData {
 +    [packages_ reloadData];
 +}
 +
 +- (void) setDelegate:(id)delegate {
 +    [super setDelegate:delegate];
 +    [packages_ setDelegate:delegate];
 +}
 +
 +@end
 +/* }}} */
  /* Sections Controller {{{ */
 -@interface CYSectionsController : CYViewController <
 +@interface SectionsController : CYViewController <
      UITableViewDataSource,
      UITableViewDelegate
  > {
  
  @end
  
 -@implementation CYSectionsController
 +@implementation SectionsController
  
  - (void) dealloc {
      [list_ setDataSource:nil];
          return;
  
      Section *section = [self sectionAtIndexPath:indexPath];
 -    NSString *name = [section name];
 -    NSString *title;
 -
 -    if ([indexPath row] == 0) {
 -        section = nil;
 -        name = nil;
 -        title = UCLocalize("ALL_PACKAGES");
 -    } else {
 -        if (name != nil) {
 -            name = [NSString stringWithString:name];
 -            title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"];
 -        } else {
 -            name = @"";
 -            title = UCLocalize("NO_SECTION");
 -        }
 -    }
  
 -    FilteredPackageController *table = [[[FilteredPackageController alloc]
 +    SectionController *controller = [[[SectionController alloc]
          initWithDatabase:database_
 -        title:title
 -        filter:@selector(isVisibleInSection:)
 -        with:name
 +        section:[section name]
      ] autorelease];
 +    [controller setDelegate:delegate_];
  
 -    [table setDelegate:delegate_];
 -
 -    [[self navigationController] pushViewController:table animated:YES];
 +    [[self navigationController] pushViewController:controller animated:YES];
  }
  
 -- (NSString *) title { return UCLocalize("SECTIONS"); }
 -
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
  
  @end
  /* }}} */
 +
  /* Changes Controller {{{ */
  @interface ChangesController : CYViewController <
      UITableViewDataSource,
  
  - (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
      Package *package([self packageAtIndexPath:path]);
 -    PackageController *view([delegate_ packageController]);
 +    CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]);
      [view setDelegate:delegate_];
      [view setPackage:package];
      [[self navigationController] pushViewController:view animated:YES];
  }
  
  - (id) initWithDatabase:(Database *)database;
 +- (void) setSearchTerm:(NSString *)term;
  - (void) reloadData;
  
  @end
      [super dealloc];
  }
  
 +- (void) setSearchTerm:(NSString *)searchTerm {
 +    [search_ setText:searchTerm];
 +}
 +
  - (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
      [packages_ setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
      [search_ resignFirstResponder];
      [self reloadData];
  }
  
 -- (NSString *) title { return nil; }
 -
  - (id) initWithDatabase:(Database *)database {
      return [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil];
  }
  @end
  /* }}} */
  /* Settings Controller {{{ */
 -@interface CYPackageSettingsController : CYViewController <
 +@interface PackageSettingsController : CYViewController <
      UITableViewDataSource,
      UITableViewDelegate
  > {
  
  @end
  
 -@implementation CYPackageSettingsController
 +@implementation PackageSettingsController
  
  - (void) dealloc {
      [name_ release];
      return 2;
  }
  
 +- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
 +    return UCLocalize("CHANGE_PACKAGE_SETTINGS");
 +}
 +
  - (NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
      return UCLocalize("SHOW_ALL_CHANGES_EX");
  }
          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];
  
          subscribedCell_ = [[UITableViewCell alloc] init];
          [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")];
  @end
  /* }}} */
  
 -typedef enum {
 -    kCydiaTag = 0,
 -    kSectionsTag = 1,
 -    kChangesTag = 2,
 -    kManageTag = 3,
 -    kInstalledTag = 4,
 -    kSourcesTag = 5,
 -    kSearchTag = 6
 -} CYTabTag;
 -
  @interface Cydia : UIApplication <
      ConfirmationControllerDelegate,
      ProgressControllerDelegate,
      Database *database_;
  
      NSURL *starturl_;
 -    int tag_;
  
      unsigned locked_;
      unsigned activity_;
  
 -    CYSectionsController *sections_;
 -    ChangesController *changes_;
 -    ManageController *manage_;
 -    SearchController *search_;
 -    SourceController *sources_;
 -    InstalledController *installed_;
 -    id queueDelegate_;
 -
      CYStashController *stash_;
  
      bool loaded_;
  }
  
 -- (CYViewController *) _pageForURL:(NSURL *)url withClass:(Class)_class;
  - (void) setPage:(CYViewController *)page;
  - (void) loadData;
  
 -// XXX: I hate prototypes
 -- (id) queueBadgeController;
 -
  @end
  
 -static _finline void _setHomePage(Cydia *self) {
 -    [self setPage:[self _pageForURL:[NSURL URLWithString:CydiaURL(@"")] withClass:[HomeController class]]];
 -}
 -
  @implementation Cydia
  
  - (void) beginUpdate {
      }
  }
  
 +// Navigation controller for the queuing badge.
 +- (CYNavigationController *) queueNavigationController {
 +    NSArray *controllers = [tabbar_ viewControllers];
 +    return [controllers objectAtIndex:3];
 +}
 +
  - (void) _updateData {
      [self _saveConfig];
  
 -    NSMutableSet *tabs([[[NSMutableSet alloc] initWithCapacity:10] autorelease]);
 -
 -    [tabs addObject:[tabbar_ selectedViewController]];
 +    [tabbar_ reloadData];
  
 -    if (sections_ != nil)
 -        [tabs addObject:sections_];
 -    if (changes_ != nil)
 -        [tabs addObject:changes_];
 -    if (manage_ != nil)
 -        [tabs addObject:manage_];
 -    if (search_ != nil)
 -        [tabs addObject:search_];
 -    if (sources_ != nil)
 -        [tabs addObject:sources_];
 -    if (installed_ != nil)
 -        [tabs addObject:installed_];
 +    CYNavigationController *navigation = [self queueNavigationController];
  
 -    for (CYNavigationController *tab in tabs)
 -        [tab reloadData];
 +    id queuedelegate = nil;
 +    if ([[navigation viewControllers] count] > 0)
 +        queuedelegate = [[navigation viewControllers] objectAtIndex:0];
  
 -    [queueDelegate_ queueStatusDidChange];
 -    [[[self queueBadgeController] tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
 -}
 -
 -- (int)indexOfTabWithTag:(int)tag {
 -    int i = 0;
 -    for (UINavigationController *controller in [tabbar_ viewControllers]) {
 -        if ([[controller tabBarItem] tag] == tag)
 -            return i;
 -        i += 1;
 -    }
 -
 -    return -1;
 +    [queuedelegate queueStatusDidChange];
 +    [[navigation tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
  }
  
  - (void) _refreshIfPossible {
  
      NSLog(@"changes:#%u", changes);
  
 -    UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem];
 +    UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem];
      if (changes != 0) {
          _trace();
          NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
              [page setViewControllers:nil];
  }
  
 -- (CYViewController *) _pageForURL:(NSURL *)url withClass:(Class)_class {
 -    CYBrowserController *browser = [[[_class alloc] init] autorelease];
 -    [browser loadURL:url];
 -    return browser;
 -}
 -
 -- (CYSectionsController *) sectionsController {
 -    if (sections_ == nil)
 -        sections_ = [[CYSectionsController alloc] initWithDatabase:database_];
 -    return sections_;
 -}
 -
 -- (ChangesController *) changesController {
 -    if (changes_ == nil)
 -        changes_ = [[ChangesController alloc] initWithDatabase:database_ delegate:self];
 -    return changes_;
 -}
 -
 -- (ManageController *) manageController {
 -    if (manage_ == nil) {
 -        manage_ = (ManageController *) [[self
 -            _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]
 -            withClass:[ManageController class]
 -        ] retain];
 -        if (!IsWildcat_)
 -            queueDelegate_ = manage_;
 -    }
 -    return manage_;
 -}
 -
 -- (SearchController *) searchController {
 -    if (search_ == nil)
 -        search_ = [[SearchController alloc] initWithDatabase:database_];
 -    return search_;
 -}
 -
 -- (SourceController *) sourcesController {
 -    if (sources_ == nil)
 -        sources_ = [[SourceController alloc] initWithDatabase:database_];
 -    return sources_;
 -}
 -
 -- (InstalledController *) installedController {
 -    if (installed_ == nil) {
 -        installed_ = [[InstalledController alloc] initWithDatabase:database_];
 -        if (IsWildcat_)
 -            queueDelegate_ = installed_;
 -    }
 -    return installed_;
 -}
 -
  - (void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
 -    int tag = [[viewController tabBarItem] tag];
 -    if (tag == tag_) {
 -        [(CYNavigationController *)[tabbar_ selectedViewController] popToRootViewControllerAnimated:YES];
 -        return;
 -    } else if (tag_ == 1) {
 -        [[self sectionsController] resetView];
 -    }
 -
 -    switch (tag) {
 -        case kCydiaTag: _setHomePage(self); break;
 +    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];
 +        }
  
 -        case kSectionsTag: [self setPage:[self sectionsController]]; break;
 -        case kChangesTag: [self setPage:[self changesController]]; break;
 -        case kManageTag: [self setPage:[self manageController]]; break;
 -        case kInstalledTag: [self setPage:[self installedController]]; break;
 -        case kSourcesTag: [self setPage:[self sourcesController]]; break;
 -        case kSearchTag: [self setPage:[self searchController]]; break;
 +        [root setDelegate:self];
  
 -        _nodefault
 +        if (root != nil)
 +            [controller setViewControllers:[NSArray arrayWithObject:root]];
      }
 -
 -    tag_ = tag;
  }
  
  - (void) showSettings {
          [self setNetworkActivityIndicatorVisible:NO];
  }
  
 -- (void) setPackageController:(PackageController *)view {
 +- (void) setPackageController:(CYPackageController *)view {
      WebThreadLock();
      [view setPackage:nil];
      WebThreadUnlock();
  }
  
 -- (PackageController *) _packageController {
 -    return [[[PackageController alloc] initWithDatabase:database_] autorelease];
 -}
 -
 -- (PackageController *) packageController {
 -    return [self _packageController];
 -}
 -
 -// Returns the navigation controller for the queuing badge.
 -- (id) queueBadgeController {
 -    int index = [self indexOfTabWithTag:kManageTag];
 -    if (index == -1)
 -        index = [self indexOfTabWithTag:kInstalledTag];
 -
 -    return [[tabbar_ viewControllers] objectAtIndex:index];
 -}
 -
  - (void) cancelAndClear:(bool)clear {
      @synchronized (self) {
          if (clear) {
  
  - (CYViewController *) pageForPackage:(NSString *)name {
      if (Package *package = [database_ packageWithName:name]) {
 -        PackageController *view([self packageController]);
 +        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]]];
 -        return [self _pageForURL:url withClass:[CYBrowserController class]];
 +        CYBrowserController *browser = [[[CYBrowserController alloc] init] autorelease];
 +        [browser loadURL:url];
 +        return browser;
      }
  }
  
 -- (CYViewController *) pageForURL:(NSURL *)url hasTag:(int *)tag {
 -    if (tag != NULL)
 -        *tag = -1;
 -
 -    NSString *href([url absoluteString]);
 -    if ([href hasPrefix:@"apptapp://package/"])
 -        return [self pageForPackage:[href substringFromIndex:18]];
 -
 +- (CYViewController *) pageForURL:(NSURL *)url {
      NSString *scheme([[url scheme] lowercaseString]);
 -    if (![scheme isEqualToString:@"cydia"])
 +    if ([[url absoluteString] length] <= [scheme length] + 3)
          return nil;
 -    NSString *path([url absoluteString]);
 -    if ([path length] < 8)
 +    NSString *path([[url absoluteString] substringFromIndex:[scheme length] + 3]);
 +    NSArray *components([path pathComponents]);
 +
 +    if ([scheme isEqualToString:@"apptapp"] && [components count] && [[components objectAtIndex:0] isEqualToString:@"package"])
 +        return [self pageForPackage:[components objectAtIndex:1]];
 +
 +    if ([components count] < 1 || ![scheme isEqualToString:@"cydia"])
          return nil;
 -    path = [path substringFromIndex:8];
 -    if (![path hasPrefix:@"/"])
 -        path = [@"/" stringByAppendingString:path];
 -
 -    if ([path isEqualToString:@"/storage"])
 -        return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[CYBrowserController class]];
 -    /*else if ([path isEqualToString:@"/add-source"])
 -        return [[[AddSourceController alloc] initWithDatabase:database_] autorelease];*/
 -    else if ([path isEqualToString:@"/sources"])
 -        return [[[SourceController alloc] initWithDatabase:database_] autorelease];
 -    else if ([path isEqualToString:@"/packages"])
 -        return [[[InstalledController alloc] initWithDatabase:database_] autorelease];
 -    else if ([path hasPrefix:@"/url/"])
 -        return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[CYBrowserController class]];
 -    else if ([path hasPrefix:@"/launch/"])
 -        [self launchApplicationWithIdentifier:[path substringFromIndex:8] suspended:NO];
 -    else if ([path hasPrefix:@"/package-settings/"])
 -        return [[[CYPackageSettingsController alloc] initWithDatabase:database_ package:[path substringFromIndex:18]] autorelease];
 -    else if ([path hasPrefix:@"/package-signature/"])
 -        return [[[SignatureController alloc] initWithDatabase:database_ package:[path substringFromIndex:19]] autorelease];
 -    else if ([path hasPrefix:@"/package/"])
 -        return [self pageForPackage:[path substringFromIndex:9]];
 -    else if ([path hasPrefix:@"/files/"]) {
 -        NSString *name = [path substringFromIndex:7];
 -
 -        if (Package *package = [database_ packageWithName:name]) {
 -            FileTable *files = [[[FileTable alloc] initWithDatabase:database_] autorelease];
 -            [files setPackage:package];
 -            return files;
 +
 +    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;
 +        }
 +
 +        if ([base isEqualToString:@"sources"]) {
 +            SourcesController *source = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
 +            return source;
 +        }
 +
 +        if ([base isEqualToString:@"home"]) {
 +            HomeController *home = [[[HomeController alloc] init] autorelease];
 +            return home;
 +        }
 +
 +        if ([base isEqualToString:@"sections"]) {
 +            SectionsController *sections = [[[SectionsController alloc] initWithDatabase:database_] autorelease];
 +            return sections;
 +        }
 +
 +        if ([base isEqualToString:@"search"]) {
 +            SearchController *search = [[[SearchController alloc] initWithDatabase:database_] autorelease];
 +            return search;
 +        }
 +
 +        if ([base isEqualToString:@"changes"]) {
 +            ChangesController *changes = [[[ChangesController alloc] initWithDatabase:database_ delegate:self] autorelease];
 +            return changes;
 +        }
 +
 +        if ([base isEqualToString:@"installed"]) {
 +            InstalledController *installed = [[[InstalledController alloc] initWithDatabase:database_] autorelease];
 +            return installed;
 +        }
 +    } else if ([components count] == 2) {
 +        NSString *argument = [components objectAtIndex:1];
 +
 +        if ([base isEqualToString:@"package"]) {
 +            CYViewController *package = [self pageForPackage:argument];
 +            return package;
 +        }
 +
 +        if ([base isEqualToString:@"search"]) {
 +            SearchController *search = [[[SearchController alloc] initWithDatabase:database_] autorelease];
 +            [search setSearchTerm:argument];
 +            return search;
 +        }
 +
 +        if ([base isEqualToString:@"sections"]) {
 +            if ([argument isEqualToString:@"all"])
 +                argument = nil;
 +            SectionController *section = [[[SectionController alloc] initWithDatabase:database_ section:argument] autorelease];
 +            [section setDelegate:self];
 +            return section;
 +        }
 +
 +        if ([base isEqualToString:@"sources"]) {
 +            if ([argument isEqualToString:@"add"]) {
 +                SourcesController *source = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
 +                [source showAddSourcePrompt];
 +                return source;
 +            } else {
 +                // XXX: Create page of the source specfified.
 +            }
 +        }
 +
 +        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];
 +        }
 +    } else if ([components count] == 3) {
 +        NSString *arg1 = [components objectAtIndex:1];
 +        NSString *arg2 = [components objectAtIndex:2];
 +
 +        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];
 +            } else if ([arg2 isEqualToString:@"files"]) {
 +                if (Package *package = [database_ packageWithName:arg1]) {
 +                    FileTable *files = [[[FileTable alloc] initWithDatabase:database_] autorelease];
 +                    [files setPackage:package];
 +                    return files;
 +                }
 +            }
          }
      }
  
  }
  
  - (BOOL) openCydiaURL:(NSURL *)url {
 -    CYViewController *page = nil;
 -    int tag = 0;
 +    CYViewController *page([self pageForURL:url]);
  
 -    if ((page = [self pageForURL:url hasTag:&tag])) {
 +    if (page != nil)
          [self setPage:page];
 -        tag_ = tag;
 -        [tabbar_ setSelectedViewController:(tag_ == -1 ? nil : [[tabbar_ viewControllers] objectAtIndex:tag_])];
 -    }
  
 -    return !!page;
 +    return page != nil;
  }
  
  - (void) applicationOpenURL:(NSURL *)url {
      }
  }
  
 -- (void) setupTabBarController {
 +- (void) setupViewControllers {
      tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_];
      [tabbar_ setDelegate:self];
  
      NSMutableArray *items([NSMutableArray arrayWithObjects:
 -        [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:kCydiaTag] autorelease],
 -        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SECTIONS") image:[UIImage applicationImageNamed:@"install.png"] tag:kSectionsTag] autorelease],
 -        [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:kChangesTag] autorelease],
 -        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:kSearchTag] autorelease],
 +        [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:0] autorelease],
 +        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SECTIONS") image:[UIImage applicationImageNamed:@"install.png"] tag:0] autorelease],
 +        [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:0] autorelease],
 +        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:0] autorelease],
      nil]);
  
      if (IsWildcat_) {
 -        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"source.png"] tag:kSourcesTag] autorelease] atIndex:3];
 -        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage.png"] tag:kInstalledTag] autorelease] atIndex:3];
 +        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"source.png"] tag:0] autorelease] atIndex:3];
 +        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage.png"] tag:0] autorelease] atIndex:3];
      } else {
 -        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:kManageTag] autorelease] atIndex:3];
 +        [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:0] autorelease] atIndex:3];
      }
  
      NSMutableArray *controllers([NSMutableArray array]);
 -
      for (UITabBarItem *item in items) {
          CYNavigationController *controller([[[CYNavigationController alloc] initWithDatabase:database_] autorelease]);
          [controller setTabBarItem:item];
          [controllers addObject:controller];
      }
 -
      [tabbar_ setViewControllers:controllers];
 +
 +    [tabbar_ setUpdateDelegate:self];
 +    [window_ addSubview:[tabbar_ view]];
  }
  
 -- (void)showFakeTabBarInView:(UIView *)view {
 -    static UITabBar *fake = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)];
 +- (void)showEmulatedLoadingControllerInView:(UIView *)view {
 +    static CYEmulatedLoadingController *fake = [[CYEmulatedLoadingController alloc] init];
      if (view != nil) {
 -        CGRect frame = [fake frame];
 -        frame.origin.y = [view frame].size.height - frame.size.height;
 -        frame.size.width = [view frame].size.width;
 -        [fake setFrame:frame];
 -        [fake setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
 -        [view addSubview:fake];
 +        [view addSubview:[fake view]];
      } else {
 -        [fake removeFromSuperview];
 +        [[fake view] removeFromSuperview];
      }
  }
  
@@@ -9051,6 -8976,8 +9039,6 @@@ _trace()
      Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
      Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
  
 -    tag_ = 0;
 -
      essential_ = [[NSMutableArray alloc] initWithCapacity:4];
      broken_ = [[NSMutableArray alloc] initWithCapacity:4];
  
  
      database_ = [Database sharedInstance];
  
 -    [self setupTabBarController];
 -    [tabbar_ setUpdateDelegate:self];
 -    [window_ addSubview:[tabbar_ view]];
 -
 -    // Show pinstripes while loading data.
 -    [[tabbar_ view] setBackgroundColor:[UIColor pinStripeColor]];
 -    [self showFakeTabBarInView:[tabbar_ tabBar]];
 +    [window_ setUserInteractionEnabled:NO];
 +    [self showEmulatedLoadingControllerInView:window_];
  
      [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
  _trace();
@@@ -9095,23 -9027,33 +9083,23 @@@ _trace()
          return;
      }
  
 -    CGRect fixframe = [[tabbar_ view] frame];
 -    if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
 -        fixframe.size = CGSizeMake(fixframe.size.height, fixframe.size.width);
 -    CYLoadingIndicator *loading = [[[CYLoadingIndicator alloc] initWithFrame:fixframe] autorelease];
 -    [loading setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
 -    [[tabbar_ view] addSubview:loading];
 -    [window_ setUserInteractionEnabled:NO];
 -
      [self reloadData];
      PrintTimes();
  
 -    // Show the initial page
 -    if (starturl_ == nil || ![self openCydiaURL:starturl_]) {
 -        [tabbar_ setSelectedIndex:0];
 -        _setHomePage(self);
 -    }
 -
 -    [self showFakeTabBarInView:nil];
 -
 -    [starturl_ release];
 -    starturl_ = nil;
 -
 +    [self setupViewControllers];
 +    [self showEmulatedLoadingControllerInView:nil];
      [window_ setUserInteractionEnabled:YES];
  
 -    // XXX: does this actually slow anything down?
 -    [[tabbar_ view] setBackgroundColor:[UIColor clearColor]];
 -    [loading removeFromSuperview];
 +    // Show the home page.
 +    CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:0];
 +    [navigation setViewControllers:[NSArray arrayWithObject:[[[HomeController alloc] init] autorelease]]];
 +
 +    // (Try to) show the startup URL.
 +    if (starturl_ != nil) {
 +        [self openCydiaURL:starturl_];
 +        [starturl_ release];
 +        starturl_ = nil;
 +    }
  }
  
  - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {