/* 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 {{{ */
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] = ':';
@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])) {
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
#define ShowInternals (0 && !ForRelease)
#define IgnoreInstall (0 && !ForRelease)
#define AlwaysReload (0 && !ForRelease)
+#define TryIndexedCollation (0 && !ForRelease)
#if !TraceLogging
#undef _trace
static bool Changed_;
static time_t now_;
-static bool IsWildcat_;
+bool IsWildcat_;
/* }}} */
/* Display Helpers {{{ */
@protocol CydiaDelegate
- (void) retainNetworkActivityIndicator;
- (void) releaseNetworkActivityIndicator;
-- (void) setPackageController:(CYPackageController *)view;
- (void) clearPackage:(Package *)package;
- (void) installPackage:(Package *)package;
- (void) installPackages:(NSArray *)packages;
static Cytore::File<MetaValue> 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;
*offset = MetaFile_.New<PackageValue>(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 {
}
static void PackageImport(const void *key, const void *value, void *context) {
+ bool &fail(*reinterpret_cast<bool *>(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"])
if (range.location != NSNotFound)
return YES;
+ [self parse];
+
range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_];
if (range.location != NSNotFound)
return YES;
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"] ||
[[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)
if (issues_ == nil && ![self isLoading])
[[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]
initWithTitle:UCLocalize("CONFIRM")
- style:UIBarButtonItemStylePlain
+ style:UIBarButtonItemStyleDone
target:self
action:@selector(confirmButtonClicked)
] autorelease]];
//[status_ setFont:font];
output_ = [[UITextView alloc] init];
-
[output_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
//[output_ setTextFont:@"Courier New"];
[output_ setFont:[[output_ font] fontWithSize:12]];
10,
20,
bounds.size.width - 20,
- bounds.size.height - 62
+ bounds.size.height - 96
)];
[close_ setFrame:CGRectMake(
(bounds.size.width - closewidth) / 2,
}
- (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
[self setNeedsDisplay];
}
+- (NSString *) accessibilityLabel {
+ return [NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), name_, description_];
+}
+
- (void) setPackage:(Package *)package {
[self clearPackage];
[package parse];
[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_);
}
- (void) release {
- if ([self retainCount] == 1)
- [delegate_ setPackageController:self];
[super release];
}
}
#endif
+- (void) viewWillAppear:(BOOL)animated {
+ if (![self hasLoaded])
+ [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/package/")]];
+ [super viewWillAppear:animated];
+}
+
- (id) initWithDatabase:(Database *)database {
if ((self = [super init]) != nil) {
database_ = database;
buttons_ = [[NSMutableArray alloc] initWithCapacity:4];
- [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"package" ofType:@"html"]]];
} return self;
}
}
- (void) reloadData {
+ [super reloadData];
+
[self setPackage:[database_ packageWithName:name_]];
}
@end
/* }}} */
-/* Package Table {{{ */
-@interface PackageTable : UIView <
+/* Package List Controller {{{ */
+@interface PackageListController : CYViewController <
UITableViewDataSource,
UITableViewDelegate
> {
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];
[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_] autorelease]);
+ [view setPackage:package];
+ [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]);
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 {
}
- (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];
}
- (void) reloadData {
+ [super reloadData];
+
era_ = [database_ era];
NSArray *packages = [database_ packages];
Section *section = nil;
+#if TryIndexedCollation
if ([[self class] hasIndexedCollation]) {
id collation = [objc_getClass("UILocalizedIndexedCollation") currentCollation];
NSArray *titles = [collation sectionIndexTitles];
[section addToCount];
}
_end
- } else {
+ } else
+#endif
+ {
[index_ removeAllObjects];
_profile(PackageTable$reloadData$Section)
[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_;
- (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)
_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_;
- SEL filter_;
- id object_;
-}
-
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
-
-@end
-
-@implementation FilteredPackageController
-
-- (void) dealloc {
- [self releaseSubviews];
- [title_ release];
-
- [super dealloc];
-}
-
-- (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];
-}
-
-- (void) loadView {
- [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
-
- 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_];
-}
-
-- (void) viewDidLoad {
- [[self navigationItem] setTitle:title_];
-}
-
-- (void) releaseSubviews {
- [packages_ release];
-}
-
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
- if ((self = [super init]) != nil) {
- database_ = database;
- title_ = [title copy];
- filter_ = filter;
- object_ = object;
- } return self;
-}
-
-- (void) reloadData {
- [super reloadData];
- [packages_ reloadData];
-}
-
-- (void) setDelegate:(id)delegate {
- [super setDelegate:delegate];
- [packages_ setDelegate:delegate];
-}
-
-@end
-
/* }}} */
/* Home Controller {{{ */
@implementation HomeController
-+ (BOOL)shouldHideNavigationBar {
++ (BOOL) shouldHideNavigationBar {
return NO;
}
[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/"
[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];
[[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:CydiaURL(@"ui/home/")]];
- [[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
return [NSURL URLWithString:@"cydia://manage"];
}
-- (id) init {
- if ((self = [super init]) != nil) {
- [[self navigationItem] setTitle:UCLocalize("MANAGE")];
+- (void) viewWillAppear:(BOOL)animated {
+ if (![self hasLoaded])
+ [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/manage/")]];
- [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]];
+ [super viewWillAppear:animated];
+}
- [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
- initWithTitle:UCLocalize("SETTINGS")
- style:UIBarButtonItemStylePlain
- target:self
- action:@selector(settingsButtonClicked)
- ] autorelease]];
+- (void) viewDidLoad {
+ [[self navigationItem] setTitle:UCLocalize("MANAGE")];
- [self queueStatusDidChange];
- } return self;
+ [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("SETTINGS")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(settingsButtonClicked)
+ ] autorelease]];
+
+ [self queueStatusDidChange];
}
- (void) settingsButtonClicked {
}
- (void) applyLoadingTitle {
- // No "Loading" title.
+ // Disable "Loading" title.
}
- (void) applyRightButton {
- // No right button.
+ // Disable right button.
}
#endif
}
- (bool) isLoading {
+ // Never show as loading.
return false;
}
id root_;
}
-- (NSArray *) navigationURLItems;
+- (NSArray *) navigationURLCollection;
- (void) dropBar:(BOOL)animated;
- (void) beginUpdate;
- (void) raiseBar:(BOOL)animated;
@implementation CYTabBarController
-- (NSArray *) navigationURLItems {
+- (NSArray *) navigationURLCollection {
NSMutableArray *items([NSMutableArray array]);
- // XXX:Deal with transient view controllers.
+ // XXX: Should this deal with transient view controllers?
for (id navigation in [self viewControllers]) {
- NSArray *stack = [navigation performSelector:@selector(navigationURLStack)];
+ NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)];
if (stack != nil)
[items addObject:stack];
}
}
- (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];
- }
+ for (CYViewController *controller in [self viewControllers])
+ [controller reloadData];
[(CYNavigationController *)[self transientViewController] reloadData];
}
+- (void) dealloc {
+ [refreshbar_ release];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [super dealloc];
+}
+
- (id) initWithDatabase:(Database *)database {
if ((self = [super init]) != nil) {
database_ = database;
}
}
-- (void) dealloc {
- [refreshbar_ release];
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
-}
-
@end
/* }}} */
/* Cydia Navigation Controller {{{ */
_transient id<UINavigationControllerDelegate> delegate_;
}
-- (NSArray *) navigationURLStack;
+- (NSArray *) navigationURLCollection;
- (id) initWithDatabase:(Database *)database;
- (void) reloadData;
[super dealloc];
}
-- (NSArray *) navigationURLStack {
+- (NSArray *) navigationURLCollection {
NSMutableArray *stack([NSMutableArray array]);
for (CYViewController *controller in [self viewControllers]) {
}
- (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]) {
+ if ([page hasLoaded])
+ [page reloadData];
}
}
/* }}} */
/* Section Controller {{{ */
-@interface SectionController : FilteredPackageController {
+@interface SectionController : FilteredPackageListController {
NSString *section_;
}
}
}
+- (BOOL) isEditing {
+ return editing_;
+}
+
- (void) setEditing:(BOOL)editing {
if ((editing_ = editing))
[list_ reloadData];
- (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];
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 ((self = [super init]) != nil) {
database_ = database;
- // We load after the view is visible, so don't "magically" load beforehand.
- loaded_ = YES;
-
packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
} return self;
@end
/* }}} */
/* Search Controller {{{ */
-@interface SearchController : FilteredPackageController <
+@interface SearchController : FilteredPackageListController <
UISearchBarDelegate
> {
UISearchBar *search_;
}
- (NSURL *) navigationURL {
- return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://search/%@", [search_ text]]];
+ 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 {
}
- (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:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)];
+ [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
[self reloadData];
}
}
- (void) reloadData {
- [packages_ setObject:[search_ text]];
+ [self setObject:[search_ text]];
[super reloadData];
- [packages_ resetCursor];
+ [self resetCursor];
}
- (void) didSelectPackage:(Package *)package {
[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];
-}
-
-- (NSURL *) navigationURL {
- return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/signature", package_]];
-}
-
-- (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_;
}
#endif
}
-- (void) reloadData {
- [packages_ reloadData];
-}
-
- (void) updateRoleButton {
if (Role_ != nil && ![Role_ isEqualToString:@"Developer"])
[[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]
}
- (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
/* }}} */
} return self;
}
+- (NSString *) accessibilityLabel {
+ return label_;
+}
+
- (void) drawContentRect:(CGRect)rect {
bool highlighted(highlighted_);
float width(rect.size.width);
@end
/* }}} */
/* Source Controller {{{ */
-@interface SourceController : FilteredPackageController {
+@interface SourceController : FilteredPackageListController {
Source *source_;
}
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 {
[self setNetworkActivityIndicatorVisible:NO];
}
-- (void) setPackageController:(CYPackageController *)view {
- WebThreadLock();
- [view setPackage:nil];
- WebThreadUnlock();
-}
-
- (void) cancelAndClear:(bool)clear {
@synchronized (self) {
if (clear) {
if ([base isEqualToString:@"package"]) {
if ([arg2 isEqualToString:@"settings"]) {
controller = [[[PackageSettingsController alloc] initWithDatabase:database_ package:arg1] autorelease];
- } else if ([arg2 isEqualToString:@"signature"]) {
- controller = [[[SignatureController alloc] initWithDatabase:database_ package:arg1] autorelease];
} else if ([arg2 isEqualToString:@"files"]) {
if (Package *package = [database_ packageWithName:arg1]) {
controller = [[[FileTable alloc] initWithDatabase:database_] autorelease];
}
- (void) applicationWillTerminate:(UIApplication *)application {
- [Metadata_ setObject:[tabbar_ navigationURLItems] forKey:@"InterfaceState"];
+ Changed_ = true;
+ [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"];
[Metadata_ setObject:[NSDate date] forKey:@"LastClosed"];
[Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"];
}
}
+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();
_UIHardware$_playSystemSound$ = reinterpret_cast<void (*)(Class, SEL, int)>(method_getImplementation(UIHardware$_playSystemSound$));
method_setImplementation(UIHardware$_playSystemSound$, reinterpret_cast<IMP>(&$UIHardware$_playSystemSound$));
}
+
+ $UIApplication = objc_getClass("UIApplication");
+ Method UIApplication$_updateApplicationAccessibility(class_getInstanceMethod($UIApplication, @selector(_updateApplicationAccessibility)));
+ if (UIApplication$_updateApplicationAccessibility != NULL) {
+ _UIApplication$_updateApplicationAccessibility = reinterpret_cast<void (*)(UIApplication *, SEL)>(method_getImplementation(UIApplication$_updateApplicationAccessibility));
+ method_setImplementation(UIApplication$_updateApplicationAccessibility, reinterpret_cast<IMP>(&$UIApplication$_updateApplicationAccessibility));
+ }
/* }}} */
/* Set Locale {{{ */
Locale_ = CFLocaleCopyCurrent();
_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];