/* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008 Jay Freeman (saurik)
+ * Copyright (C) 2008-2010 Jay Freeman (saurik)
*/
+/* Modified BSD License {{{ */
/*
* Redistribution and use in source and binary
* forms, with or without modification, are permitted
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/* }}} */
// XXX: wtf/FastMalloc.h... wtf?
#define USE_SYSTEM_MALLOC 1
/* #include Directives {{{ */
-#import "UICaboodle.h"
+#import "UICaboodle/UCPlatform.h"
+#import "UICaboodle/UCLocalize.h"
-#include <objc/message.h>
#include <objc/objc.h>
#include <objc/runtime.h>
#include <CoreFoundation/CFPriv.h>
#include <CoreFoundation/CFUniChar.h>
-#import <QuartzCore/CALayer.h>
#import <UIKit/UIKit.h>
#include <WebCore/WebCoreThread.h>
#include <ext/stdio_filebuf.h>
+#undef ABS
+
#include <apt-pkg/acquire.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/algorithms.h>
#include <ext/hash_map>
-#import "BrowserView.h"
-#import "ResetView.h"
+#include <notify.h>
+
+#import "UICaboodle/BrowserView.h"
+#import "UICaboodle/ResetView.h"
#import "substrate.h"
+
+// Apple's sample Reachability code, ASPL licensed.
+#import "Reachability.h"
/* }}} */
-//#define _finline __attribute__((force_inline))
-#define _finline inline
+/* Header Fixes and Updates {{{ */
+typedef enum {
+ UIModalPresentationFullScreen = 0,
+ UIModalPresentationPageSheet,
+ UIModalPresentationFormSheet,
+ UIModalPresentationCurrentContext,
+} UIModalPresentationStyle;
+
+@interface UIAlertView (Private)
+- (void)setNumberOfRows:(int)rows;
+- (void)setContext:(id)context;
+- (id)context;
+@end
-struct timeval _ltv;
-bool _itv;
+@interface UIViewController (UIKit)
+- (id)navigationItem;
+- (id)navigationController;
+- (id)tabBarItem;
+@end
-#define _limit(count) do { \
- static size_t _count(0); \
- if (++_count == count) \
- exit(0); \
-} while (false)
+@interface UITabBarController : UIViewController {
+ id _tabBar;
+ id _containerView;
+ id _viewControllerTransitionView;
+ id _viewControllers;
+ id _tabBarItemsToViewControllers;
+ id _selectedViewController;
+ id _moreNavigationController;
+ id _customizableViewControllers;
+ id _delegate;
+ id _selectedViewControllerDuringWillAppear;
+ id _transientViewController;
+ unsigned int isShowingMoreItem:1;
+ unsigned int needsToRebuildItems:1;
+ unsigned int isBarHidden:1;
+ unsigned int editButtonOnLeft:1;
+}
+@end
+/* }}} */
/* Profiler {{{ */
+struct timeval _ltv;
+bool _itv;
+
#define _timestamp ({ \
struct timeval tv; \
gettimeofday(&tv, NULL); \
#define _end }
/* }}} */
-/* Objective-C Handle<> {{{ */
-template <typename Type_>
-class _H {
- typedef _H<Type_> This_;
-
- private:
- Type_ *value_;
-
- _finline void Retain_() {
- if (value_ != nil)
- [value_ retain];
- }
-
- _finline void Clear_() {
- if (value_ != nil)
- [value_ release];
- }
-
- public:
- _finline _H(Type_ *value = NULL, bool mended = false) :
- value_(value)
- {
- if (!mended)
- Retain_();
- }
-
- _finline ~_H() {
- Clear_();
- }
-
- _finline operator Type_ *() const {
- return value_;
- }
-
- _finline This_ &operator =(Type_ *value) {
- if (value_ != value) {
- Type_ *old(value_);
- value_ = value;
- Retain_();
- if (old != nil)
- [old release];
- } return *this;
- }
-};
-/* }}} */
#define _pooled _H<NSAutoreleasePool> _pool([[NSAutoreleasePool alloc] init], true);
+static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
void NSLogPoint(const char *fix, const CGPoint &point) {
NSLog(@"%s(%g,%g)", fix, point.x, point.y);
}
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] = ':';
+ page[5] = '/'; page[6] = '/'; page[7] = 'c'; page[8] = 'y'; page[9] = 'd';
+ page[10] = 'i'; page[11] = 'a'; page[12] = '.'; page[13] = 's'; page[14] = 'a';
+ page[15] = 'u'; page[16] = 'r'; page[17] = 'i'; page[18] = 'k'; page[19] = '.';
+ page[20] = 'c'; page[21] = 'o'; page[22] = 'm'; page[23] = '/'; page[24] = '\0';
+ return [[NSString stringWithUTF8String:page] stringByAppendingString:path];
+}
+
+static _finline void UpdateExternalStatus(uint64_t newStatus) {
+ int notify_token;
+ if (notify_register_check("com.saurik.Cydia.status", ¬ify_token) == NOTIFY_STATUS_OK) {
+ notify_set_state(notify_token, newStatus);
+ notify_cancel(notify_token);
+ }
+ notify_post("com.saurik.Cydia.status");
+}
+
+/* [NSObject yieldToSelector:(withObject:)] {{{*/
@interface NSObject (Cydia)
- (id) yieldToSelector:(SEL)selector withObject:(id)object;
- (id) yieldToSelector:(SEL)selector;
}
@end
+/* }}} */
-/* NSForcedOrderingSearch doesn't work on the iPhone */
-static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
-static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
-static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
+@interface CYActionSheet : UIAlertView {
+ unsigned button_;
+}
-/* iPhoneOS 2.0 Compatibility {{{ */
-#ifdef __OBJC2__
-@interface UITextView (iPhoneOS)
-- (void) setTextSize:(float)size;
+- (int) yieldToPopupAlertAnimated:(BOOL)animated;
@end
-@implementation UITextView (iPhoneOS)
+@implementation CYActionSheet
+
+- (id) initWithTitle:(NSString *)title buttons:(NSArray *)buttons defaultButtonIndex:(int)index {
+ if ((self = [super init])) {
+ [self setTitle:title];
+ [self setDelegate:self];
+ for (NSString *button in buttons) [self addButtonWithTitle:button];
+ [self setCancelButtonIndex:index];
+ } return self;
+}
+
+- (void)_updateFrameForDisplay {
+ [super _updateFrameForDisplay];
+ if ([self cancelButtonIndex] == -1) {
+ NSArray *buttons = [self buttons];
+ if ([buttons count]) {
+ UIImage *background = [[buttons objectAtIndex:0] backgroundForState:0];
+ for (UIThreePartButton *button in buttons)
+ [button setBackground:background forState:0];
+ }
+ }
+}
+
+- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+ button_ = buttonIndex + 1;
+}
+
+- (void) dismiss {
+ [self dismissWithClickedButtonIndex:-1 animated:YES];
+}
-- (void) setTextSize:(float)size {
- [self setFont:[[self font] fontWithSize:size]];
+- (int) yieldToPopupAlertAnimated:(BOOL)animated {
+ [self setRunsModal:YES];
+ button_ = 0;
+ [self show];
+ return button_;
}
@end
-#endif
-/* }}} */
-extern NSString * const kCAFilterNearest;
+/* NSForcedOrderingSearch doesn't work on the iPhone */
+static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
+static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
+static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
/* Information Dictionaries {{{ */
@interface NSMutableArray (Cydia)
@implementation NSMutableDictionary (Cydia)
- (void) addInfoDictionary:(NSDictionary *)info {
- NSString *bundle = [info objectForKey:@"CFBundleIdentifier"];
- [self setObject:info forKey:bundle];
-}
-
-@end
-/* }}} */
-/* Pop Transitions {{{ */
-@interface PopTransitionView : UITransitionView {
-}
-
-@end
-
-@implementation PopTransitionView
-
-- (void) transitionViewDidComplete:(UITransitionView *)view fromView:(UIView *)from toView:(UIView *)to {
- if (from != nil && to == nil)
- [self removeFromSuperview];
-}
-
-@end
-
-@implementation UIView (PopUpView)
-
-- (void) popFromSuperviewAnimated:(BOOL)animated {
- [[self superview] transition:(animated ? UITransitionPushFromTop : UITransitionNone) toView:nil];
-}
-
-- (void) popSubview:(UIView *)view {
- UITransitionView *transition([[[PopTransitionView alloc] initWithFrame:[self bounds]] autorelease]);
- [transition setDelegate:transition];
- [self addSubview:transition];
-
- UIView *blank = [[[UIView alloc] initWithFrame:[transition bounds]] autorelease];
- [transition transition:UITransitionNone toView:blank];
- [transition transition:UITransitionPushFromBottom toView:view];
+ [self setObject:info forKey:[info objectForKey:@"CFBundleIdentifier"]];
}
@end
#define HistogramInsertionSort (0 && !ForRelease)
#define ProfileTimes (0 && !ForRelease)
#define ForSaurik (0 && !ForRelease)
-#define LogBrowser (1 && !ForRelease)
+#define LogBrowser (0 && !ForRelease)
#define TrackResize (0 && !ForRelease)
-#define ManualRefresh (1 && !ForRelease)
+#define ManualRefresh (0 && !ForRelease)
#define ShowInternals (0 && !ForRelease)
#define IgnoreInstall (0 && !ForRelease)
#define RecycleWebViews 0
+#define RecyclePackageViews (1 && ForRelease)
#define AlwaysReload (1 && !ForRelease)
#if !TraceLogging
CFIndex half = count / 2;
const char *probe = ptr + elementSize * half;
CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
+ if (0 == cr) return (probe - (const char *)list) / elementSize;
ptr = (cr < 0) ? ptr : probe + elementSize;
count = (cr < 0) ? half : (half + (count & 1) - 1);
}
CFIndex half = count / 2;
const char *probe = ptr + elementSize * half;
CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
+ if (0 == cr) return (probe - (const char *)list) / elementSize;
ptr = (cr < 0) ? ptr : probe + elementSize;
count = (cr < 0) ? half : (half + (count & 1) - 1);
}
@end
/* }}} */
-typedef enum {
- kUIControlEventMouseDown = 1 << 0,
- kUIControlEventMouseMovedInside = 1 << 2, // mouse moved inside control target
- kUIControlEventMouseMovedOutside = 1 << 3, // mouse moved outside control target
- kUIControlEventMouseUpInside = 1 << 6, // mouse up inside control target
- kUIControlEventMouseUpOutside = 1 << 7, // mouse up outside control target
- kUIControlAllEvents = (kUIControlEventMouseDown | kUIControlEventMouseMovedInside | kUIControlEventMouseMovedOutside | kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)
-} UIControlEventMasks;
+NSUInteger WebScriptObject$countByEnumeratingWithState$objects$count$(WebScriptObject *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
+ size_t length([self count] - state->state);
+ if (length <= 0)
+ return 0;
+ else if (length > count)
+ length = count;
+ for (size_t i(0); i != length; ++i)
+ objects[i] = [self objectAtIndex:state->state++];
+ state->itemsPtr = objects;
+ state->mutationsPtr = (unsigned long *) self;
+ return length;
+}
NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
size_t length([self length] - state->state);
@interface NSString (UIKit)
- (NSString *) stringByAddingPercentEscapes;
-- (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
@end
+/* Cydia NSString Additions {{{ */
@interface NSString (Cydia)
+ (NSString *) stringWithUTF8BytesNoCopy:(const char *)bytes length:(int)length;
+ (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length withZone:(NSZone *)zone inPool:(apr_pool_t *)pool;
- (NSString *) stringByCachingURLWithCurrentCDN {
return [self
- stringByReplacingOccurrencesOfString:@"://"
- withString:@"://ne.edgecastcdn.net/8003A4/"
- options:0
- /* XXX: this is somewhat inaccurate */
- range:NSMakeRange(0, 10)
+ stringByReplacingOccurrencesOfString:@"://cydia.saurik.com/"
+ withString:@"://cache.cydia.saurik.com/"
];
}
}
@end
+/* }}} */
-static inline NSString *CYLocalizeEx(NSString *key, NSString *value = nil) {
- return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
-}
-
-#define CYLocalize(key) CYLocalizeEx(@ key)
-
+/* C++ NSString Wrapper Cache {{{ */
class CYString {
private:
char *data_;
CFStringRef cache_;
_finline void clear_() {
- if (cache_ != nil)
+ if (cache_ != NULL) {
CFRelease(cache_);
+ cache_ = NULL;
+ }
}
public:
_finline CYString() :
data_(0),
size_(0),
- cache_(nil)
+ cache_(NULL)
{
}
if (size_ == 0)
return nil;
cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingUTF8, NO, kCFAllocatorNull);
+ if (cache_ == NULL)
+ cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
} return cache_;
}
return (NSString *) static_cast<CFStringRef>(*this);
}
};
-
+/* }}} */
+/* C++ NSString Algorithm Adapters {{{ */
extern "C" {
CF_EXPORT CFHashCode CFStringHashNSString(CFStringRef str);
}
//[lhs isEqualToString:rhs];
}
};
+/* }}} */
/* Perl-Compatible RegEx {{{ */
class Pcre {
};
/* }}} */
-extern "C" void UISetColor(CGColorRef color);
-
/* Random Global Variables {{{ */
static const int PulseInterval_ = 50000;
+static const int ButtonBarWidth_ = 60;
static const int ButtonBarHeight_ = 48;
static const float KeyboardTime_ = 0.3f;
+static int Finish_;
+static NSArray *Finishes_;
+
#define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
-#define SandboxTemplate_ "/usr/share/sandbox/SandboxTemplate.sb"
#define NotifyConfig_ "/etc/notify.conf"
static bool Queuing_;
static NSString *App_;
static NSString *Home_;
-static BOOL Sounds_Keyboard_;
static BOOL Advanced_;
-static BOOL Loaded_;
static BOOL Ignored_;
static UIFont *Font12_;
static UIFont *Font22Bold_;
static const char *Machine_ = NULL;
+static const NSString *System_ = NULL;
+static const NSString *SerialNumber_ = nil;
+static const NSString *ChipID_ = nil;
+static const NSString *Token_ = nil;
static const NSString *UniqueID_ = nil;
static const NSString *Build_ = nil;
static const NSString *Product_ = nil;
static const NSString *Safari_ = nil;
-CFLocaleRef Locale_;
-NSArray *Languages_;
-CGColorSpaceRef space_;
-
-bool bootstrap_;
-bool reload_;
+static CFLocaleRef Locale_;
+static NSArray *Languages_;
+static CGColorSpaceRef space_;
static NSDictionary *SectionMap_;
static NSMutableDictionary *Metadata_;
static bool Changed_;
static NSDate *now_;
+static bool IsWildcat_;
+
#if RecycleWebViews
static NSMutableArray *Documents_;
#endif
-
-NSString *GetLastUpdate() {
- NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
-
- if (update == nil)
- return CYLocalize("NEVER_OR_UNKNOWN");
-
- CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
- CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
-
- CFRelease(formatter);
-
- return [(NSString *) formatted autorelease];
-}
/* }}} */
+
/* Display Helpers {{{ */
inline float Interpolate(float begin, float end, float fraction) {
return (end - begin) * fraction + begin;
return CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(value), strlen(value), kCFStringEncodingUTF8, NO, kCFAllocatorNull);
}
+const char *StripVersion_(const char *version) {
+ const char *colon(strchr(version, ':'));
+ if (colon != NULL)
+ version = colon + 1;
+ return version;
+}
+
CFStringRef StripVersion(const char *version) {
const char *colon(strchr(version, ':'));
if (colon != NULL)
version = colon + 1;
+ return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(version), strlen(version), kCFStringEncodingUTF8, NO);
+ // XXX: performance
return CFCString(version);
}
NSString *parent(title_r[1]);
NSString *child(title_r[2]);
- return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"),
+ return [NSString stringWithFormat:UCLocalize("PARENTHETICAL"),
LocalizeSection(parent),
LocalizeSection(child)
];
}
/* }}} */
+NSString *GetLastUpdate() {
+ NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
+
+ if (update == nil)
+ return UCLocalize("NEVER_OR_UNKNOWN");
+
+ CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
+ CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
+
+ CFRelease(formatter);
+
+ return [(NSString *) formatted autorelease];
+}
+
bool isSectionVisible(NSString *section) {
NSDictionary *metadata([Sections_ objectForKey:section]);
NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
return hidden == nil || ![hidden boolValue];
}
+@class Cydia;
+
/* Delegate Prototypes {{{ */
@class Package;
@class Source;
@interface NSObject (ProgressDelegate)
@end
-@implementation NSObject(ProgressDelegate)
-
-- (void) _setProgressError:(NSArray *)args {
- [self performSelector:@selector(setProgressError:forPackage:)
- withObject:[args objectAtIndex:0]
- withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
- ];
-}
-
-@end
-
@protocol ProgressDelegate
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id;
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)id;
- (void) setProgressTitle:(NSString *)title;
- (void) setProgressPercent:(float)percent;
- (void) startProgress;
- (void) setConfigurationData:(NSString *)data;
@end
-@class PackageView;
+@class PackageController;
@protocol CydiaDelegate
-- (void) setPackageView:(PackageView *)view;
+- (void) setPackageController:(PackageController *)view;
- (void) clearPackage:(Package *)package;
- (void) installPackage:(Package *)package;
+- (void) installPackages:(NSArray *)packages;
- (void) removePackage:(Package *)package;
-- (void) slideUp:(UIActionSheet *)alert;
- (void) distUpgrade;
- (void) updateData;
- (void) syncData;
-- (void) askForSettings;
+- (void) showSettings;
- (UIProgressHUD *) addProgressHUD;
- (void) removeProgressHUD:(UIProgressHUD *)hud;
-- (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag;
-- (RVPage *) pageForPackage:(NSString *)name;
-- (void) openMailToURL:(NSURL *)url;
-- (void) clearFirstResponder;
-- (PackageView *) packageView;
+- (UIViewController *) pageForPackage:(NSString *)name;
+- (PackageController *) packageController;
@end
/* }}} */
delegate_ = delegate;
}
+ NSObject<ProgressDelegate> *getDelegate() const {
+ return delegate_;
+ }
+
virtual bool MediaChange(std::string media, std::string drive) {
return false;
}
virtual void Fetch(pkgAcquire::ItemDesc &item) {
//NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]);
- [delegate_ setProgressTitle:[NSString stringWithUTF8String:("Downloading " + item.ShortDesc).c_str()]];
+ [delegate_ setProgressTitle:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), [NSString stringWithUTF8String:item.ShortDesc.c_str()]]];
}
virtual void Done(pkgAcquire::ItemDesc &item) {
NSArray *fields([description componentsSeparatedByString:@" "]);
NSString *source([fields count] == 0 ? nil : [fields objectAtIndex:0]);
- [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+ [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
withObject:[NSArray arrayWithObjects:
[NSString stringWithUTF8String:error.c_str()],
source,
{
private:
_transient id<ProgressDelegate> delegate_;
+ float percent_;
protected:
virtual void Update() {
+ /*if (abs(Percent - percent_) > 2)
+ //NSLog(@"%s:%s:%f", Op.c_str(), SubOp.c_str(), Percent);
+ percent_ = Percent;
+ }*/
+
/*[delegate_ setProgressTitle:[NSString stringWithUTF8String:Op.c_str()]];
[delegate_ setProgressPercent:(Percent / 100)];*/
}
public:
Progress() :
- delegate_(nil)
+ delegate_(nil),
+ percent_(0)
{
}
delegate_ = delegate;
}
+ id getDelegate() const {
+ return delegate_;
+ }
+
virtual void Done() {
+ //NSLog(@"DONE");
//[delegate_ setProgressPercent:1];
}
};
- (void) reloadData;
- (void) configure;
-- (void) prepare;
+- (bool) prepare;
- (void) perform;
-- (void) upgrade;
+- (bool) upgrade;
- (void) update;
+- (void) setVisible;
+
- (void) updateWithStatus:(Status &)status;
- (void) setDelegate:(id)delegate;
- (Source *) getSource:(pkgCache::PkgFileIterator)file;
+@end
+/* }}} */
+/* Delegate Helpers {{{ */
+@implementation NSObject(ProgressDelegate)
+
+- (void) _setProgressErrorPackage:(NSArray *)args {
+ [self performSelector:@selector(setProgressError:forPackage:)
+ withObject:[args objectAtIndex:0]
+ withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
+ ];
+}
+
+- (void) _setProgressErrorTitle:(NSArray *)args {
+ [self performSelector:@selector(setProgressError:withTitle:)
+ withObject:[args objectAtIndex:0]
+ withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
+ ];
+}
+
+- (void) _setProgressError:(NSString *)error withTitle:(NSString *)title {
+ [self performSelectorOnMainThread:@selector(_setProgressErrorTitle:)
+ withObject:[NSArray arrayWithObjects:error, title, nil]
+ waitUntilDone:YES
+ ];
+}
+
+- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
+ Package *package = id == nil ? nil : [[Database sharedInstance] packageWithName:id];
+ // XXX: holy typecast batman!
+ [self setProgressError:error withTitle:(package == nil ? id : [package name])];
+}
+
@end
/* }}} */
/* Source Class {{{ */
@interface Source : NSObject {
+ CYString depiction_;
CYString description_;
CYString label_;
CYString origin_;
CYString version_;
NSString *host_;
+ NSString *authority_;
CYString defaultIcon_;
- (NSComparisonResult) compareByNameAndType:(Source *)source;
+- (NSString *) depictionForPackage:(NSString *)package;
- (NSString *) supportForPackage:(NSString *)package;
- (NSDictionary *) record;
description_.clear();
label_.clear();
origin_.clear();
+ depiction_.clear();
support_.clear();
version_.clear();
defaultIcon_.clear();
[host_ release];
host_ = nil;
}
+
+ if (authority_ != nil) {
+ [authority_ release];
+ authority_ = nil;
+ }
}
- (void) dealloc {
debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
if (dindex != NULL) {
- FileFd fd(dindex->MetaIndexFile("Release"), FileFd::ReadOnly);
- pkgTagFile tags(&fd);
+ FileFd fd;
+ if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ pkgTagFile tags(&fd);
- pkgTagSection section;
- tags.Step(section);
+ pkgTagSection section;
+ tags.Step(section);
- struct {
- const char *name_;
- CYString *value_;
- } names[] = {
- {"default-icon", &defaultIcon_},
- {"description", &description_},
- {"label", &label_},
- {"origin", &origin_},
- {"support", &support_},
- {"version", &version_},
- };
-
- for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
- const char *start, *end;
+ struct {
+ const char *name_;
+ CYString *value_;
+ } names[] = {
+ {"default-icon", &defaultIcon_},
+ {"depiction", &depiction_},
+ {"description", &description_},
+ {"label", &label_},
+ {"origin", &origin_},
+ {"support", &support_},
+ {"version", &version_},
+ };
+
+ for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
+ const char *start, *end;
- if (section.Find(names[i].name_, start, end)) {
- CYString &value(*names[i].value_);
- value.set(pool, start, end - start);
+ if (section.Find(names[i].name_, start, end)) {
+ CYString &value(*names[i].value_);
+ value.set(pool, start, end - start);
+ }
}
}
}
if (record_ != nil)
record_ = [record_ retain];
- host_ = [[[[NSURL URLWithString:uri_] host] lowercaseString] retain];
+ NSURL *url([NSURL URLWithString:uri_]);
+
+ host_ = [url host];
+ if (host_ != nil)
+ host_ = [[host_ lowercaseString] retain];
+
+ if (host_ != nil)
+ authority_ = host_;
+ else
+ authority_ = [url path];
+
+ if (authority_ != nil)
+ authority_ = [authority_ retain];
}
- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool {
return [lhs compare:rhs options:LaxCompareOptions_];
}
+- (NSString *) depictionForPackage:(NSString *)package {
+ return depiction_.empty() ? nil : [depiction_ stringByReplacingOccurrencesOfString:@"*" withString:package];
+}
+
- (NSString *) supportForPackage:(NSString *)package {
return support_.empty() ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package];
}
}
- (NSString *) name {
- return origin_.empty() ? host_ : origin_;
+ return origin_.empty() ? authority_ : origin_;
}
- (NSString *) description {
}
- (NSString *) label {
- return label_.empty() ? host_ : label_;
+ return label_.empty() ? authority_ : label_;
}
- (NSString *) origin {
CYString section_;
NSString *section$_;
bool essential_;
+ bool required_;
bool visible_;
+ bool obsolete_;
NSString *latest_;
- NSString *installed_;
+ CYString installed_;
CYString id_;
CYString name_;
CYString author_;
Address *author$_;
+ CYString bugs_;
CYString support_;
NSMutableArray *tags_;
NSString *role_;
- (NSString *) latest;
- (NSString *) installed;
+- (BOOL) uninstalled;
- (BOOL) valid;
- (BOOL) upgradableAndEssential:(BOOL)essential;
- (BOOL) hasMode;
- (NSString *) mode;
+- (void) setVisible;
+
- (NSString *) id;
- (NSString *) name;
- (UIImage *) icon;
- (void) remove;
- (bool) isUnfilteredAndSearchedForBy:(NSString *)search;
+- (bool) isUnfilteredAndSelectedForBy:(NSString *)search;
- (bool) isInstalledAndVisible:(NSNumber *)number;
-- (bool) isVisiblyUninstalledInSection:(NSString *)section;
+- (bool) isVisibleInSection:(NSString *)section;
- (bool) isVisibleInSource:(Source *)source;
@end
CYString &rhi(PackageName(rhs, @selector(cyname)));
CFStringRef lhn(lhi), rhn(rhi);
+ if (lhn == NULL)
+ return rhn == NULL ? NSOrderedSame : NSOrderedAscending;
+ else if (rhn == NULL)
+ return NSOrderedDescending;
+
_profile(PackageNameCompare$NumbersLast)
if (!lhi.empty() && !rhi.empty()) {
UniChar lhc(CFStringGetCharacterAtIndex(lhn, 0));
if (latest_ != nil)
[latest_ release];
- if (installed_ != nil)
- [installed_ release];
if (sponsor$_ != nil)
[sponsor$_ release];
{"depiction", &depiction_},
{"homepage", &homepage_},
{"website", &website},
+ {"bugs", &bugs_},
{"support", &support_},
{"sponsor", &sponsor_},
{"author", &author_},
_end
_profile(Package$parse$Retain)
- if (!homepage_.empty())
+ if (homepage_.empty())
homepage_ = website;
if (homepage_ == depiction_)
homepage_.clear();
_end
}
+- (void) setVisible {
+ visible_ = required_ && [self unfiltered];
+}
+
- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
if ((self = [super init]) != nil) {
_profile(Package$initWithVersion)
_profile(Package$initWithVersion$Versions)
current = iterator_.CurrentVer();
if (!current.end())
- installed_ = (NSString *) StripVersion(current.VerStr());
+ installed_.set(pool_, StripVersion_(current.VerStr()));
if (!version_.end())
file_ = version_.FileList();
_end
}
+ required_ = true;
+
_profile(Package$initWithVersion$Tags)
pkgCache::TagIterator tag(iterator_.TagList());
if (!tag.end()) {
do {
const char *name(tag.Name());
[tags_ addObject:(NSString *)CFCString(name)];
- if (role_ == nil && strncmp(name, "role::", 6) == 0)
+ if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
role_ = (NSString *) CFCString(name + 6);
+ if (required_ && strncmp(name, "require::", 9) == 0 && (
+ true
+ ))
+ required_ = false;
++tag;
} while (!tag.end());
}
section_.set(pool_, iterator_.Section());
_end
+ obsolete_ = [self hasTag:@"cydia::obsolete"];
essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
- visible_ = [self hasSupportingRole] && [self unfiltered];
+ [self setVisible];
} _end } return self;
}
+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
+@synchronized ([Database class]) {
pkgCache::VerIterator version;
_profile(Package$packageWithIterator$GetCandidateVer)
inPool:pool
database:database
] autorelease];
-}
+} }
- (pkgCache::PkgIterator) iterator {
return iterator_;
}
- (NSString *) longSection {
- return LocalizeSection(section_);
+ return LocalizeSection([self section]);
}
- (NSString *) shortSection {
return installed_;
}
+- (BOOL) uninstalled {
+ return installed_.empty();
+}
+
- (BOOL) valid {
return !version_.end();
}
- (BOOL) unfiltered {
NSString *section([self section]);
- return section == nil || isSectionVisible(section);
+ return !obsolete_ && [self hasSupportingRole] && (section == nil || isSectionVisible(section));
}
- (BOOL) visible {
return @"UPGRADE";
case 2:
return @"NEW_INSTALL";
- default:
- _assert(false);
+ _nodefault
}
- default:
- _assert(false);
+ _nodefault
}
}
}
- (NSString *) depiction {
- return depiction_;
+ return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_];
}
- (Address *) sponsor {
}
- (NSString *) support {
- return !support_.empty() ? support_ : [[self source] supportForPackage:id_];
+ return !bugs_.empty() ? bugs_ : [[self source] supportForPackage:id_];
}
- (NSArray *) files {
size_t length(strlen(name));
if (length < 2) invalid:
- [warnings addObject:CYLocalize("ILLEGAL_PACKAGE_IDENTIFIER")];
+ [warnings addObject:UCLocalize("ILLEGAL_PACKAGE_IDENTIFIER")];
else for (size_t i(0); i != length; ++i)
if (
/* XXX: technically this is not allowed */
if (strcmp(name, "cydia") != 0) {
bool cydia = false;
+ bool user = false;
bool _private = false;
bool stash = false;
for (NSString *file in files)
if (!cydia && [file isEqualToString:@"/Applications/Cydia.app"])
cydia = true;
+ else if (!user && [file isEqualToString:@"/User"])
+ user = true;
else if (!_private && [file isEqualToString:@"/private"])
_private = true;
else if (!stash && [file isEqualToString:@"/var/stash"])
/* XXX: this is not sensitive enough. only some folders are valid. */
if (cydia && !repository)
- [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]];
+ [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]];
+ if (user)
+ [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/User"]];
if (_private)
- [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/private"]];
+ [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
if (stash)
- [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
+ [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
}
return [warnings count] == 0 ? nil : warnings;
_end
}
+- (bool) isUnfilteredAndSelectedForBy:(NSString *)search {
+ if ([search length] == 0)
+ return false;
+
+ _profile(Package$isUnfilteredAndSelectedForBy)
+ bool value(true);
+
+ _profile(Package$isUnfilteredAndSelectedForBy$Unfiltered)
+ value &= [self unfiltered];
+ _end
+
+ _profile(Package$isUnfilteredAndSelectedForBy$Match)
+ value &= [[self name] compare:search options:MatchCompareOptions_ range:NSMakeRange(0, [search length])] == NSOrderedSame;
+ _end
+
+ return value;
+ _end
+}
+
- (bool) isInstalledAndVisible:(NSNumber *)number {
- return (![number boolValue] || [self visible]) && [self installed] != nil;
+ return (![number boolValue] || [self visible]) && ![self uninstalled];
}
-- (bool) isVisiblyUninstalledInSection:(NSString *)name {
+- (bool) isVisibleInSection:(NSString *)name {
NSString *section = [self section];
return
- [self visible] &&
- [self installed] == nil && (
+ [self visible] && (
name == nil ||
section == nil && [name length] == 0 ||
[name isEqualToString:section]
/* XXX: localize the index thingees */
- (Section *) initWithIndex:(unichar)index row:(size_t)row {
if ((self = [super init]) != nil) {
- name_ = [(index == '#' ? @"123" : [NSString stringWithCharacters:&index length:1]) retain];
+ name_ = [[NSString stringWithCharacters:&index length:1] retain];
index_ = index;
row_ = row;
} return self;
@end
/* }}} */
-static int Finish_;
-static NSArray *Finishes_;
+static NSString *Colon_;
+static NSString *Error_;
+static NSString *Warning_;
/* Database Implementation {{{ */
@implementation Database
}
}
- _assert(false);
+ _assume(false);
}
- (void) _readStatus:(NSNumber *)fd { _pooled
while (std::getline(is, line)) {
const char *data(line.c_str());
- size_t size = line.size();
+ size_t size(line.size());
lprintf("S:%s\n", data);
if (conffile_r(data, size)) {
NSString *string = pmstatus_r[4];
if (type == "pmerror")
- [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+ [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
withObject:[NSArray arrayWithObjects:string, id, nil]
waitUntilDone:YES
];
[delegate_ setProgressTitle:string];
} else if (type == "pmconffile")
[delegate_ setConfigurationData:string];
- else _assert(false);
- } else _assert(false);
+ else
+ lprintf("E:unknown pmstatus\n");
+ } else
+ lprintf("E:unknown status\n");
}
- _assert(false);
+ _assume(false);
}
- (void) _readOutput:(NSNumber *)fd { _pooled
[delegate_ addProgressOutput:[NSString stringWithUTF8String:line.c_str()]];
}
- _assert(false);
+ _assume(false);
}
- (FILE *) input {
}
- (Package *) packageWithName:(NSString *)name {
+@synchronized ([Database class]) {
if (static_cast<pkgDepCache *>(cache_) == NULL)
return nil;
pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:pool_ database:self];
-}
+} }
- (Database *) init {
if ((self = [super init]) != nil) {
[entry addObject:failure];
[failure addObject:[NSString stringWithUTF8String:start.DepType()]];
- Package *package([self packageWithName:[NSString stringWithUTF8String:start.TargetPkg().Name()]]);
- [failure addObject:[package name]];
+ NSString *name([NSString stringWithUTF8String:start.TargetPkg().Name()]);
+ if (Package *package = [self packageWithName:name])
+ name = [package name];
+ [failure addObject:name];
pkgCache::PkgIterator target(start.TargetPkg());
if (target->ProvidesList != 0)
return issues;
}
+- (bool) popErrorWithTitle:(NSString *)title {
+ bool fatal(false);
+ std::string message;
+
+ while (!_error->empty()) {
+ std::string error;
+ bool warning(!_error->PopMessage(error));
+ if (!warning)
+ fatal = true;
+ for (;;) {
+ size_t size(error.size());
+ if (size == 0 || error[size - 1] != '\n')
+ break;
+ error.resize(size - 1);
+ }
+ lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
+
+ if (!message.empty())
+ message += "\n\n";
+ message += error;
+ }
+
+ if (fatal && !message.empty())
+ [delegate_ _setProgressError:[NSString stringWithUTF8String:message.c_str()] withTitle:[NSString stringWithFormat:Colon_, fatal ? Error_ : Warning_, title]];
+
+ return fatal;
+}
+
+- (bool) popErrorWithTitle:(NSString *)title forOperation:(bool)success {
+ return [self popErrorWithTitle:title] || !success;
+}
+
- (void) reloadData { _pooled
+@synchronized ([Database class]) {
@synchronized (self) {
++era_;
}
if (chk != -1)
close(chk);
+ NSString *title(UCLocalize("DATABASE"));
+
_trace();
- if (!cache_.Open(progress_, true)) {
+ if (!cache_.Open(progress_, true)) { pop:
std::string error;
- if (!_error->PopMessage(error))
- _assert(false);
- _error->Discard();
+ bool warning(!_error->PopMessage(error));
lprintf("cache_.Open():[%s]\n", error.c_str());
if (error == "dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem. ")
// else if (error == "Could not open lock file /var/lib/dpkg/lock - open (13 Permission denied)")
// else if (error == "Could not get lock /var/lib/dpkg/lock - open (35 Resource temporarily unavailable)")
// else if (error == "The list of sources could not be read.")
- else _assert(false);
+ else
+ [delegate_ _setProgressError:[NSString stringWithUTF8String:error.c_str()] withTitle:[NSString stringWithFormat:Colon_, warning ? Warning_ : Error_, title]];
+ if (warning)
+ goto pop;
+ _error->Discard();
return;
}
_trace();
lock_ = NULL;
list_ = new pkgSourceList();
- _assert(list_->ReadMainList());
-
- _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
- _assert(pkgApplyStatus(cache_));
+ if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
+ return;
- if (cache_->BrokenCount() != 0) {
- _assert(pkgFixBroken(cache_));
- _assert(cache_->BrokenCount() == 0);
- _assert(pkgMinimizeUpgrade(cache_));
+ if (cache_->DelCount() != 0 || cache_->InstCount() != 0) {
+ [delegate_ _setProgressError:@"COUNTS_NONZERO_EX" withTitle:title];
+ return;
+ }
+
+ if ([self popErrorWithTitle:title forOperation:pkgApplyStatus(cache_)])
+ return;
+
+ if (cache_->BrokenCount() != 0) {
+ if ([self popErrorWithTitle:title forOperation:pkgFixBroken(cache_)])
+ return;
+
+ if (cache_->BrokenCount() != 0) {
+ [delegate_ _setProgressError:@"STILL_BROKEN_EX" withTitle:title];
+ return;
+ }
+
+ if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
+ return;
}
_trace();
_trace();
}
-}
+} }
- (void) configure {
NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
system([dpkg UTF8String]);
}
-- (void) clean {
+- (bool) clean {
+ // XXX: I don't remember this condition
if (lock_ != NULL)
- return;
+ return false;
FileFd Lock;
Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
- _assert(!_error->PendingError());
+
+ NSString *title(UCLocalize("CLEAN_ARCHIVES"));
+
+ if ([self popErrorWithTitle:title])
+ return false;
pkgAcquire fetcher;
fetcher.Clean(_config->FindDir("Dir::Cache::Archives"));
}
} cleaner;
- if (!cleaner.Go(_config->FindDir("Dir::Cache::Archives") + "partial/", cache_)) {
- std::string error;
- while (_error->PopMessage(error))
- lprintf("ArchiveCleaner: %s\n", error.c_str());
- }
+ if ([self popErrorWithTitle:title forOperation:cleaner.Go(_config->FindDir("Dir::Cache::Archives") + "partial/", cache_)])
+ return false;
+
+ return true;
}
-- (void) prepare {
+- (bool) prepare {
+ fetcher_->Shutdown();
+
pkgRecords records(cache_);
lock_ = new FileFd();
lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
- _assert(!_error->PendingError());
+
+ NSString *title(UCLocalize("PREPARE_ARCHIVES"));
+
+ if ([self popErrorWithTitle:title])
+ return false;
pkgSourceList list;
- // XXX: explain this with an error message
- _assert(list.ReadMainList());
+ if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ return false;
manager_ = (_system->CreatePM(cache_));
- _assert(manager_->GetArchives(fetcher_, &list, &records));
- _assert(!_error->PendingError());
+ if ([self popErrorWithTitle:title forOperation:manager_->GetArchives(fetcher_, &list, &records)])
+ return false;
+
+ return true;
}
- (void) perform {
+ NSString *title(UCLocalize("PERFORM_SELECTIONS"));
+
NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; {
pkgSourceList list;
- _assert(list.ReadMainList());
+ if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ return;
for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
[before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
}
for (pkgAcquire::ItemIterator item = fetcher_->ItemsBegin(); item != fetcher_->ItemsEnd(); item++) {
if ((*item)->Status == pkgAcquire::Item::StatDone && (*item)->Complete)
continue;
+ if ((*item)->Status == pkgAcquire::Item::StatIdle)
+ continue;
std::string uri = (*item)->DescURI();
std::string error = (*item)->ErrorText;
lprintf("pAf:%s:%s\n", uri.c_str(), error.c_str());
failed = true;
- [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+ [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
withObject:[NSArray arrayWithObjects:
[NSString stringWithUTF8String:error.c_str()],
nil]
NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; {
pkgSourceList list;
- _assert(list.ReadMainList());
+ if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ return;
for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
[after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
}
[self update];
}
-- (void) upgrade {
- _assert(pkgDistUpgrade(cache_));
+- (bool) upgrade {
+ NSString *title(UCLocalize("UPGRADE"));
+ if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)])
+ return false;
+ return true;
}
- (void) update {
[self updateWithStatus:status_];
}
+- (void) setVisible {
+ for (Package *package in packages_)
+ [package setVisible];
+}
+
- (void) updateWithStatus:(Status &)status {
+ _transient NSObject<ProgressDelegate> *delegate(status.getDelegate());
+ NSString *title(UCLocalize("REFRESHING_DATA"));
+
pkgSourceList list;
- _assert(list.ReadMainList());
+ if (!list.ReadMainList())
+ [delegate _setProgressError:@"Unable to read source list." withTitle:title];
FileFd lock;
lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
- _assert(!_error->PendingError());
-
- pkgAcquire fetcher(&status);
- _assert(list.GetIndexes(&fetcher));
-
- if (fetcher.Run(PulseInterval_) != pkgAcquire::Failed) {
- bool failed = false;
- for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
- if ((*item)->Status != pkgAcquire::Item::StatDone) {
- (*item)->Finished();
- failed = true;
- }
+ if ([self popErrorWithTitle:title])
+ return;
- if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
- _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
- _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
- }
+ if ([self popErrorWithTitle:title forOperation:ListUpdate(status, list, PulseInterval_)])
+ /* XXX: ignore this because users suck and don't understand why refreshing is important: return */;
- [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
- Changed_ = true;
- }
+ [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
+ Changed_ = true;
}
- (void) setDelegate:(id)delegate {
}
- (Source *) getSource:(pkgCache::PkgFileIterator)file {
- return sources_[file->ID];
+ SourceMap::const_iterator i(sources_.find(file->ID));
+ return i == sources_.end() ? nil : i->second;
}
@end
/* }}} */
-/* PopUp Windows {{{ */
-@interface PopUpView : UIView {
- _transient id delegate_;
- UITransitionView *transition_;
- UIView *overlay_;
+/* Confirmation Controller {{{ */
+bool DepSubstrate(const pkgCache::VerIterator &iterator) {
+ if (!iterator.end())
+ for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) {
+ if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends)
+ continue;
+ pkgCache::PkgIterator package(dep.TargetPkg());
+ if (package.end())
+ continue;
+ if (strcmp(package.Name(), "mobilesubstrate") == 0)
+ return true;
+ }
+
+ return false;
}
+/* }}} */
-- (void) cancel;
-- (id) initWithView:(UIView *)view delegate:(id)delegate;
+/* Web Scripting {{{ */
+@interface CydiaObject : NSObject {
+ id indirect_;
+ id delegate_;
+}
+- (id) initWithDelegate:(IndirectDelegate *)indirect;
@end
-@implementation PopUpView
+@implementation CydiaObject
- (void) dealloc {
- [transition_ setDelegate:nil];
- [transition_ release];
- [overlay_ release];
+ [indirect_ release];
[super dealloc];
}
-- (void) cancel {
- [transition_ transition:UITransitionPushFromTop toView:nil];
+- (id) initWithDelegate:(IndirectDelegate *)indirect {
+ if ((self = [super init]) != nil) {
+ indirect_ = [indirect retain];
+ } return self;
}
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
- if (from != nil && to == nil)
- [self removeFromSuperview];
+- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
}
-- (id) initWithView:(UIView *)view delegate:(id)delegate {
- if ((self = [super initWithFrame:[view bounds]]) != nil) {
- delegate_ = delegate;
++ (NSArray *) _attributeKeys {
+ return [NSArray arrayWithObjects:@"device", @"firewire", @"imei", @"mac", @"serial", nil];
+}
- transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
- [self addSubview:transition_];
+- (NSArray *) attributeKeys {
+ return [[self class] _attributeKeys];
+}
- overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
++ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
+ return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
+}
- [view addSubview:self];
+- (NSString *) device {
+ return [[UIDevice currentDevice] uniqueIdentifier];
+}
- [transition_ setDelegate:self];
+#if 0 // XXX: implement!
+- (NSString *) mac {
+ if (![indirect_ promptForSensitive:@"Mac Address"])
+ return nil;
+}
- UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
- [transition_ transition:UITransitionNone toView:blank];
- [transition_ transition:UITransitionPushFromBottom toView:overlay_];
- } return self;
+- (NSString *) serial {
+ if (![indirect_ promptForSensitive:@"Serial #"])
+ return nil;
}
-@end
-/* }}} */
+- (NSString *) firewire {
+ if (![indirect_ promptForSensitive:@"Firewire GUID"])
+ return nil;
+}
-#if 0
-/* Mail Composition {{{ */
-@interface MailToView : PopUpView {
- MailComposeController *controller_;
+- (NSString *) imei {
+ if (![indirect_ promptForSensitive:@"IMEI"])
+ return nil;
}
+#endif
-- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url;
++ (NSString *) webScriptNameForSelector:(SEL)selector {
+ if (selector == @selector(close))
+ return @"close";
+ else if (selector == @selector(getInstalledPackages))
+ return @"getInstalledPackages";
+ else if (selector == @selector(getPackageById:))
+ return @"getPackageById";
+ else if (selector == @selector(installPackages:))
+ return @"installPackages";
+ else if (selector == @selector(setAutoPopup:))
+ return @"setAutoPopup";
+ else if (selector == @selector(setButtonImage:withStyle:toFunction:))
+ return @"setButtonImage";
+ else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
+ return @"setButtonTitle";
+ else if (selector == @selector(setFinishHook:))
+ return @"setFinishHook";
+ else if (selector == @selector(setPopupHook:))
+ return @"setPopupHook";
+ else if (selector == @selector(setSpecial:))
+ return @"setSpecial";
+ else if (selector == @selector(setToken:))
+ return @"setToken";
+ else if (selector == @selector(setViewportWidth:))
+ return @"setViewportWidth";
+ else if (selector == @selector(supports:))
+ return @"supports";
+ else if (selector == @selector(stringWithFormat:arguments:))
+ return @"format";
+ else if (selector == @selector(localizedStringForKey:value:table:))
+ return @"localize";
+ else if (selector == @selector(du:))
+ return @"du";
+ else if (selector == @selector(statfs:))
+ return @"statfs";
+ else
+ return nil;
+}
-@end
++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
+ return [self webScriptNameForSelector:selector] == nil;
+}
-@implementation MailToView
+- (BOOL) supports:(NSString *)feature {
+ return [feature isEqualToString:@"window.open"];
+}
-- (void) dealloc {
- [controller_ release];
- [super dealloc];
+- (NSArray *) getInstalledPackages {
+ NSArray *packages([[Database sharedInstance] packages]);
+ NSMutableArray *installed([NSMutableArray arrayWithCapacity:[packages count]]);
+ for (Package *package in packages)
+ if ([package installed] != nil)
+ [installed addObject:package];
+ return installed;
+}
+
+- (Package *) getPackageById:(NSString *)id {
+ Package *package([[Database sharedInstance] packageWithName:id]);
+ [package parse];
+ return package;
+}
+
+- (NSArray *) statfs:(NSString *)path {
+ struct statfs stat;
+
+ if (path == nil || statfs([path UTF8String], &stat) == -1)
+ return nil;
+
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithUnsignedLong:stat.f_bsize],
+ [NSNumber numberWithUnsignedLong:stat.f_blocks],
+ [NSNumber numberWithUnsignedLong:stat.f_bfree],
+ nil];
}
-- (void) mailComposeControllerWillAttemptToSend:(MailComposeController *)controller {
- NSLog(@"will");
+- (NSNumber *) du:(NSString *)path {
+ NSNumber *value(nil);
+
+ int fds[2];
+ _assert(pipe(fds) != -1);
+
+ pid_t pid(ExecFork());
+ if (pid == 0) {
+ _assert(dup2(fds[1], 1) != -1);
+ _assert(close(fds[0]) != -1);
+ _assert(close(fds[1]) != -1);
+ /* XXX: this should probably not use du */
+ execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL);
+ exit(1);
+ _assert(false);
+ }
+
+ _assert(close(fds[1]) != -1);
+
+ if (FILE *du = fdopen(fds[0], "r")) {
+ char line[1024];
+ while (fgets(line, sizeof(line), du) != NULL) {
+ size_t length(strlen(line));
+ while (length != 0 && line[length - 1] == '\n')
+ line[--length] = '\0';
+ if (char *tab = strchr(line, '\t')) {
+ *tab = '\0';
+ value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)];
+ }
+ }
+
+ fclose(du);
+ } else _assert(close(fds[0]));
+
+ int status;
+ wait:
+ if (waitpid(pid, &status, 0) == -1)
+ if (errno == EINTR)
+ goto wait;
+ else _assert(false);
+
+ return value;
}
-- (void) mailComposeControllerDidAttemptToSend:(MailComposeController *)controller mailDelivery:(id)delivery {
- NSLog(@"did:%@", delivery);
-// [UIApp setStatusBarShowsProgress:NO];
-if ([controller error]){
-NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil];
-UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
-[mailAlertSheet setBodyText:[controller error]];
-[mailAlertSheet popupAlertAnimated:YES];
+- (void) close {
+ [indirect_ close];
}
+
+- (void) installPackages:(NSArray *)packages {
+ [delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
}
-- (void) showError {
- NSLog(@"%@", [controller_ error]);
- NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil];
- UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
- [mailAlertSheet setBodyText:[controller_ error]];
- [mailAlertSheet popupAlertAnimated:YES];
+- (void) setAutoPopup:(BOOL)popup {
+ [indirect_ setAutoPopup:popup];
}
-- (void) deliverMessage { _pooled
- setuid(501);
- setgid(501);
+- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
+ [indirect_ setButtonImage:button withStyle:style toFunction:function];
+}
- if (![controller_ deliverMessage])
- [self performSelectorOnMainThread:@selector(showError) withObject:nil waitUntilDone:NO];
+- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
+ [indirect_ setButtonTitle:button withStyle:style toFunction:function];
}
-- (void) mailComposeControllerCompositionFinished:(MailComposeController *)controller {
- if ([controller_ needsDelivery])
- [NSThread detachNewThreadSelector:@selector(deliverMessage) toTarget:self withObject:nil];
- else
- [self cancel];
+- (void) setSpecial:(id)function {
+ [indirect_ setSpecial:function];
}
-- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url {
- if ((self = [super initWithView:view delegate:delegate]) != nil) {
- controller_ = [[MailComposeController alloc] initForContentSize:[overlay_ bounds].size];
- [controller_ setDelegate:self];
- [controller_ initializeUI];
- [controller_ setupForURL:url];
+- (void) setToken:(NSString *)token {
+ if (Token_ != nil)
+ [Token_ release];
+ Token_ = [token retain];
- UIView *view([controller_ view]);
- [overlay_ addSubview:view];
- } return self;
+ [Metadata_ setObject:Token_ forKey:@"Token"];
+ Changed_ = true;
+}
+
+- (void) setFinishHook:(id)function {
+ [indirect_ setFinishHook:function];
+}
+
+- (void) setPopupHook:(id)function {
+ [indirect_ setPopupHook:function];
+}
+
+- (void) setViewportWidth:(float)width {
+ [indirect_ setViewportWidth:width];
+}
+
+- (NSString *) stringWithFormat:(NSString *)format arguments:(WebScriptObject *)arguments {
+ //NSLog(@"SWF:\"%@\" A:%@", format, [arguments description]);
+ unsigned count([arguments count]);
+ id values[count];
+ for (unsigned i(0); i != count; ++i)
+ values[i] = [arguments objectAtIndex:i];
+ return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast<va_list>(values)] autorelease];
+}
+
+- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table {
+ if (reinterpret_cast<id>(value) == [WebUndefined undefined])
+ value = nil;
+ if (reinterpret_cast<id>(table) == [WebUndefined undefined])
+ table = nil;
+ return [[NSBundle mainBundle] localizedStringForKey:key value:value table:table];
}
@end
/* }}} */
-#endif
-/* Confirmation View {{{ */
-bool DepSubstrate(const pkgCache::VerIterator &iterator) {
- if (!iterator.end())
- for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) {
- if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends)
- continue;
- pkgCache::PkgIterator package(dep.TargetPkg());
- if (package.end())
- continue;
- if (strcmp(package.Name(), "mobilesubstrate") == 0)
- return true;
- }
+/* Cydia View Controller {{{ */
+@interface CYViewController : UCViewController { }
+@end
- return false;
+@implementation CYViewController
+@end
+/* }}} */
+
+@interface CYBrowserController : BrowserController {
+ CydiaObject *cydia_;
+}
+
+@end
+
+@implementation CYBrowserController
+
+- (void) dealloc {
+ [cydia_ release];
+ [super dealloc];
+}
+
+- (void) setHeaders:(NSDictionary *)headers forHost:(NSString *)host {
+}
+
+- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
+ [super webView:sender didClearWindowObject:window forFrame:frame];
+
+ 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 (
+ [host isEqualToString:@"cydia.saurik.com"] ||
+ [host hasSuffix:@".cydia.saurik.com"] ||
+ [scheme isEqualToString:@"file"]
+ )
+ [window setValue:cydia_ forKey:@"cydia"];
+}
+
+- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
+ if (System_ != NULL)
+ [request setValue:System_ forHTTPHeaderField:@"X-System"];
+ if (Machine_ != NULL)
+ [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
+ if (Token_ != nil)
+ [request setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
+ if (Role_ != nil)
+ [request setValue:Role_ forHTTPHeaderField:@"X-Role"];
+}
+
+- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
+ NSMutableURLRequest *copy = [request mutableCopy];
+ [self _setMoreHeaders:copy];
+ return copy;
+}
+
+- (void) setDelegate:(id)delegate {
+ [super setDelegate:delegate];
+ [cydia_ setDelegate:delegate];
+}
+
+- (id) init {
+ if ((self = [super initWithWidth:[[self view] bounds].size.width ofClass:[CYBrowserController class]]) != nil) {
+ cydia_ = [[CydiaObject alloc] initWithDelegate:indirect_];
+
+ WebView *webview([document_ webView]);
+
+ Package *package([[Database sharedInstance] packageWithName:@"cydia"]);
+
+ NSString *application = package == nil ? @"Cydia" : [NSString
+ stringWithFormat:@"Cydia/%@",
+ [package installed]
+ ];
+
+ if (Safari_ != nil)
+ application = [NSString stringWithFormat:@"Safari/%@ %@", Safari_, application];
+ if (Build_ != nil)
+ application = [NSString stringWithFormat:@"Mobile/%@ %@", Build_, application];
+ if (Product_ != nil)
+ application = [NSString stringWithFormat:@"Version/%@ %@", Product_, application];
+
+ [webview setApplicationNameForUserAgent:application];
+ } return self;
}
-@protocol ConfirmationViewDelegate
-- (void) cancel;
-- (void) confirm;
+@end
+
+@protocol ConfirmationControllerDelegate
+- (void) cancelAndClear:(bool)clear;
+- (void) confirmWithNavigationController:(UINavigationController *)navigation;
- (void) queue;
@end
-@interface ConfirmationView : BrowserView {
+@interface ConfirmationController : CYBrowserController {
_transient Database *database_;
- UIActionSheet *essential_;
+ UIAlertView *essential_;
NSArray *changes_;
NSArray *issues_;
NSArray *sizes_;
BOOL substrate_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
@end
-@implementation ConfirmationView
+@implementation ConfirmationController
- (void) dealloc {
[changes_ release];
[super dealloc];
}
-- (void) cancel {
- [delegate_ cancel];
- [book_ popFromSuperviewAnimated:YES];
-}
-
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
+- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+ NSString *context([alert context]);
if ([context isEqualToString:@"remove"]) {
- switch (button) {
- case 1:
- [self cancel];
- break;
- case 2:
- if (substrate_)
- Finish_ = 2;
- [delegate_ confirm];
- break;
- default:
- _assert(false);
+ if (button == [alert cancelButtonIndex]) {
+ [self dismissModalViewControllerAnimated:YES];
+ } else if (button == [alert firstOtherButtonIndex]) {
+ if (substrate_)
+ Finish_ = 2;
+ [delegate_ confirmWithNavigationController:[self navigationController]];
}
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
} else if ([context isEqualToString:@"unable"]) {
- [self cancel];
- [sheet dismiss];
- } else
- [super alertSheet:sheet buttonClicked:button];
+ [self dismissModalViewControllerAnimated:YES];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
+ } else {
+ [super alertView:alert clickedButtonAtIndex:button];
+ }
+}
+
+- (id) invokeDefaultMethodWithArguments:(NSArray *)args {
+ [self dismissModalViewControllerAnimated:YES];
+ [delegate_ cancelAndClear:NO];
+
+ return nil;
}
- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
[window setValue:changes_ forKey:@"changes"];
[window setValue:issues_ forKey:@"issues"];
[window setValue:sizes_ forKey:@"sizes"];
+ [window setValue:self forKey:@"queue"];
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
database_ = database;
+ [[self navigationItem] setTitle:UCLocalize("CONFIRM")];
+
NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
NSMutableArray *reinstalling = [NSMutableArray arrayWithCapacity:16];
NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
if (!remove)
essential_ = nil;
- else if (Advanced_ || true) {
- NSString *parenthetical(CYLocalize("PARENTHETICAL"));
-
- essential_ = [[UIActionSheet alloc]
- initWithTitle:CYLocalize("REMOVING_ESSENTIALS")
- buttons:[NSArray arrayWithObjects:
- [NSString stringWithFormat:parenthetical, CYLocalize("CANCEL_OPERATION"), CYLocalize("SAFE")],
- [NSString stringWithFormat:parenthetical, CYLocalize("FORCE_REMOVAL"), CYLocalize("UNSAFE")],
- nil]
- defaultButtonIndex:0
+ else if (Advanced_) {
+ NSString *parenthetical(UCLocalize("PARENTHETICAL"));
+
+ essential_ = [[UIAlertView alloc]
+ initWithTitle:UCLocalize("REMOVING_ESSENTIALS")
+ message:UCLocalize("REMOVING_ESSENTIALS_EX")
delegate:self
- context:@"remove"
+ cancelButtonTitle:[NSString stringWithFormat:parenthetical, UCLocalize("CANCEL_OPERATION"), UCLocalize("SAFE")]
+ otherButtonTitles:[NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")], nil
];
-#ifndef __OBJC2__
- [essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]];
-#endif
- [essential_ setBodyText:CYLocalize("REMOVING_ESSENTIALS_EX")];
+ [essential_ setContext:@"remove"];
} else {
- essential_ = [[UIActionSheet alloc]
- initWithTitle:CYLocalize("UNABLE_TO_COMPLY")
- buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
- defaultButtonIndex:0
+ essential_ = [[UIAlertView alloc]
+ initWithTitle:UCLocalize("UNABLE_TO_COMPLY")
+ message:UCLocalize("UNABLE_TO_COMPLY_EX")
delegate:self
- context:@"unable"
+ cancelButtonTitle:UCLocalize("OKAY")
+ otherButtonTitles:nil
];
- [essential_ setBodyText:CYLocalize("UNABLE_TO_COMPLY_EX")];
+ [essential_ setContext:@"unable"];
}
changes_ = [[NSArray alloc] initWithObjects:
sizes_ = [[NSArray alloc] initWithObjects:
SizeString([database_ fetcher].FetchNeeded()),
SizeString([database_ fetcher].PartialPresent()),
- SizeString([database_ cache]->UsrSize()),
nil];
[self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"confirm" ofType:@"html"]]];
- } return self;
-}
-
-- (NSString *) backButtonTitle {
- return CYLocalize("CONFIRM");
-}
-- (NSString *) leftButtonTitle {
- return [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("CANCEL"), CYLocalize("QUEUE")];
-}
-
-- (id) rightButtonTitle {
- return issues_ != nil ? nil : [super rightButtonTitle];
+ UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("CANCEL")
+ // OLD: [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("CANCEL"), UCLocalize("QUEUE")]
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(cancelButtonClicked)
+ ];
+ [[self navigationItem] setLeftBarButtonItem:leftItem];
+ [leftItem release];
+ } return self;
}
-- (id) _rightButtonTitle {
-#if AlwaysReload || IgnoreInstall
- return [super _rightButtonTitle];
+- (void) applyRightButton {
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("CONFIRM")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(confirmButtonClicked)
+ ];
+#if !AlwaysReload && !IgnoreInstall
+ if (issues_ == nil && ![self isLoading]) [[self navigationItem] setRightBarButtonItem:rightItem];
+ else [super applyRightButton];
#else
- return CYLocalize("CONFIRM");
+ [[self navigationItem] setRightBarButtonItem:nil];
#endif
+ [rightItem release];
}
-- (void) _leftButtonClicked {
- [self cancel];
+- (void) cancelButtonClicked {
+ [self dismissModalViewControllerAnimated:YES];
+ [delegate_ cancelAndClear:YES];
}
#if !AlwaysReload
-- (void) _rightButtonClicked {
+- (void) confirmButtonClicked {
#if IgnoreInstall
- return [super _rightButtonClicked];
+ return;
#endif
if (essential_ != nil)
- [essential_ popupAlertAnimated:YES];
+ [essential_ show];
else {
if (substrate_)
Finish_ = 2;
- [delegate_ confirm];
+ [delegate_ confirmWithNavigationController:[self navigationController]];
}
}
#endif
@end
/* }}} */
-/* Progress View {{{ */
-@interface ProgressView : UIView <
+/* Progress Controller {{{ */
+@interface ProgressController : CYViewController <
ConfigurationDelegate,
ProgressDelegate
> {
_transient Database *database_;
- UIView *view_;
- UIView *background_;
- UITransitionView *transition_;
- UIView *overlay_;
- UINavigationBar *navbar_;
UIProgressBar *progress_;
UITextView *output_;
UITextLabel *status_;
UIPushButton *close_;
- id delegate_;
BOOL running_;
SHA1SumValue springlist_;
SHA1SumValue notifyconf_;
- SHA1SumValue sandplate_;
+ NSString *title_;
}
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
-
-- (id) initWithFrame:(struct CGRect)frame database:(Database *)database delegate:(id)delegate;
-- (void) setContentView:(UIView *)view;
-- (void) resetView;
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate;
- (void) _retachThread;
- (void) _detachNewThreadData:(ProgressData *)data;
@end
-@protocol ProgressViewDelegate
-- (void) progressViewIsComplete:(ProgressView *)sender;
+@protocol ProgressControllerDelegate
+- (void) progressControllerIsComplete:(ProgressController *)sender;
@end
-@implementation ProgressView
+@implementation ProgressController
- (void) dealloc {
- [transition_ setDelegate:nil];
- [navbar_ setDelegate:nil];
-
- [view_ release];
- if (background_ != nil)
- [background_ release];
- [transition_ release];
- [overlay_ release];
- [navbar_ release];
+ [database_ setDelegate:nil];
[progress_ release];
[output_ release];
[status_ release];
[close_ release];
+ if (title_ != nil)
+ [title_ release];
[super dealloc];
}
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
- if (bootstrap_ && from == overlay_ && to == view_)
- exit(0);
-}
-
-- (id) initWithFrame:(struct CGRect)frame database:(Database *)database delegate:(id)delegate {
- if ((self = [super initWithFrame:frame]) != nil) {
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate {
+ if ((self = [super init]) != nil) {
database_ = database;
+ [database_ setDelegate:self];
delegate_ = delegate;
- transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
- [transition_ setDelegate:self];
-
- overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
-
- if (bootstrap_)
- [overlay_ setBackgroundColor:[UIColor blackColor]];
- else {
- background_ = [[UIView alloc] initWithFrame:[self bounds]];
- [background_ setBackgroundColor:[UIColor blackColor]];
- [self addSubview:background_];
- }
-
- [self addSubview:transition_];
-
- CGSize navsize = [UINavigationBar defaultSize];
- CGRect navrect = {{0, 0}, navsize};
-
- navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
- [overlay_ addSubview:navbar_];
+ [[self view] setBackgroundColor:(CGColor *)[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f]];
- [navbar_ setBarStyle:1];
- [navbar_ setDelegate:self];
-
- UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
- [navbar_ pushNavigationItem:navitem];
-
- CGRect bounds = [overlay_ bounds];
- CGSize prgsize = [UIProgressBar defaultSize];
-
- CGRect prgrect = {{
- (bounds.size.width - prgsize.width) / 2,
- bounds.size.height - prgsize.height - 20
- }, prgsize};
-
- progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
+ progress_ = [[UIProgressBar alloc] init];
+ [progress_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
[progress_ setStyle:0];
- status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
- 10,
- bounds.size.height - prgsize.height - 50,
- bounds.size.width - 20,
- 24
- )];
-
+ status_ = [[UITextLabel alloc] init];
+ [status_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
[status_ setColor:[UIColor whiteColor]];
[status_ setBackgroundColor:[UIColor clearColor]];
-
[status_ setCentersHorizontally:YES];
//[status_ setFont:font];
- _trace();
- output_ = [[UITextView alloc] initWithFrame:CGRectMake(
- 10,
- navrect.size.height + 20,
- bounds.size.width - 20,
- bounds.size.height - navsize.height - 62 - navrect.size.height
- )];
- _trace();
+ output_ = [[UITextView alloc] init];
+ [output_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
//[output_ setTextFont:@"Courier New"];
- [output_ setTextSize:12];
-
+ [output_ setFont:[[output_ font] fontWithSize:12]];
[output_ setTextColor:[UIColor whiteColor]];
[output_ setBackgroundColor:[UIColor clearColor]];
-
[output_ setMarginTop:0];
[output_ setAllowsRubberBanding:YES];
[output_ setEditable:NO];
+ [[self view] addSubview:output_];
- [overlay_ addSubview:output_];
-
- close_ = [[UIPushButton alloc] initWithFrame:CGRectMake(
- 10,
- bounds.size.height - prgsize.height - 50,
- bounds.size.width - 20,
- 32 + prgsize.height
- )];
-
+ close_ = [[UIPushButton alloc] init];
+ [close_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
[close_ setAutosizesToFit:NO];
[close_ setDrawsShadow:YES];
[close_ setStretchBackground:YES];
[close_ setEnabled:YES];
-
- UIFont *bold = [UIFont boldSystemFontOfSize:22];
- [close_ setTitleFont:bold];
-
- [close_ addTarget:self action:@selector(closeButtonPushed) forEvents:kUIControlEventMouseUpInside];
+ [close_ setTitleFont:[UIFont boldSystemFontOfSize:22]];
+ [close_ addTarget:self action:@selector(closeButtonPushed) forEvents:UIControlEventTouchUpInside];
[close_ setBackground:[UIImage applicationImageNamed:@"green-up.png"] forState:0];
[close_ setBackground:[UIImage applicationImageNamed:@"green-dn.png"] forState:1];
} return self;
}
-- (void) setContentView:(UIView *)view {
- view_ = [view retain];
-}
-
-- (void) resetView {
- [transition_ transition:6 toView:view_];
-}
-
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
-
- if ([context isEqualToString:@"error"])
- [sheet dismiss];
- else if ([context isEqualToString:@"conffile"]) {
+- (void) positionViews {
+ CGRect bounds = [[self view] bounds];
+ CGSize prgsize = [UIProgressBar defaultSize];
+
+ CGRect prgrect = {{
+ (bounds.size.width - prgsize.width) / 2,
+ bounds.size.height - prgsize.height - 64
+ }, prgsize};
+
+ float closewidth = bounds.size.width - 20;
+ if (closewidth > 300) closewidth = 300;
+
+ [progress_ setFrame:prgrect];
+ [status_ setFrame:CGRectMake(
+ 10,
+ bounds.size.height - prgsize.height - 94,
+ bounds.size.width - 20,
+ 24
+ )];
+ [output_ setFrame:CGRectMake(
+ 10,
+ 20,
+ bounds.size.width - 20,
+ bounds.size.height - 106
+ )];
+ [close_ setFrame:CGRectMake(
+ (bounds.size.width - closewidth) / 2,
+ bounds.size.height - prgsize.height - 94,
+ closewidth,
+ 32 + prgsize.height
+ )];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [[self navigationItem] setHidesBackButton:YES];
+ [[[self navigationController] navigationBar] setBarStyle:1];
+
+ [self positionViews];
+}
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+ [self positionViews];
+}
+
+- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+ NSString *context([alert context]);
+
+ if ([context isEqualToString:@"conffile"]) {
FILE *input = [database_ input];
-
- switch (button) {
- case 1:
- fprintf(input, "N\n");
- fflush(input);
- break;
- case 2:
- fprintf(input, "Y\n");
- fflush(input);
- break;
- default:
- _assert(false);
- }
-
- [sheet dismiss];
+ if (button == [alert cancelButtonIndex]) fprintf(input, "N\n");
+ else if (button == [alert firstOtherButtonIndex]) fprintf(input, "Y\n");
+ fflush(input);
}
}
- (void) closeButtonPushed {
running_ = NO;
+ UpdateExternalStatus(0);
+
switch (Finish_) {
case 0:
- [self resetView];
+ [self dismissModalViewControllerAnimated:YES];
break;
case 1:
- [delegate_ suspendWithAnimation:YES];
+ [delegate_ terminateWithSuccess];
+ /*if ([delegate_ respondsToSelector:@selector(suspendWithAnimation:)])
+ [delegate_ suspendWithAnimation:YES];
+ else
+ [delegate_ suspend];*/
break;
case 2:
}
- (void) _retachThread {
- UINavigationItem *item = [navbar_ topItem];
- [item setTitle:CYLocalize("COMPLETE")];
+ [[self navigationItem] setTitle:UCLocalize("COMPLETE")];
- [overlay_ addSubview:close_];
+ [[self view] addSubview:close_];
[progress_ removeFromSuperview];
[status_ removeFromSuperview];
- [delegate_ progressViewIsComplete:self];
-
- if (Finish_ < 4) {
- FileFd file(SandboxTemplate_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(sandplate_ == sha1.Result()))
- Finish_ = 4;
- }
+ [database_ popErrorWithTitle:title_];
+ [delegate_ progressControllerIsComplete:self];
if (Finish_ < 4) {
- FileFd file(NotifyConfig_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(notifyconf_ == sha1.Result()))
- Finish_ = 4;
+ FileFd file;
+ if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ if (!(notifyconf_ == sha1.Result()))
+ Finish_ = 4;
+ }
}
if (Finish_ < 3) {
- FileFd file(SpringBoard_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(springlist_ == sha1.Result()))
- Finish_ = 3;
+ FileFd file;
+ if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ if (!(springlist_ == sha1.Result()))
+ Finish_ = 3;
+ }
}
switch (Finish_) {
- case 0: [close_ setTitle:CYLocalize("RETURN_TO_CYDIA")]; break;
- case 1: [close_ setTitle:CYLocalize("CLOSE_CYDIA")]; break;
- case 2: [close_ setTitle:CYLocalize("RESTART_SPRINGBOARD")]; break;
- case 3: [close_ setTitle:CYLocalize("RELOAD_SPRINGBOARD")]; break;
- case 4: [close_ setTitle:CYLocalize("REBOOT_DEVICE")]; break;
- }
-
-#define Cache_ "/User/Library/Caches/com.apple.mobile.installation.plist"
-
- if (NSMutableDictionary *cache = [[NSMutableDictionary alloc] initWithContentsOfFile:@ Cache_]) {
- [cache autorelease];
-
- NSFileManager *manager = [NSFileManager defaultManager];
- NSError *error = nil;
-
- id system = [cache objectForKey:@"System"];
- if (system == nil)
- goto error;
-
- struct stat info;
- if (stat(Cache_, &info) == -1)
- goto error;
-
- [system removeAllObjects];
-
- if (NSArray *apps = [manager contentsOfDirectoryAtPath:@"/Applications" error:&error]) {
- for (NSString *app in apps)
- if ([app hasSuffix:@".app"]) {
- NSString *path = [@"/Applications" stringByAppendingPathComponent:app];
- NSString *plist = [path stringByAppendingPathComponent:@"Info.plist"];
- if (NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithContentsOfFile:plist]) {
- [info autorelease];
- if ([info objectForKey:@"CFBundleIdentifier"] != nil) {
- [info setObject:path forKey:@"Path"];
- [info setObject:@"System" forKey:@"ApplicationType"];
- [system addInfoDictionary:info];
- }
- }
- }
- } else goto error;
-
- [cache writeToFile:@Cache_ atomically:YES];
-
- if (chown(Cache_, info.st_uid, info.st_gid) == -1)
- goto error;
- if (chmod(Cache_, info.st_mode) == -1)
- goto error;
-
- if (false) error:
- lprintf("%s\n", error == nil ? strerror(errno) : [[error localizedDescription] UTF8String]);
+ case 0: [close_ setTitle:UCLocalize("RETURN_TO_CYDIA")]; break; /* XXX: Maybe UCLocalize("DONE")? */
+ case 1: [close_ setTitle:UCLocalize("CLOSE_CYDIA")]; break;
+ case 2: [close_ setTitle:UCLocalize("RESTART_SPRINGBOARD")]; break;
+ case 3: [close_ setTitle:UCLocalize("RELOAD_SPRINGBOARD")]; break;
+ case 4: [close_ setTitle:UCLocalize("REBOOT_DEVICE")]; break;
}
- notify_post("com.apple.mobile.application_installed");
+ system("su -c /usr/bin/uicache mobile");
+
+ UpdateExternalStatus(Finish_ == 0 ? 2 : 0);
[delegate_ setStatusBarShowsProgress:NO];
}
}
- (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
- UINavigationItem *item = [navbar_ topItem];
- [item setTitle:title];
+ UpdateExternalStatus(1);
+
+ if (title_ != nil)
+ [title_ release];
+ if (title == nil)
+ title_ = nil;
+ else
+ title_ = [title retain];
+
+ [[self navigationItem] setTitle:title_];
[status_ setText:nil];
[output_ setText:@""];
[progress_ setProgress:0];
[close_ removeFromSuperview];
- [overlay_ addSubview:progress_];
- [overlay_ addSubview:status_];
+ [[self view] addSubview:progress_];
+ [[self view] addSubview:status_];
[delegate_ setStatusBarShowsProgress:YES];
running_ = YES;
{
- FileFd file(SandboxTemplate_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- sandplate_ = sha1.Result();
- }
-
- {
- FileFd file(NotifyConfig_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- notifyconf_ = sha1.Result();
+ FileFd file;
+ if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ notifyconf_ = sha1.Result();
+ }
}
{
- FileFd file(SpringBoard_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- springlist_ = sha1.Result();
+ FileFd file;
+ if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ springlist_ = sha1.Result();
+ }
}
- [transition_ transition:6 toView:overlay_];
-
[NSThread
detachNewThreadSelector:@selector(_detachNewThreadData:)
toTarget:self
detachNewThreadSelector:selector
toTarget:database_
withObject:nil
- title:CYLocalize("REPAIRING")
+ title:UCLocalize("REPAIRING")
];
}
];
}
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
- Package *package = id == nil ? nil : [database_ packageWithName:id];
-
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:(package == nil ? id : [package name])
- buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)title {
+ CYActionSheet *sheet([[[CYActionSheet alloc]
+ initWithTitle:title
+ buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil]
defaultButtonIndex:0
- delegate:self
- context:@"error"
- ] autorelease];
+ ] autorelease]);
- [sheet setBodyText:error];
- [sheet popupAlertAnimated:YES];
+ [sheet setMessage:error];
+ [sheet yieldToPopupAlertAnimated:YES];
+ [sheet dismiss];
}
- (void) setProgressTitle:(NSString *)title {
- (void) _setConfigurationData:(NSString *)data {
static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
- _assert(conffile_r(data));
+ if (!conffile_r(data)) {
+ lprintf("E:invalid conffile\n");
+ return;
+ }
NSString *ofile = conffile_r[1];
//NSString *nfile = conffile_r[2];
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("CONFIGURATION_UPGRADE")
- buttons:[NSArray arrayWithObjects:
- CYLocalize("KEEP_OLD_COPY"),
- CYLocalize("ACCEPT_NEW_COPY"),
- // XXX: CYLocalize("SEE_WHAT_CHANGED"),
- nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:UCLocalize("CONFIGURATION_UPGRADE")
+ message:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile]
delegate:self
- context:@"conffile"
+ cancelButtonTitle:UCLocalize("KEEP_OLD_COPY")
+ otherButtonTitles:UCLocalize("ACCEPT_NEW_COPY"),
+ // XXX: UCLocalize("SEE_WHAT_CHANGED"),
+ nil
] autorelease];
- [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", CYLocalize("CONFIGURATION_UPGRADE_EX"), ofile]];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"conffile"];
+ [alert show];
}
- (void) _setProgressTitle:(NSString *)title {
@end
/* }}} */
+/* Cell Content View {{{ */
+@interface ContentView : UIView {
+ _transient id delegate_;
+}
+
+@end
+
+@implementation ContentView
+- (id) initWithFrame:(CGRect)frame {
+ if ((self = [super initWithFrame:frame]) != nil) {
+ /* Fix landscape stretching. */
+ [self setNeedsDisplayOnBoundsChange:YES];
+ } return self;
+}
+
+- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
+}
+
+- (void) drawRect:(CGRect)rect {
+ [super drawRect:rect];
+ [delegate_ drawContentRect:rect];
+}
+@end
+/* }}} */
/* Package Cell {{{ */
-@interface PackageCell : UITableCell {
+@interface PackageCell : UITableViewCell {
UIImage *icon_;
NSString *name_;
NSString *description_;
bool commercial_;
NSString *source_;
UIImage *badge_;
- bool cached_;
Package *package_;
-#ifdef USE_BADGES
- UITextLabel *status_;
-#endif
+ UIColor *color_;
+ ContentView *content_;
+ BOOL faded_;
+ float fade_;
+ UIImage *placard_;
}
- (PackageCell *) init;
- (void) setPackage:(Package *)package;
+ (int) heightForPackage:(Package *)package;
+- (void) drawContentRect:(CGRect)rect;
@end
badge_ = nil;
}
+ if (placard_ != nil) {
+ [placard_ release];
+ placard_ = nil;
+ }
+
[package_ release];
package_ = nil;
}
- (void) dealloc {
[self clearPackage];
-#ifdef USE_BADGES
- [status_ release];
-#endif
+ [content_ release];
+ [color_ release];
[super dealloc];
}
+- (float) fade {
+ return faded_ ? [self selectionPercent] : fade_;
+}
+
- (PackageCell *) init {
- if ((self = [super init]) != nil) {
-#ifdef USE_BADGES
- status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 68, 280, 20)];
- [status_ setBackgroundColor:[UIColor clearColor]];
- [status_ setFont:small];
-#endif
+ CGRect frame(CGRectMake(0, 0, 320, 74));
+ if ((self = [super initWithFrame:frame reuseIdentifier:@"Package"]) != nil) {
+ UIView *content([self contentView]);
+ CGRect bounds([content bounds]);
+
+ content_ = [[ContentView alloc] initWithFrame:bounds];
+ [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [content addSubview:content_];
+
+ [content_ setDelegate:self];
+ [content_ setOpaque:YES];
+ if ([self respondsToSelector:@selector(selectionPercent)])
+ faded_ = YES;
} return self;
}
+- (void) _setBackgroundColor {
+ UIColor *color;
+ if (NSString *mode = [package_ mode]) {
+ bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]);
+ color = remove ? RemovingColor_ : InstallingColor_;
+ } else
+ color = [UIColor whiteColor];
+
+ [content_ setBackgroundColor:color];
+ [self setNeedsDisplay];
+}
+
- (void) setPackage:(Package *)package {
[self clearPackage];
[package parse];
icon_ = [[package icon] retain];
name_ = [[package name] retain];
- description_ = [[package shortDescription] retain];
+
+ if (IsWildcat_)
+ description_ = [package longDescription];
+ if (description_ == nil)
+ description_ = [package shortDescription];
+ if (description_ != nil)
+ description_ = [description_ retain];
+
commercial_ = [package isCommercial];
package_ = [package retain];
label = [source label];
trusted = [source trusted];
} else if ([[package id] isEqualToString:@"firmware"])
- label = CYLocalize("APPLE");
+ label = UCLocalize("APPLE");
else
- label = [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("UNKNOWN"), CYLocalize("LOCAL")];
+ label = [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("UNKNOWN"), UCLocalize("LOCAL")];
NSString *from(label);
NSString *section = [package simpleSection];
if (section != nil && ![section isEqualToString:label]) {
section = [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"];
- from = [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), from, section];
+ from = [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), from, section];
}
- from = [NSString stringWithFormat:CYLocalize("FROM"), from];
+ from = [NSString stringWithFormat:UCLocalize("FROM"), from];
source_ = [from retain];
if (NSString *purpose = [package primaryPurpose])
if ((badge_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Purposes/%@.png", App_, purpose]]) != nil)
badge_ = [badge_ retain];
-#ifdef USE_BADGES
- if (NSString *mode = [package mode]) {
- [badge_ setImage:[UIImage applicationImageNamed:
- [mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"] ? @"removing.png" : @"installing.png"
- ]];
-
- [status_ setText:[NSString stringWithFormat:CYLocalize("QUEUED_FOR"), CYLocalize(mode)]];
- [status_ setColor:[UIColor colorWithCGColor:Blueish_]];
- } else if ([package half]) {
- [badge_ setImage:[UIImage applicationImageNamed:@"damaged.png"]];
- [status_ setText:CYLocalize("PACKAGE_DAMAGED")];
- [status_ setColor:[UIColor redColor]];
- } else {
- [badge_ setImage:nil];
- [status_ setText:nil];
- }
-#endif
-
- cached_ = false;
-}
-
-- (void) drawRect:(CGRect)rect {
- if (!cached_) {
- UIColor *color;
-
- if (NSString *mode = [package_ mode]) {
- bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]);
- color = remove ? RemovingColor_ : InstallingColor_;
- } else
- color = [UIColor whiteColor];
-
- [self setBackgroundColor:color];
- cached_ = true;
- }
+ if ([package installed] != nil)
+ if ((placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/installed.png", App_]]) != nil)
+ placard_ = [placard_ retain];
- [super drawRect:rect];
+ [self _setBackgroundColor];
+ [content_ setNeedsDisplay];
}
-- (void) drawBackgroundInRect:(CGRect)rect withFade:(float)fade {
- if (fade == 0) {
- CGContextRef context(UIGraphicsGetCurrentContext());
- [[self backgroundColor] set];
- CGRect back(rect);
- back.size.height -= 1;
- CGContextFillRect(context, back);
- }
+- (void) drawContentRect:(CGRect)rect {
+ bool selected([self isSelected]);
+ float width([self bounds].size.width);
- [super drawBackgroundInRect:rect withFade:fade];
-}
+#if 0
+ CGContextRef context(UIGraphicsGetCurrentContext());
+ [([[self selectedBackgroundView] superview] != nil ? [UIColor clearColor] : [self backgroundColor]) set];
+ CGContextFillRect(context, rect);
+#endif
-- (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
if (icon_ != nil) {
CGRect rect;
rect.size = [icon_ size];
if (!selected)
UISetColor(commercial_ ? Purple_ : Black_);
- [name_ drawAtPoint:CGPointMake(48, 8) forWidth:240 withFont:Font18Bold_ ellipsis:2];
- [source_ drawAtPoint:CGPointMake(58, 29) forWidth:225 withFont:Font12_ ellipsis:2];
+ [name_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - (placard_ == nil ? 80 : 106)) withFont:Font18Bold_ ellipsis:2];
+ [source_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ ellipsis:2];
if (!selected)
UISetColor(commercial_ ? Purplish_ : Gray_);
- [description_ drawAtPoint:CGPointMake(12, 46) forWidth:280 withFont:Font14_ ellipsis:2];
+ [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 46) withFont:Font14_ ellipsis:2];
- [super drawContentInRect:rect selected:selected];
+ if (placard_ != nil)
+ [placard_ drawAtPoint:CGPointMake(width - 52, 9)];
}
-- (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
- cached_ = false;
- [super setSelected:selected withFade:fade];
+- (void) setSelected:(BOOL)selected animated:(BOOL)fade {
+ //[self _setBackgroundColor];
+ [super setSelected:selected animated:fade];
+ [content_ setNeedsDisplay];
}
+ (int) heightForPackage:(Package *)package {
@end
/* }}} */
/* Section Cell {{{ */
-@interface SectionCell : UISimpleTableCell {
+@interface SectionCell : UITableViewCell {
+ NSString *basic_;
NSString *section_;
NSString *name_;
NSString *count_;
UIImage *icon_;
- _UISwitchSlider *switch_;
+ ContentView *content_;
+ id switch_;
BOOL editing_;
}
@implementation SectionCell
- (void) clearSection {
+ if (basic_ != nil) {
+ [basic_ release];
+ basic_ = nil;
+ }
+
if (section_ != nil) {
[section_ release];
section_ = nil;
[self clearSection];
[icon_ release];
[switch_ release];
+ [content_ release];
+
[super dealloc];
}
-- (id) init {
- if ((self = [super init]) != nil) {
+- (id) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
+ if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) != nil) {
icon_ = [[UIImage applicationImageNamed:@"folder.png"] retain];
+ switch_ = [[objc_getClass("UISwitch") alloc] initWithFrame:CGRectMake(218, 9, 60, 25)];
+ [switch_ addTarget:self action:@selector(onSwitch:) forEvents:UIControlEventValueChanged];
- switch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(218, 9, 60, 25)];
- [switch_ addTarget:self action:@selector(onSwitch:) forEvents:kUIControlEventMouseUpInside];
+ UIView *content([self contentView]);
+ CGRect bounds([content bounds]);
+
+ content_ = [[ContentView alloc] initWithFrame:bounds];
+ [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [content addSubview:content_];
+ [content_ setBackgroundColor:[UIColor whiteColor]];
+
+ [content_ setDelegate:self];
} return self;
}
- (void) onSwitch:(id)sender {
- NSMutableDictionary *metadata = [Sections_ objectForKey:section_];
+ NSMutableDictionary *metadata = [Sections_ objectForKey:basic_];
if (metadata == nil) {
metadata = [NSMutableDictionary dictionaryWithCapacity:2];
- [Sections_ setObject:metadata forKey:section_];
+ [Sections_ setObject:metadata forKey:basic_];
}
Changed_ = true;
- [metadata setObject:[NSNumber numberWithBool:([switch_ value] == 0)] forKey:@"Hidden"];
+ [metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"];
}
- (void) setSection:(Section *)section editing:(BOOL)editing {
[self clearSection];
if (section == nil) {
- name_ = [CYLocalize("ALL_PACKAGES") retain];
+ name_ = [UCLocalize("ALL_PACKAGES") retain];
count_ = nil;
} else {
+ basic_ = [section name];
+ if (basic_ != nil)
+ basic_ = [basic_ retain];
+
section_ = [section localized];
if (section_ != nil)
section_ = [section_ retain];
- name_ = [(section_ == nil ? CYLocalize("NO_SECTION") : section_) retain];
+
+ name_ = [(section_ == nil || [section_ length] == 0 ? UCLocalize("NO_SECTION") : section_) retain];
count_ = [[NSString stringWithFormat:@"%d", [section count]] retain];
if (editing_)
- [switch_ setValue:(isSectionVisible(section_) ? 1 : 0) animated:NO];
+ [switch_ setOn:(isSectionVisible(basic_) ? 1 : 0) animated:NO];
}
+
+ [self setAccessoryType:editing ? 0 : 1 /*UITableViewCellAccessoryDisclosureIndicator*/];
+ [content_ setNeedsDisplay];
+}
+
+- (void) setFrame:(CGRect)frame {
+ [super setFrame:frame];
+
+ CGRect rect([switch_ frame]);
+ [switch_ setFrame:CGRectMake(frame.size.width - 102, 9, rect.size.width, rect.size.height)];
}
-- (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
+- (void) drawContentRect:(CGRect)rect {
+ BOOL selected = [self isSelected];
+
[icon_ drawInRect:CGRectMake(8, 7, 32, 32)];
if (selected)
if (!selected)
UISetColor(Black_);
- [name_ drawAtPoint:CGPointMake(48, 9) forWidth:(editing_ ? 164 : 250) withFont:Font22Bold_ ellipsis:2];
+
+ float width(rect.size.width);
+ if (editing_)
+ width -= 87;
+
+ [name_ drawAtPoint:CGPointMake(48, 9) forWidth:(width - 70) withFont:Font22Bold_ ellipsis:2];
CGSize size = [count_ sizeWithFont:Font14_];
UISetColor(White_);
if (count_ != nil)
[count_ drawAtPoint:CGPointMake(13 + (29 - size.width) / 2, 16) withFont:Font12Bold_];
-
- [super drawContentInRect:rect selected:selected];
}
@end
/* }}} */
/* File Table {{{ */
-@interface FileTable : RVPage {
+@interface FileTable : CYViewController {
_transient Database *database_;
Package *package_;
NSString *name_;
NSMutableArray *files_;
- UITable *list_;
+ UITableView *list_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
- (void) setPackage:(Package *)package;
@end
[super dealloc];
}
-- (int) numberOfRowsInTable:(UITable *)table {
+- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(int)section {
return files_ == nil ? 0 : [files_ count];
}
-- (float) table:(UITable *)table heightForRow:(int)row {
- return 24;
-}
+/*- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+ return 24.0f;
+}*/
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
- if (reusing == nil) {
- reusing = [[[UIImageAndTextTableCell alloc] init] autorelease];
- UIFont *font = [UIFont systemFontOfSize:16];
- [[(UIImageAndTextTableCell *)reusing titleTextLabel] setFont:font];
+- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ static NSString *reuseIdentifier = @"Cell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:reuseIdentifier] autorelease];
+ [cell setFont:[UIFont systemFontOfSize:16]];
}
- [(UIImageAndTextTableCell *)reusing setTitle:[files_ objectAtIndex:row]];
- return reusing;
-}
+ [cell setText:[files_ objectAtIndex:indexPath.row]];
+ [cell setSelectionStyle:0 /*UITableViewCellSelectionStyleNone*/];
-- (BOOL) table:(UITable *)table canSelectRow:(int)row {
- return NO;
+ return cell;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
database_ = database;
- files_ = [[NSMutableArray arrayWithCapacity:32] retain];
+ [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")];
- list_ = [[UITable alloc] initWithFrame:[self bounds]];
- [self addSubview:list_];
+ files_ = [[NSMutableArray arrayWithCapacity:32] retain];
- UITableColumn *column = [[[UITableColumn alloc]
- initWithTitle:CYLocalize("NAME")
- identifier:@"name"
- width:[self frame].size.width
- ] autorelease];
+ list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
+ [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [list_ setRowHeight:24.0f];
+ [[self view] addSubview:list_];
[list_ setDataSource:self];
- [list_ setSeparatorStyle:1];
- [list_ addTableColumn:column];
[list_ setDelegate:self];
- [list_ setReusesTableCells:YES];
} return self;
}
[list_ reloadData];
}
-- (void) resetViewAnimated:(BOOL)animated {
- [list_ resetViewAnimated:animated];
-}
-
- (void) reloadData {
[self setPackage:[database_ packageWithName:name_]];
- [self reloadButtons];
-}
-
-- (NSString *) title {
- return CYLocalize("INSTALLED_FILES");
-}
-
-- (NSString *) backButtonTitle {
- return CYLocalize("FILES");
}
@end
/* }}} */
-/* Package View {{{ */
-@interface PackageView : BrowserView {
+/* Package Controller {{{ */
+@interface PackageController : CYBrowserController {
_transient Database *database_;
Package *package_;
NSString *name_;
NSMutableArray *buttons_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
- (void) setPackage:(Package *)package;
@end
-@implementation PackageView
+@implementation PackageController
- (void) dealloc {
if (package_ != nil)
- (void) release {
if ([self retainCount] == 1)
- [delegate_ setPackageView:self];
+ [delegate_ setPackageController:self];
[super release];
}
/* XXX: this is not safe at all... localization of /fail/ */
- (void) _clickButtonWithName:(NSString *)name {
- if ([name isEqualToString:CYLocalize("CLEAR")])
+ if ([name isEqualToString:UCLocalize("CLEAR")])
[delegate_ clearPackage:package_];
- else if ([name isEqualToString:CYLocalize("INSTALL")])
+ else if ([name isEqualToString:UCLocalize("INSTALL")])
[delegate_ installPackage:package_];
- else if ([name isEqualToString:CYLocalize("REINSTALL")])
+ else if ([name isEqualToString:UCLocalize("REINSTALL")])
[delegate_ installPackage:package_];
- else if ([name isEqualToString:CYLocalize("REMOVE")])
+ else if ([name isEqualToString:UCLocalize("REMOVE")])
[delegate_ removePackage:package_];
- else if ([name isEqualToString:CYLocalize("UPGRADE")])
+ else if ([name isEqualToString:UCLocalize("UPGRADE")])
[delegate_ installPackage:package_];
else _assert(false);
}
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
+- (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button {
NSString *context([sheet context]);
if ([context isEqualToString:@"modify"]) {
- int count = [buttons_ count];
- _assert(count != 0);
- _assert(button <= count + 1);
-
- if (count != button - 1)
- [self _clickButtonWithName:[buttons_ objectAtIndex:(button - 1)]];
-
- [sheet dismiss];
- } else
- [super alertSheet:sheet buttonClicked:button];
+ if (button != [sheet cancelButtonIndex]) {
+ NSString *buttonName = [buttons_ objectAtIndex:button];
+ [self _clickButtonWithName:buttonName];
+ }
+
+ [sheet dismissWithClickedButtonIndex:-1 animated:YES];
+ } else {
+ [super alertSheet:sheet clickedButtonAtIndex:button];
+ }
}
- (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
}
#if !AlwaysReload
-- (void) __rightButtonClicked {
- int count = [buttons_ count];
- _assert(count != 0);
+- (void) _actionButtonClicked {
+ int count([buttons_ count]);
+ if (count == 0)
+ return;
if (count == 1)
[self _clickButtonWithName:[buttons_ objectAtIndex:0]];
else {
- NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:(count + 1)];
+ NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:count];
[buttons addObjectsFromArray:buttons_];
- [buttons addObject:CYLocalize("CANCEL")];
- [delegate_ slideUp:[[[UIActionSheet alloc]
+ UIActionSheet *sheet = [[[UIActionSheet alloc]
initWithTitle:nil
- buttons:buttons
- defaultButtonIndex:([buttons count] - 1)
delegate:self
- context:@"modify"
- ] autorelease]];
+ cancelButtonTitle:nil
+ destructiveButtonTitle:nil
+ otherButtonTitles:nil
+ ] autorelease];
+
+ for (NSString *button in buttons) [sheet addButtonWithTitle:button];
+ if (!IsWildcat_) {
+ [sheet addButtonWithTitle:UCLocalize("CANCEL")];
+ [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1];
+ }
+ [sheet setContext:@"modify"];
+
+ [delegate_ showActionSheet:sheet fromItem:[[self navigationItem] rightBarButtonItem]];
}
}
-- (void) _rightButtonClicked {
- if (commercial_)
- [super _rightButtonClicked];
- else
- [self __rightButtonClicked];
+- (void) actionButtonClicked {
+ // Wait until it's done loading.
+ if (![self isLoading])
+ [self _actionButtonClicked];
}
-#endif
-- (id) _rightButtonTitle {
- int count = [buttons_ count];
- return count == 0 ? nil : count != 1 ? CYLocalize("MODIFY") : [buttons_ objectAtIndex:0];
+- (void) reloadButtonClicked {
+ // Don't reload a package view by clicking the button.
}
-- (NSString *) backButtonTitle {
- return @"Details";
+- (void) applyLoadingTitle {
+ // Don't show "Loading" as the title. Ever.
}
+#endif
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (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"]]];
commercial_ = [package isCommercial];
if ([package_ mode] != nil)
- [buttons_ addObject:CYLocalize("CLEAR")];
+ [buttons_ addObject:UCLocalize("CLEAR")];
if ([package_ source] == nil);
else if ([package_ upgradableAndEssential:NO])
- [buttons_ addObject:CYLocalize("UPGRADE")];
- else if ([package_ installed] == nil)
- [buttons_ addObject:CYLocalize("INSTALL")];
+ [buttons_ addObject:UCLocalize("UPGRADE")];
+ else if ([package_ uninstalled])
+ [buttons_ addObject:UCLocalize("INSTALL")];
else
- [buttons_ addObject:CYLocalize("REINSTALL")];
- if ([package_ installed] != nil)
- [buttons_ addObject:CYLocalize("REMOVE")];
+ [buttons_ addObject:UCLocalize("REINSTALL")];
+ if (![package_ uninstalled])
+ [buttons_ addObject:UCLocalize("REMOVE")];
if (special_ != NULL) {
- CGRect frame([webview_ frame]);
- frame.size.width = 320;
+ CGRect frame([document_ frame]);
frame.size.height = 0;
- [webview_ setFrame:frame];
+ [document_ setFrame:frame];
- [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
+ if ([scroller_ respondsToSelector:@selector(scrollPointVisibleAtTopLeft:)])
+ [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
+ else
+ [scroller_ scrollRectToVisible:CGRectZero animated:NO];
WebThreadLock();
- [[[webview_ webView] windowScriptObject] setValue:package_ forKey:@"package"];
+ [[[document_ webView] windowScriptObject] setValue:package_ forKey:@"package"];
[self setButtonTitle:nil withStyle:nil toFunction:nil];
[super callFunction:special_];
}
}
+}
- [self reloadButtons];
+- (void) applyRightButton {
+ int count = [buttons_ count];
+ UIBarButtonItem *actionItem = [[UIBarButtonItem alloc]
+ initWithTitle:count == 0 ? nil : count != 1 ? UCLocalize("MODIFY") : [buttons_ objectAtIndex:0]
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(actionButtonClicked)
+ ];
+ if (![self isLoading]) [[self navigationItem] setRightBarButtonItem:actionItem];
+ else [super applyRightButton];
+ [actionItem release];
}
- (bool) isLoading {
@end
/* }}} */
/* Package Table {{{ */
-@interface PackageTable : RVPage {
+@interface PackageTable : UIView {
_transient Database *database_;
- NSString *title_;
NSMutableArray *packages_;
NSMutableArray *sections_;
- UISectionList *list_;
+ UITableView *list_;
+ NSMutableArray *index_;
+ NSMutableDictionary *indices_;
+ id target_;
+ SEL action_;
+ id delegate_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title;
+- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action;
- (void) setDelegate:(id)delegate;
- (void) reloadData;
- (void) resetCursor;
-- (UISectionList *) list;
+- (UITableView *) list;
- (void) setShouldHideHeaderInShortLists:(BOOL)hide;
+- (void) deselectWithAnimation:(BOOL)animated;
+
@end
@implementation PackageTable
- (void) dealloc {
- [list_ setDataSource:nil];
-
- [title_ release];
[packages_ release];
[sections_ release];
[list_ release];
+ [index_ release];
+ [indices_ release];
+
[super dealloc];
}
-- (int) numberOfSectionsInSectionList:(UISectionList *)list {
- return [sections_ count];
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
+ NSInteger count([sections_ count]);
+ return count == 0 ? 1 : count;
}
-- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
+- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
+ if ([sections_ count] == 0)
+ return nil;
return [[sections_ objectAtIndex:section] name];
}
-- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
- return [[sections_ objectAtIndex:section] row];
+- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
+ if ([sections_ count] == 0)
+ return 0;
+ return [[sections_ objectAtIndex:section] count];
}
-- (int) numberOfRowsInTable:(UITable *)table {
- return [packages_ count];
+- (Package *) packageAtIndexPath:(NSIndexPath *)path {
+ Section *section([sections_ objectAtIndex:[path section]]);
+ NSInteger row([path row]);
+ Package *package([packages_ objectAtIndex:([section row] + row)]);
+ return package;
}
-- (float) table:(UITable *)table heightForRow:(int)row {
- return [PackageCell heightForPackage:[packages_ objectAtIndex:row]];
+- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
+ PackageCell *cell([table dequeueReusableCellWithIdentifier:@"Package"]);
+ if (cell == nil)
+ cell = [[[PackageCell alloc] init] autorelease];
+ [cell setPackage:[self packageAtIndexPath:path]];
+ return cell;
}
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
- if (reusing == nil)
- reusing = [[[PackageCell alloc] init] autorelease];
- [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
- return reusing;
+- (void) deselectWithAnimation:(BOOL)animated {
+ [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
}
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
- return NO;
+/*- (CGFloat) tableView:(UITableView *)table heightForRowAtIndexPath:(NSIndexPath *)path {
+ return [PackageCell heightForPackage:[self packageAtIndexPath:path]];
+}*/
+
+- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
+ Package *package([self packageAtIndexPath:path]);
+ package = [database_ packageWithName:[package id]];
+ [target_ performSelector:action_ withObject:package];
+ return path;
}
-- (void) tableRowSelected:(NSNotification *)notification {
- int row = [[notification object] selectedRow];
- if (row == INT_MAX)
- return;
+- (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView {
+ return [packages_ count] > 20 ? index_ : nil;
+}
- Package *package = [packages_ objectAtIndex:row];
- package = [database_ packageWithName:[package id]];
- PackageView *view([delegate_ packageView]);
- [view setPackage:package];
- [view setDelegate:delegate_];
- [book_ pushPage:view];
+- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
+ return index;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action {
+ if ((self = [super initWithFrame:frame]) != nil) {
database_ = database;
- title_ = [title retain];
-
- packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
- sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
- list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
- [list_ setDataSource:self];
+ target_ = target;
+ action_ = action;
- UITableColumn *column = [[[UITableColumn alloc]
- initWithTitle:CYLocalize("NAME")
- identifier:@"name"
- width:[self frame].size.width
- ] autorelease];
+ index_ = [[NSMutableArray alloc] initWithCapacity:32];
+ indices_ = [[NSMutableDictionary alloc] initWithCapacity:32];
- UITable *table = [list_ table];
- [table setSeparatorStyle:1];
- [table addTableColumn:column];
- [table setDelegate:self];
- [table setReusesTableCells:YES];
+ packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+ sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
+ list_ = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStylePlain];
+ [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [list_ setRowHeight:73.0f];
[self addSubview:list_];
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+ [list_ setDataSource:self];
+ [list_ setDelegate:self];
} return self;
}
[packages_ addObject:package];
_end
+ [index_ removeAllObjects];
+ [indices_ removeAllObjects];
+
Section *section = nil;
_profile(PackageTable$reloadData$Section)
section = [[[Section alloc] initWithIndex:index row:offset] autorelease];
_end
+ [index_ addObject:[section name]];
+ //[indices_ setObject:[NSNumber numberForInt:[sections_ count]] forKey:index];
+
_profile(PackageTable$reloadData$Section$Add)
[sections_ addObject:section];
_end
_end
}
-- (NSString *) title {
- return title_;
-}
-
-- (void) resetViewAnimated:(BOOL)animated {
- [list_ resetViewAnimated:animated];
-}
-
- (void) resetCursor {
- [[list_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
+ [list_ scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:NO];
}
-- (UISectionList *) list {
+- (UITableView *) list {
return list_;
}
- (void) setShouldHideHeaderInShortLists:(BOOL)hide {
- [list_ setShouldHideHeaderInShortLists:hide];
+ //XXX:[list_ setShouldHideHeaderInShortLists:hide];
}
@end
}
- (void) setObject:(id)object;
+- (void) setObject:(id)object forFilter:(SEL)filter;
-- (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
+- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action filter:(SEL)filter with:(id)object;
@end
[super dealloc];
}
+- (void) setFilter:(SEL)filter {
+ filter_ = filter;
+
+ /* XXX: this is an unsafe optimization of doomy hell */
+ Method method(class_getInstanceMethod([Package class], filter));
+ _assert(method != NULL);
+ imp_ = method_getImplementation(method);
+ _assert(imp_ != NULL);
+}
+
- (void) setObject:(id)object {
if (object_ != nil)
[object_ release];
object_ = [object retain];
}
+- (void) setObject:(id)object forFilter:(SEL)filter {
+ [self setFilter:filter];
+ [self setObject:object];
+}
+
- (bool) hasPackage:(Package *)package {
_profile(FilteredPackageTable$hasPackage)
return [package valid] && (*reinterpret_cast<bool (*)(id, SEL, id)>(imp_))(package, filter_, object_);
_end
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
- if ((self = [super initWithBook:book database:database title:title]) != nil) {
- filter_ = filter;
- object_ = object == nil ? nil : [object retain];
+- (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) {
+ [self setFilter:filter];
+ object_ = [object retain];
+ [self reloadData];
+ } return self;
+}
+
+@end
+/* }}} */
+
+/* Filtered Package Controller {{{ */
+@interface FilteredPackageController : CYViewController {
+ _transient Database *database_;
+ FilteredPackageTable *packages_;
+ NSString *title_;
+}
+
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
+
+@end
+
+@implementation FilteredPackageController
- /* XXX: this is an unsafe optimization of doomy hell */
- Method method = class_getInstanceMethod([Package class], filter);
- _assert(method != NULL);
- imp_ = method_getImplementation(method);
- _assert(imp_ != NULL);
+- (void) dealloc {
+ [packages_ release];
+ [title_ release];
+
+ [super dealloc];
+}
- [self reloadData];
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [packages_ deselectWithAnimation:animated];
+}
+
+- (void) didSelectPackage:(Package *)package {
+ PackageController *view([delegate_ packageController]);
+ [view setPackage:package];
+ [view setDelegate:delegate_];
+ [[self navigationController] pushViewController:view animated:YES];
+}
+
+- (id) title { return title_; }
+
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
+ if ((self = [super init]) != nil) {
+ database_ = database;
+ title_ = [title copy];
+ [[self navigationItem] setTitle:title_];
+
+ packages_ = [[FilteredPackageTable alloc]
+ initWithFrame:[[self view] bounds]
+ database:database
+ target:self
+ action:@selector(didSelectPackage:)
+ filter:filter
+ with:object
+ ];
+
+ [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [[self view] addSubview:packages_];
} return self;
}
+- (void) reloadData {
+ [packages_ reloadData];
+}
+
+- (void) setDelegate:(id)delegate {
+ [super setDelegate:delegate];
+ [packages_ setDelegate:delegate];
+}
+
@end
+
/* }}} */
-/* Add Source View {{{ */
-@interface AddSourceView : RVPage {
+/* Add Source Controller {{{ */
+@interface AddSourceController : CYViewController {
_transient Database *database_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
@end
-@implementation AddSourceView
+@implementation AddSourceController
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
database_ = database;
} return self;
}
@end
/* }}} */
/* Source Cell {{{ */
-@interface SourceCell : UITableCell {
+@interface SourceCell : UITableViewCell {
UIImage *icon_;
NSString *origin_;
NSString *description_;
NSString *label_;
+ ContentView *content_;
}
-- (void) dealloc;
-
-- (SourceCell *) initWithSource:(Source *)source;
+- (void) setSource:(Source *)source;
@end
@implementation SourceCell
-- (void) dealloc {
+- (void) clearSource {
[icon_ release];
[origin_ release];
[description_ release];
[label_ release];
- [super dealloc];
-}
-- (SourceCell *) initWithSource:(Source *)source {
- if ((self = [super init]) != nil) {
- if (icon_ == nil)
- icon_ = [UIImage applicationImageNamed:[NSString stringWithFormat:@"Sources/%@.png", [source host]]];
- if (icon_ == nil)
- icon_ = [UIImage applicationImageNamed:@"unknown.png"];
- icon_ = [icon_ retain];
-
- origin_ = [[source name] retain];
- label_ = [[source uri] retain];
- description_ = [[source description] retain];
- } return self;
+ icon_ = nil;
+ origin_ = nil;
+ description_ = nil;
+ label_ = nil;
}
-- (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
- if (icon_ != nil)
- [icon_ drawInRect:CGRectMake(10, 10, 30, 30)];
+- (void) setSource:(Source *)source {
+ [self clearSource];
+
+ if (icon_ == nil)
+ icon_ = [UIImage applicationImageNamed:[NSString stringWithFormat:@"Sources/%@.png", [source host]]];
+ if (icon_ == nil)
+ icon_ = [UIImage applicationImageNamed:@"unknown.png"];
+ icon_ = [icon_ retain];
- if (selected)
+ origin_ = [[source name] retain];
+ label_ = [[source uri] retain];
+ description_ = [[source description] retain];
+
+ [content_ setNeedsDisplay];
+}
+
+- (void) dealloc {
+ [self clearSource];
+ [content_ release];
+ [super dealloc];
+}
+
+- (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
+ if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) != nil) {
+ UIView *content([self contentView]);
+ CGRect bounds([content bounds]);
+
+ content_ = [[ContentView alloc] initWithFrame:bounds];
+ [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [content_ setBackgroundColor:[UIColor whiteColor]];
+ [content addSubview:content_];
+
+ [content_ setDelegate:self];
+ [content_ setOpaque:YES];
+ } return self;
+}
+
+- (void) setSelected:(BOOL)selected animated:(BOOL)animated {
+ [super setSelected:selected animated:animated];
+ [content_ setNeedsDisplay];
+}
+
+- (void) drawContentRect:(CGRect)rect {
+ bool selected([self isSelected]);
+ float width(rect.size.width);
+
+ if (icon_ != nil)
+ [icon_ drawInRect:CGRectMake(10, 10, 30, 30)];
+
+ if (selected)
UISetColor(White_);
if (!selected)
UISetColor(Black_);
- [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:240 withFont:Font18Bold_ ellipsis:2];
+ [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - 80) withFont:Font18Bold_ ellipsis:2];
if (!selected)
UISetColor(Blue_);
- [label_ drawAtPoint:CGPointMake(58, 29) forWidth:225 withFont:Font12_ ellipsis:2];
+ [label_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ ellipsis:2];
if (!selected)
UISetColor(Gray_);
- [description_ drawAtPoint:CGPointMake(12, 46) forWidth:280 withFont:Font14_ ellipsis:2];
-
- [super drawContentInRect:rect selected:selected];
+ [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 40) withFont:Font14_ ellipsis:2];
}
@end
/* }}} */
/* Source Table {{{ */
-@interface SourceTable : RVPage {
+@interface SourceTable : CYViewController {
_transient Database *database_;
- UISectionList *list_;
+ UITableView *list_;
NSMutableArray *sources_;
- UIActionSheet *alert_;
int offset_;
NSString *href_;
NSError *error_;
//NSURLConnection *installer_;
+ NSURLConnection *trivial_;
NSURLConnection *trivial_bz2_;
NSURLConnection *trivial_gz_;
//NSURLConnection *automatic_;
- BOOL trivial_;
+ BOOL cydia_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
@end
}
- (void) dealloc {
- [[list_ table] setDelegate:nil];
- [list_ setDataSource:nil];
-
if (href_ != nil)
[href_ release];
if (hud_ != nil)
[error_ release];
//[self _deallocConnection:installer_];
+ [self _deallocConnection:trivial_];
[self _deallocConnection:trivial_gz_];
[self _deallocConnection:trivial_bz2_];
//[self _deallocConnection:automatic_];
[super dealloc];
}
-- (int) numberOfSectionsInSectionList:(UISectionList *)list {
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
+}
+
+- (int) numberOfSectionsInTableView:(UITableView *)tableView {
return offset_ == 0 ? 1 : 2;
}
-- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
+- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(int)section {
switch (section + (offset_ == 0 ? 1 : 0)) {
- case 0: return CYLocalize("ENTERED_BY_USER");
- case 1: return CYLocalize("INSTALLED_BY_PACKAGE");
+ case 0: return UCLocalize("ENTERED_BY_USER");
+ case 1: return UCLocalize("INSTALLED_BY_PACKAGE");
- default:
- _assert(false);
- return nil;
+ _nodefault
}
}
-- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
- switch (section + (offset_ == 0 ? 1 : 0)) {
- case 0: return 0;
- case 1: return offset_;
+- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(int)section {
+ int count = [sources_ count];
+ switch (section) {
+ case 0: return (offset_ == 0 ? count : offset_);
+ case 1: return count - offset_;
- default:
- _assert(false);
- return -1;
+ _nodefault
}
}
-- (int) numberOfRowsInTable:(UITable *)table {
- return [sources_ count];
+- (Source *) sourceAtIndexPath:(NSIndexPath *)indexPath {
+ unsigned idx = 0;
+ switch (indexPath.section) {
+ case 0: idx = indexPath.row; break;
+ case 1: idx = indexPath.row + offset_; break;
+
+ _nodefault
+ }
+ return [sources_ objectAtIndex:idx];
}
-- (float) table:(UITable *)table heightForRow:(int)row {
- Source *source = [sources_ objectAtIndex:row];
+- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+ Source *source = [self sourceAtIndexPath:indexPath];
return [source description] == nil ? 56 : 73;
}
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
- Source *source = [sources_ objectAtIndex:row];
- // XXX: weird warning, stupid selectors ;P
- return [[[SourceCell alloc] initWithSource:(id)source] autorelease];
-}
+- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ static NSString *cellIdentifier = @"SourceCell";
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
- return YES;
+ SourceCell *cell = (SourceCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
+ if(cell == nil) cell = [[[SourceCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
+ [cell setSource:[self sourceAtIndexPath:indexPath]];
+
+ return cell;
}
-- (BOOL) table:(UITable *)table canSelectRow:(int)row {
- return YES;
+- (int) tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
+ return 1; //UITableViewCellAccessoryDisclosureIndicator?
}
-- (void) tableRowSelected:(NSNotification*)notification {
- UITable *table([list_ table]);
- int row([table selectedRow]);
- if (row == INT_MAX)
- return;
-
- Source *source = [sources_ objectAtIndex:row];
+- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ Source *source = [self sourceAtIndexPath:indexPath];
- PackageTable *packages = [[[FilteredPackageTable alloc]
- initWithBook:book_
- database:database_
+ FilteredPackageController *packages = [[[FilteredPackageController alloc]
+ initWithDatabase:database_
title:[source label]
filter:@selector(isVisibleInSource:)
with:source
[packages setDelegate:delegate_];
- [book_ pushPage:packages];
+ [[self navigationController] pushViewController:packages animated:YES];
}
-- (BOOL) table:(UITable *)table canDeleteRow:(int)row {
- Source *source = [sources_ objectAtIndex:row];
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
+ Source *source = [self sourceAtIndexPath:indexPath];
return [source record] != nil;
}
-- (void) table:(UITable *)table willSwipeToDeleteRow:(int)row {
- [[list_ table] setDeleteConfirmationRow:row];
-}
-
-- (void) table:(UITable *)table deleteRow:(int)row {
- Source *source = [sources_ objectAtIndex:row];
+- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
+ Source *source = [self sourceAtIndexPath:indexPath];
[Sources_ removeObjectForKey:[source key]];
[delegate_ syncData];
}
if (colon.location != NSNotFound)
href = [href substringFromIndex:(colon.location + 3)];
href = [href stringByAddingPercentEscapes];
- href = [@"http://cydia.saurik.com/api/repotag/" stringByAppendingString:href];
+ href = [CydiaURL(@"api/repotag/") stringByAppendingString:href];
href = [href stringByCachingURLWithCurrentCDN];
NSURL *url([NSURL URLWithString:href]);
- (void) _endConnection:(NSURLConnection *)connection {
NSURLConnection **field = NULL;
- if (connection == trivial_bz2_)
+ if (connection == trivial_)
+ field = &trivial_;
+ else if (connection == trivial_bz2_)
field = &trivial_bz2_;
else if (connection == trivial_gz_)
field = &trivial_gz_;
*field = nil;
if (
+ trivial_ == nil &&
trivial_bz2_ == nil &&
trivial_gz_ == nil
) {
bool defer(false);
- if (trivial_) {
+ if (cydia_) {
if (NSString *warning = [self yieldToSelector:@selector(getWarning)]) {
defer = true;
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("SOURCE_WARNING")
- buttons:[NSArray arrayWithObjects:CYLocalize("ADD_ANYWAY"), CYLocalize("CANCEL"), nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:UCLocalize("SOURCE_WARNING")
+ message:warning
delegate:self
- context:@"warning"
+ cancelButtonTitle:UCLocalize("CANCEL")
+ otherButtonTitles:UCLocalize("ADD_ANYWAY"), nil
] autorelease];
- [sheet setNumberOfRows:1];
-
- [sheet setBodyText:warning];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"warning"];
+ [alert setNumberOfRows:1];
+ [alert show];
} else
[self complete];
} else if (error_ != nil) {
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("VERIFICATION_ERROR")
- buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:UCLocalize("VERIFICATION_ERROR")
+ message:[error_ localizedDescription]
delegate:self
- context:@"urlerror"
+ cancelButtonTitle:UCLocalize("OK")
+ otherButtonTitles:nil
] autorelease];
- [sheet setBodyText:[error_ localizedDescription]];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"urlerror"];
+ [alert show];
} else {
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("NOT_REPOSITORY")
- buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:UCLocalize("NOT_REPOSITORY")
+ message:UCLocalize("NOT_REPOSITORY_EX")
delegate:self
- context:@"trivial"
+ cancelButtonTitle:UCLocalize("OK")
+ otherButtonTitles:nil
] autorelease];
- [sheet setBodyText:CYLocalize("NOT_REPOSITORY_EX")];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"trivial"];
+ [alert show];
}
[delegate_ setStatusBarShowsProgress:NO];
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
switch ([response statusCode]) {
case 200:
- trivial_ = YES;
+ cydia_ = YES;
}
}
[self _endConnection:connection];
}
+- (id)title { return UCLocalize("SOURCES"); }
+
- (NSURLConnection *) _requestHRef:(NSString *)href method:(NSString *)method {
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:href]
cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:20.0
+ timeoutInterval:120.0
];
[request setHTTPMethod:method];
[request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
if (UniqueID_ != nil)
[request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
-
if (Role_ != nil)
[request setValue:Role_ forHTTPHeaderField:@"X-Role"];
return [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
}
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
+- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+ NSString *context([alert context]);
if ([context isEqualToString:@"source"]) {
switch (button) {
case 1: {
- NSString *href = [[sheet textField] text];
+ NSString *href = [[alert textField] text];
//installer_ = [[self _requestHRef:href method:@"GET"] retain];
href_ = href;
href_ = [href_ retain];
+ trivial_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages"] method:@"HEAD"] retain];
trivial_bz2_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.bz2"] method:@"HEAD"] retain];
trivial_gz_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.gz"] method:@"HEAD"] retain];
//trivial_bz2_ = [[self _requestHRef:[href stringByAppendingString:@"dists/Release"] method:@"HEAD"] retain];
- trivial_ = false;
+ cydia_ = false;
hud_ = [[delegate_ addProgressHUD] retain];
- [hud_ setText:CYLocalize("VERIFYING_URL")];
+ [hud_ setText:UCLocalize("VERIFYING_URL")];
} break;
- case 2:
+ case 0:
break;
- default:
- _assert(false);
+ _nodefault
}
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
} else if ([context isEqualToString:@"trivial"])
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
else if ([context isEqualToString:@"urlerror"])
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
else if ([context isEqualToString:@"warning"]) {
switch (button) {
case 1:
[self complete];
break;
- case 2:
+ case 0:
break;
- default:
- _assert(false);
+ _nodefault
}
[href_ release];
href_ = nil;
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
}
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
+ [[self navigationItem] setTitle:UCLocalize("SOURCES")];
+ [self updateButtonsForEditingStatus:NO animated:NO];
+
database_ = database;
sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
- //list_ = [[UITable alloc] initWithFrame:[self bounds]];
- list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:NO];
- [list_ setShouldHideHeaderInShortLists:NO];
+ list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
+ [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [[self view] addSubview:list_];
- [self addSubview:list_];
[list_ setDataSource:self];
-
- UITableColumn *column = [[UITableColumn alloc]
- initWithTitle:CYLocalize("NAME")
- identifier:@"name"
- width:[self frame].size.width
- ];
-
- UITable *table = [list_ table];
- [table setSeparatorStyle:1];
- [table addTableColumn:column];
- [table setDelegate:self];
+ [list_ setDelegate:self];
[self reloadData];
-
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
} return self;
}
- (void) reloadData {
pkgSourceList list;
- _assert(list.ReadMainList());
+ if (!list.ReadMainList())
+ return;
[sources_ removeAllObjects];
[sources_ addObjectsFromArray:[database_ sources]];
[sources_ sortUsingSelector:@selector(compareByNameAndType:)];
_trace();
- int count = [sources_ count];
- for (offset_ = 0; offset_ != count; ++offset_) {
- Source *source = [sources_ objectAtIndex:offset_];
- if ([source record] == nil)
- break;
+ int count([sources_ count]);
+ offset_ = 0;
+ for (int i = 0; i != count; i++) {
+ if ([[sources_ objectAtIndex:i] record] == nil) break;
+ else offset_++;
}
+ [list_ setEditing:NO];
+ [self updateButtonsForEditingStatus:NO animated:NO];
[list_ reloadData];
}
-- (void) resetViewAnimated:(BOOL)animated {
- [list_ resetViewAnimated:animated];
-}
-
-- (void) _leftButtonClicked {
- /*[book_ pushPage:[[[AddSourceView alloc]
+- (void) addButtonClicked {
+ /*[book_ pushPage:[[[AddSourceController alloc]
initWithBook:book_
database:database_
] autorelease]];*/
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("ENTER_APT_URL")
- buttons:[NSArray arrayWithObjects:CYLocalize("ADD_SOURCE"), CYLocalize("CANCEL"), nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:UCLocalize("ENTER_APT_URL")
+ message:nil
delegate:self
- context:@"source"
+ cancelButtonTitle:UCLocalize("CANCEL")
+ otherButtonTitles:UCLocalize("ADD_SOURCE"), nil
] autorelease];
- [sheet setNumberOfRows:1];
+ [alert setContext:@"source"];
+ [alert setTransform:CGAffineTransformTranslate([alert transform], 0.0, 100.0)];
- [sheet addTextFieldWithValue:@"http://" label:@""];
+ [alert setNumberOfRows:1];
+ [alert addTextFieldWithValue:@"http://" label:@""];
- UITextInputTraits *traits = [[sheet textField] textInputTraits];
+ UITextInputTraits *traits = [[alert textField] textInputTraits];
[traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[traits setAutocorrectionType:UITextAutocorrectionTypeNo];
[traits setKeyboardType:UIKeyboardTypeURL];
// XXX: UIReturnKeyDone
[traits setReturnKeyType:UIReturnKeyNext];
- [sheet popupAlertAnimated:YES];
-}
-
-- (void) _rightButtonClicked {
- UITable *table = [list_ table];
- BOOL editing = [table isRowDeletionEnabled];
- [table enableRowDeletion:!editing animated:YES];
- [book_ reloadButtonsForPage:self];
-}
-
-- (NSString *) title {
- return CYLocalize("SOURCES");
+ [alert show];
}
-- (NSString *) leftButtonTitle {
- return [[list_ table] isRowDeletionEnabled] ? CYLocalize("ADD") : nil;
+- (void) updateButtonsForEditingStatus:(BOOL)editing animated:(BOOL)animated {
+ UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("ADD")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(addButtonClicked)
+ ];
+ [[self navigationItem] setLeftBarButtonItem:editing ? leftItem : [[self navigationItem] backBarButtonItem] animated:animated];
+ [leftItem release];
+
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:editing ? UCLocalize("DONE") : UCLocalize("EDIT")
+ style:editing ? UIBarButtonItemStyleDone : UIBarButtonItemStylePlain
+ target:self
+ action:@selector(editButtonClicked)
+ ];
+ [[self navigationItem] setRightBarButtonItem:rightItem animated:animated];
+ [rightItem release];
+
+ if (IsWildcat_ && !editing) {
+ UIBarButtonItem *settingsItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("SETTINGS")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(settingsButtonClicked)
+ ];
+ [[self navigationItem] setLeftBarButtonItem:settingsItem];
+ [settingsItem release];
+ }
}
-- (id) rightButtonTitle {
- return [[list_ table] isRowDeletionEnabled] ? CYLocalize("DONE") : CYLocalize("EDIT");
+- (void) settingsButtonClicked {
+ [delegate_ showSettings];
}
-- (UINavigationButtonStyle) rightButtonStyle {
- return [[list_ table] isRowDeletionEnabled] ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
+- (void) editButtonClicked {
+ [list_ setEditing:![list_ isEditing] animated:YES];
+
+ [self updateButtonsForEditingStatus:[list_ isEditing] animated:YES];
}
@end
/* }}} */
-/* Installed View {{{ */
-@interface InstalledView : RVPage {
- _transient Database *database_;
- FilteredPackageTable *packages_;
+/* Installed Controller {{{ */
+@interface InstalledController : FilteredPackageController {
BOOL expert_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
@end
-@implementation InstalledView
+@implementation InstalledController
- (void) dealloc {
- [packages_ release];
[super dealloc];
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
- database_ = database;
-
- packages_ = [[FilteredPackageTable alloc]
- initWithBook:book
- database:database
- title:nil
- filter:@selector(isInstalledAndVisible:)
- with:[NSNumber numberWithBool:YES]
- ];
-
- [self addSubview:packages_];
+- (id) title { return UCLocalize("INSTALLED"); }
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndVisible:) with:[NSNumber numberWithBool:YES]]) != nil) {
+ [self updateRoleButton];
+ [self queueStatusDidChange];
} return self;
}
-- (void) resetViewAnimated:(BOOL)animated {
- [packages_ resetViewAnimated:animated];
+#if !AlwaysReload
+- (void) queueButtonClicked {
+ [delegate_ queue];
}
+#endif
-- (void) reloadData {
- [packages_ reloadData];
+- (void) queueStatusDidChange {
+#if !AlwaysReload
+ if (IsWildcat_) {
+ UIBarButtonItem *queueItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("QUEUE")
+ style:UIBarButtonItemStyleDone
+ target:self
+ action:@selector(queueButtonClicked)
+ ];
+ if (Queuing_) [[self navigationItem] setLeftBarButtonItem:queueItem];
+ else [[self navigationItem] setLeftBarButtonItem:nil];
+ [queueItem release];
+ }
+#endif
}
-- (void) _rightButtonClicked {
- [packages_ setObject:[NSNumber numberWithBool:expert_]];
+- (void) reloadData {
[packages_ reloadData];
- expert_ = !expert_;
- [book_ reloadButtonsForPage:self];
-}
-
-- (NSString *) title {
- return CYLocalize("INSTALLED");
}
-- (NSString *) backButtonTitle {
- return CYLocalize("PACKAGES");
+- (void) updateRoleButton {
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:expert_ ? UCLocalize("EXPERT") : UCLocalize("SIMPLE")
+ style:expert_ ? UIBarButtonItemStyleDone : UIBarButtonItemStylePlain
+ target:self
+ action:@selector(roleButtonClicked)
+ ];
+ if (Role_ != nil && ![Role_ isEqualToString:@"Developer"]) [[self navigationItem] setRightBarButtonItem:rightItem];
+ [rightItem release];
}
-- (id) rightButtonTitle {
- return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? CYLocalize("EXPERT") : CYLocalize("SIMPLE");
-}
+- (void) roleButtonClicked {
+ [packages_ setObject:[NSNumber numberWithBool:expert_]];
+ [packages_ reloadData];
+ expert_ = !expert_;
-- (UINavigationButtonStyle) rightButtonStyle {
- return expert_ ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
+ [self updateRoleButton];
}
- (void) setDelegate:(id)delegate {
@end
/* }}} */
-/* Home View {{{ */
-@interface HomeView : BrowserView {
+/* Home Controller {{{ */
+@interface HomeController : CYBrowserController {
}
@end
-@implementation HomeView
-
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
+@implementation HomeController
- if ([context isEqualToString:@"about"])
- [sheet dismiss];
- else
- [super alertSheet:sheet buttonClicked:button];
+- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
+ [super _setMoreHeaders:request];
+ if (ChipID_ != nil)
+ [request setValue:ChipID_ forHTTPHeaderField:@"X-Chip-ID"];
+ if (UniqueID_ != nil)
+ [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
}
-- (void) _leftButtonClicked {
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("ABOUT_CYDIA")
- buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil]
- defaultButtonIndex:0
- delegate:self
- context:@"about"
- ] autorelease];
+- (void) aboutButtonClicked {
+ UIAlertView *alert = [[[UIAlertView alloc] init] autorelease];
+ [alert setTitle:UCLocalize("ABOUT_CYDIA")];
+ [alert addButtonWithTitle:UCLocalize("CLOSE")];
+ [alert setCancelButtonIndex:0];
- [sheet setBodyText:
- @"Copyright (C) 2008-2009\n"
+ [alert setMessage:
+ @"Copyright (C) 2008-2010\n"
"Jay Freeman (saurik)\n"
"saurik@saurik.com\n"
- "http://www.saurik.com/\n"
- "\n"
- "The Okori Group\n"
- "http://www.theokorigroup.com/\n"
- "\n"
- "College of Creative Studies,\n"
- "University of California,\n"
- "Santa Barbara\n"
- "http://www.ccs.ucsb.edu/"
+ "http://www.saurik.com/"
];
- [sheet popupAlertAnimated:YES];
+ [alert show];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [[self navigationController] setNavigationBarHidden:YES animated:animated];
+}
+
+- (void) viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [[self navigationController] setNavigationBarHidden:NO animated:animated];
}
-- (NSString *) leftButtonTitle {
- return CYLocalize("ABOUT");
+- (id) init {
+ if ((self = [super init]) != nil) {
+ UIBarButtonItem *aboutItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("ABOUT")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(aboutButtonClicked)
+ ];
+ [[self navigationItem] setLeftBarButtonItem:aboutItem];
+ [aboutItem release];
+ } return self;
}
@end
/* }}} */
-/* Manage View {{{ */
-@interface ManageView : BrowserView {
+/* Manage Controller {{{ */
+@interface ManageController : CYBrowserController {
}
@end
-@implementation ManageView
-
-- (NSString *) title {
- return CYLocalize("MANAGE");
-}
+@implementation ManageController
-- (void) _leftButtonClicked {
- [delegate_ askForSettings];
+- (id) init {
+ if ((self = [super init]) != nil) {
+ [[self navigationItem] setTitle:UCLocalize("MANAGE")];
+
+ UIBarButtonItem *settingsItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("SETTINGS")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(settingsButtonClicked)
+ ];
+ [[self navigationItem] setLeftBarButtonItem:settingsItem];
+ [settingsItem release];
+
+ [self queueStatusDidChange];
+ } return self;
}
-- (NSString *) leftButtonTitle {
- return CYLocalize("SETTINGS");
+- (void) settingsButtonClicked {
+ [delegate_ showSettings];
}
#if !AlwaysReload
-- (id) _rightButtonTitle {
- return Queuing_ ? CYLocalize("QUEUE") : nil;
+- (void) queueButtonClicked {
+ [delegate_ queue];
}
-- (UINavigationButtonStyle) rightButtonStyle {
- return Queuing_ ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
+- (void) applyLoadingTitle {
+ // No "Loading" title.
}
-- (void) _rightButtonClicked {
- [delegate_ queue];
+- (void) applyRightButton {
+ // No right button.
}
#endif
+- (void) queueStatusDidChange {
+#if !AlwaysReload
+ if (!IsWildcat_ && Queuing_) {
+ UIBarButtonItem *queueItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("QUEUE")
+ style:UIBarButtonItemStyleDone
+ target:self
+ action:@selector(queueButtonClicked)
+ ];
+ [[self navigationItem] setRightBarButtonItem:queueItem];
+
+ [queueItem release];
+ } else {
+ [[self navigationItem] setRightBarButtonItem:nil];
+ }
+#endif
+}
+
- (bool) isLoading {
return false;
}
@end
/* }}} */
-#include <BrowserView.m>
-
-/* Cydia Book {{{ */
-@interface CYBook : RVBook <
- ProgressDelegate
-> {
- _transient Database *database_;
- UINavigationBar *overlay_;
- UINavigationBar *underlay_;
+/* Refresh Bar {{{ */
+@interface RefreshBar : UINavigationBar {
UIProgressIndicator *indicator_;
UITextLabel *prompt_;
UIProgressBar *progress_;
UINavigationButton *cancel_;
- bool updating_;
}
-- (id) initWithFrame:(CGRect)frame database:(Database *)database;
-- (void) update;
-- (BOOL) updating;
-
@end
-@implementation CYBook
-
-- (void) dealloc {
- [overlay_ release];
- [indicator_ release];
- [prompt_ release];
- [progress_ release];
- [cancel_ release];
- [super dealloc];
-}
-
-- (NSString *) getTitleForPage:(RVPage *)page {
- return [super getTitleForPage:page];
-}
-
-- (BOOL) updating {
- return updating_;
-}
-
-- (void) update {
- [UIView beginAnimations:nil context:NULL];
-
- CGRect ovrframe = [overlay_ frame];
- ovrframe.origin.y = 0;
- [overlay_ setFrame:ovrframe];
-
- 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:CYLocalize("UPDATING_DATABASE")];
- [progress_ setProgress:0];
-
- updating_ = true;
- [overlay_ addSubview:cancel_];
-
- [NSThread
- detachNewThreadSelector:@selector(_update)
- toTarget:self
- withObject:nil
- ];
-}
-
-- (void) _update_ {
- updating_ = false;
-
- [indicator_ stopAnimation];
-
- [UIView beginAnimations:nil context:NULL];
-
- CGRect ovrframe = [overlay_ frame];
- ovrframe.origin.y = -ovrframe.size.height;
- [overlay_ setFrame:ovrframe];
-
- 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 commitAnimations];
-
- [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
-}
-
-- (id) initWithFrame:(CGRect)frame database:(Database *)database {
- if ((self = [super initWithFrame:frame]) != nil) {
- database_ = database;
-
- CGRect ovrrect = [navbar_ bounds];
- ovrrect.size.height = [UINavigationBar defaultSize].height;
- ovrrect.origin.y = -ovrrect.size.height;
-
- overlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect];
- [self addSubview:overlay_];
-
- 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;
+@implementation RefreshBar
+
+- (void) positionViews {
+ CGRect frame = [cancel_ frame];
+ frame.origin.x = [self frame].size.width - frame.size.width - 5;
+ frame.origin.y = ([self frame].size.height - frame.size.height) / 2;
+ [cancel_ setFrame:frame];
+
+ CGSize prgsize = {75, 100};
+ CGRect prgrect = {{
+ [self frame].size.width - prgsize.width - 10,
+ ([self frame].size.height - prgsize.height) / 2
+ } , prgsize};
+ [progress_ setFrame:prgrect];
+
+ CGSize indsize([UIProgressIndicator defaultSizeForStyle:[indicator_ activityIndicatorViewStyle]]);
+ unsigned indoffset = ([self frame].size.height - indsize.height) / 2;
+ CGRect indrect = {{indoffset, indoffset}, indsize};
+ [indicator_ setFrame:indrect];
+
+ CGSize prmsize = {215, indsize.height + 4};
+ CGRect prmrect = {{
+ indoffset * 2 + indsize.width,
+ unsigned([self frame].size.height - prmsize.height) / 2 - 1
+ }, prmsize};
+ [prompt_ setFrame:prmrect];
+}
+
+- (void)setFrame:(CGRect)frame {
+ [super setFrame:frame];
+
+ [self positionViews];
+}
+
+- (id) initWithFrame:(CGRect)frame delegate:(id)delegate {
+ if ((self = [super initWithFrame:frame])) {
+ [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
+
+ [self setTintColor:[UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1]];
+ [self setBarStyle:1];
+
+ int barstyle([self _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_ = [[UIProgressIndicator alloc] initWithFrame:CGRectZero];
[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];
+ [indicator_ startAnimation];
+ [self addSubview:indicator_];
+ prompt_ = [[UITextLabel alloc] initWithFrame:CGRectZero];
[prompt_ setColor:[UIColor colorWithCGColor:(ugly ? Blueish_ : Off_)]];
[prompt_ setBackgroundColor:[UIColor clearColor]];
- [prompt_ setFont:font];
-
- [overlay_ addSubview:prompt_];
-
- CGSize prgsize = {75, 100};
+ [prompt_ setFont:[UIFont systemFontOfSize:15]];
+ [self addSubview:prompt_];
- CGRect prgrect = {{
- ovrrect.size.width - prgsize.width - 10,
- (ovrrect.size.height - prgsize.height) / 2
- } , prgsize};
-
- progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
+ progress_ = [[UIProgressBar alloc] initWithFrame:CGRectZero];
+ [progress_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin];
[progress_ setStyle:0];
- [overlay_ addSubview:progress_];
-
- cancel_ = [[UINavigationButton alloc] initWithTitle:CYLocalize("CANCEL") style:UINavigationButtonStyleHighlighted];
- [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside];
-
- CGRect frame = [cancel_ frame];
- frame.origin.x = ovrrect.size.width - frame.size.width - 5;
- frame.origin.y = (ovrrect.size.height - frame.size.height) / 2;
- [cancel_ setFrame:frame];
-
+ [self addSubview:progress_];
+
+ cancel_ = [[UINavigationButton alloc] initWithTitle:UCLocalize("CANCEL") style:UINavigationButtonStyleHighlighted];
+ [cancel_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
+ [cancel_ addTarget:delegate action:@selector(cancelPressed) forControlEvents:UIControlEventTouchUpInside];
[cancel_ setBarStyle:barstyle];
+
+ [self positionViews];
} return self;
}
-- (void) _onCancel {
- updating_ = false;
+- (void) cancel {
[cancel_ removeFromSuperview];
}
-- (void) _update { _pooled
- Status status;
- status.setDelegate(self);
-
- [database_ updateWithStatus:status];
-
- [self
- performSelectorOnMainThread:@selector(_update_)
- withObject:nil
- waitUntilDone:NO
- ];
+- (void) start {
+ [prompt_ setText:UCLocalize("UPDATING_DATABASE")];
+ [progress_ setProgress:0];
+ [self addSubview:cancel_];
}
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
- [prompt_ setText:[NSString stringWithFormat:CYLocalize("COLON_DELIMITED"), CYLocalize("ERROR"), error]];
+- (void) stop {
+ [cancel_ removeFromSuperview];
}
-- (void) setProgressTitle:(NSString *)title {
- [self
- performSelectorOnMainThread:@selector(_setProgressTitle:)
- withObject:title
- waitUntilDone:YES
- ];
+- (void) setPrompt:(NSString *)prompt {
+ [prompt_ setText:prompt];
}
-- (void) setProgressPercent:(float)percent {
- [self
- performSelectorOnMainThread:@selector(_setProgressPercent:)
- withObject:[NSNumber numberWithFloat:percent]
- waitUntilDone:YES
- ];
+- (void) setProgress:(float)progress {
+ [progress_ setProgress:progress];
}
-- (void) startProgress {
-}
+@end
+/* }}} */
-- (void) addProgressOutput:(NSString *)output {
- [self
- performSelectorOnMainThread:@selector(_addProgressOutput:)
- withObject:output
- waitUntilDone:YES
- ];
+/* Cydia Tab Bar Controller {{{ */
+@interface CYTabBarController : UITabBarController {
+ Database *database_;
}
-- (bool) isCancelling:(size_t)received {
- return !updating_;
-}
+@end
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- [sheet dismiss];
-}
+@implementation CYTabBarController
-- (void) _setProgressTitle:(NSString *)title {
- [prompt_ setText:title];
-}
+/* XXX: some logic should probably go here related to
+freeing the view controllers on tab change */
-- (void) _setProgressPercent:(NSNumber *)percent {
- [progress_ setProgress:[percent floatValue]];
+- (void) reloadData {
+ size_t count([[self viewControllers] count]);
+ for (size_t i(0); i != count; ++i) {
+ UIViewController *page([[self viewControllers] objectAtIndex:(count - i - 1)]);
+ [page reloadData];
+ }
}
-- (void) _addProgressOutput:(NSString *)output {
+- (id) initWithDatabase: (Database *)database {
+ if ((self = [super init]) != nil) {
+ database_ = database;
+ } return self;
}
@end
/* }}} */
-/* Cydia:// Protocol {{{ */
-@interface CydiaURLProtocol : NSURLProtocol {
+
+/* Cydia Navigation Controller {{{ */
+@interface CYNavigationController : UINavigationController <
+ ProgressDelegate
+> {
+ _transient Database *database_;
+ id delegate_;
}
+- (id) initWithDatabase:(Database *)database;
+- (void) reloadData;
+
@end
-@implementation CydiaURLProtocol
-+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
+@implementation CYNavigationController
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
+ // Inherit autorotation settings for modal parents.
+ if ([self parentViewController] && [[self parentViewController] modalViewController] == self) {
+ return [[self parentViewController] shouldAutorotateToInterfaceOrientation:orientation];
+ } else {
+ return [super shouldAutorotateToInterfaceOrientation:orientation];
+ }
+}
+
+- (void) dealloc {
+ [super dealloc];
+}
+
+- (void) reloadData {
+ size_t count([[self viewControllers] count]);
+ for (size_t i(0); i != count; ++i) {
+ UIViewController *page([[self viewControllers] objectAtIndex:(count - i - 1)]);
+ [page reloadData];
+ }
+}
+
+- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
+}
+
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
+ database_ = database;
+ } return self;
+}
+
+@end
+/* }}} */
+/* Cydia:// Protocol {{{ */
+@interface CydiaURLProtocol : NSURLProtocol {
+}
+
+@end
+
+@implementation CydiaURLProtocol
+
++ (BOOL) canInitWithRequest:(NSURLRequest *)request {
NSURL *url([request URL]);
if (url == nil)
return NO;
@end
/* }}} */
-/* Sections View {{{ */
-@interface SectionsView : RVPage {
+/* Sections Controller {{{ */
+@interface SectionsController : CYViewController {
_transient Database *database_;
NSMutableArray *sections_;
NSMutableArray *filtered_;
- UITransitionView *transition_;
- UITable *list_;
+ UITableView *list_;
UIView *accessory_;
BOOL editing_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
- (void) reloadData;
- (void) resetView;
@end
-@implementation SectionsView
+@implementation SectionsController
- (void) dealloc {
[list_ setDataSource:nil];
[sections_ release];
[filtered_ release];
- [transition_ release];
[list_ release];
[accessory_ release];
[super dealloc];
}
-- (int) numberOfRowsInTable:(UITable *)table {
- return editing_ ? [sections_ count] : [filtered_ count] + 1;
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
}
-- (float) table:(UITable *)table heightForRow:(int)row {
- return 45;
+- (Section *) sectionAtIndexPath:(NSIndexPath *)indexPath {
+ Section *section = (editing_ ? [sections_ objectAtIndex:[indexPath row]] : ([indexPath row] == 0 ? nil : [filtered_ objectAtIndex:([indexPath row] - 1)]));
+ return section;
}
-- (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;
+- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(int)section {
+ return editing_ ? [sections_ count] : [filtered_ count] + 1;
}
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
- return !editing_;
-}
+/*- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+ return 45.0f;
+}*/
-- (BOOL) table:(UITable *)table canSelectRow:(int)row {
- return !editing_;
-}
+- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ static NSString *reuseIdentifier = @"SectionCell";
-- (void) tableRowSelected:(NSNotification *)notification {
- int row = [[notification object] selectedRow];
- if (row == INT_MAX)
- return;
+ SectionCell *cell = (SectionCell *) [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
+ if (cell == nil) cell = [[[SectionCell alloc] initWithFrame:CGRectZero reuseIdentifier:reuseIdentifier] autorelease];
+ [cell setSection:[self sectionAtIndexPath:indexPath] editing:editing_];
- Section *section;
- NSString *name;
+ return cell;
+}
+
+- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ Section *section = [self sectionAtIndexPath:indexPath];
+ NSString *name = [section name];
NSString *title;
- if (row == 0) {
+ if ([indexPath row] == 0) {
section = nil;
name = nil;
- title = CYLocalize("ALL_PACKAGES");
+ title = UCLocalize("ALL_PACKAGES");
} else {
- section = [filtered_ objectAtIndex:(row - 1)];
- name = [section name];
-
- if (name != nil)
+ if (name != nil) {
+ name = [NSString stringWithString:name];
title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"];
- else {
+ } else {
name = @"";
- title = CYLocalize("NO_SECTION");
+ title = UCLocalize("NO_SECTION");
}
}
- PackageTable *table = [[[FilteredPackageTable alloc]
- initWithBook:book_
- database:database_
+ FilteredPackageController *table = [[[FilteredPackageController alloc]
+ initWithDatabase:database_
title:title
- filter:@selector(isVisiblyUninstalledInSection:)
+ filter:@selector(isVisibleInSection:)
with:name
] autorelease];
[table setDelegate:delegate_];
- [book_ pushPage:table];
+ [[self navigationController] pushViewController:table animated:YES];
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) title { return UCLocalize("SECTIONS"); }
+
+- (id) initWithDatabase:(Database *)database {
+ if ((self = [super init]) != nil) {
database_ = database;
+ [[self navigationItem] setTitle:UCLocalize("SECTIONS")];
+
sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
filtered_ = [[NSMutableArray arrayWithCapacity:16] retain];
- transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
- [self addSubview:transition_];
-
- list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
- [transition_ transition:0 toView:list_];
-
- UITableColumn *column = [[[UITableColumn alloc]
- initWithTitle:CYLocalize("NAME")
- identifier:@"name"
- width:[self frame].size.width
- ] autorelease];
+ list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
+ [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [list_ setRowHeight:45.0f];
+ [[self view] addSubview:list_];
[list_ setDataSource:self];
- [list_ setSeparatorStyle:1];
- [list_ addTableColumn:column];
[list_ setDelegate:self];
- [list_ setReusesTableCells:YES];
[self reloadData];
-
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
} return self;
}
[*section addToCount];
_profile(SectionsView$reloadData$Filter)
- if (![package valid] || [package installed] != nil || ![package visible])
+ if (![package valid] || ![package visible])
continue;
_end
[section addToCount];
_profile(SectionsView$reloadData$Filter)
- if (![package valid] || [package installed] != nil || ![package visible])
+ if (![package valid] || ![package visible])
continue;
_end
[filtered_ addObject:section];
}
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:[sections_ count] == 0 ? nil : UCLocalize("EDIT")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(editButtonClicked)
+ ];
+ [[self navigationItem] setRightBarButtonItem:rightItem animated:[[self navigationItem] rightBarButtonItem] != nil];
+ [rightItem release];
+
[list_ reloadData];
_trace();
}
- (void) resetView {
if (editing_)
- [self _rightButtonClicked];
+ [self editButtonClicked];
}
-- (void) resetViewAnimated:(BOOL)animated {
- [list_ resetViewAnimated:animated];
-}
-
-- (void) _rightButtonClicked {
+- (void) editButtonClicked {
if ((editing_ = !editing_))
[list_ reloadData];
else
[delegate_ updateData];
- [book_ reloadTitleForPage:self];
- [book_ reloadButtonsForPage:self];
-}
-
-- (NSString *) title {
- return editing_ ? CYLocalize("SECTION_VISIBILITY") : CYLocalize("INSTALL_BY_SECTION");
-}
-
-- (NSString *) backButtonTitle {
- return CYLocalize("SECTIONS");
-}
-
-- (id) rightButtonTitle {
- return [sections_ count] == 0 ? nil : editing_ ? CYLocalize("DONE") : CYLocalize("EDIT");
-}
-
-- (UINavigationButtonStyle) rightButtonStyle {
- return editing_ ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
+
+ [[self navigationItem] setTitle:editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS")];
+ [[[self navigationItem] rightBarButtonItem] setTitle:[sections_ count] == 0 ? nil : editing_ ? UCLocalize("DONE") : UCLocalize("EDIT")];
+ [[[self navigationItem] rightBarButtonItem] setStyle:editing_ ? UIBarButtonItemStyleDone : UIBarButtonItemStylePlain];
}
- (UIView *) accessoryView {
@end
/* }}} */
-/* Changes View {{{ */
-@interface ChangesView : RVPage {
+/* Changes Controller {{{ */
+@interface ChangesController : CYViewController {
_transient Database *database_;
NSMutableArray *packages_;
NSMutableArray *sections_;
- UISectionList *list_;
+ UITableView *list_;
unsigned upgrades_;
+ BOOL hasSentFirstLoad_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate;
- (void) reloadData;
@end
-@implementation ChangesView
+@implementation ChangesController
- (void) dealloc {
- [[list_ table] setDelegate:nil];
+ [list_ setDelegate:nil];
[list_ setDataSource:nil];
[packages_ release];
[super dealloc];
}
-- (int) numberOfSectionsInSectionList:(UISectionList *)list {
- return [sections_ count];
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ if (!hasSentFirstLoad_) {
+ hasSentFirstLoad_ = YES;
+ [self performSelector:@selector(reloadData) withObject:nil afterDelay:0.0];
+ } else {
+ [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
+ }
}
-- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
- return [[sections_ objectAtIndex:section] name];
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
+ NSInteger count([sections_ count]);
+ return count == 0 ? 1 : count;
}
-- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
- return [[sections_ objectAtIndex:section] row];
+- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
+ if ([sections_ count] == 0)
+ return nil;
+ return [[sections_ objectAtIndex:section] name];
}
-- (int) numberOfRowsInTable:(UITable *)table {
- return [packages_ count];
+- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
+ if ([sections_ count] == 0)
+ return 0;
+ return [[sections_ objectAtIndex:section] count];
}
-- (float) table:(UITable *)table heightForRow:(int)row {
- return [PackageCell heightForPackage:[packages_ objectAtIndex:row]];
+- (Package *) packageAtIndexPath:(NSIndexPath *)path {
+ Section *section([sections_ objectAtIndex:[path section]]);
+ NSInteger row([path row]);
+ return [packages_ objectAtIndex:([section row] + row)];
}
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
- if (reusing == nil)
- reusing = [[[PackageCell alloc] init] autorelease];
- [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
- return reusing;
+- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
+ PackageCell *cell([table dequeueReusableCellWithIdentifier:@"Package"]);
+ if (cell == nil)
+ cell = [[[PackageCell alloc] init] autorelease];
+ [cell setPackage:[self packageAtIndexPath:path]];
+ return cell;
}
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
- return NO;
-}
+/*- (CGFloat) tableView:(UITableView *)table heightForRowAtIndexPath:(NSIndexPath *)path {
+ return [PackageCell heightForPackage:[self packageAtIndexPath:path]];
+}*/
-- (void) tableRowSelected:(NSNotification *)notification {
- int row = [[notification object] selectedRow];
- if (row == INT_MAX)
- return;
- Package *package = [packages_ objectAtIndex:row];
- PackageView *view([delegate_ packageView]);
+- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
+ Package *package([self packageAtIndexPath:path]);
+ PackageController *view([delegate_ packageController]);
[view setDelegate:delegate_];
[view setPackage:package];
- [book_ pushPage:view];
+ [[self navigationController] pushViewController:view animated:YES];
+ return path;
}
-- (void) _leftButtonClicked {
- [(CYBook *)book_ update];
- [self reloadButtons];
+- (void) refreshButtonClicked {
+ [[UIApplication sharedApplication] beginUpdate];
+ [[self navigationItem] setLeftBarButtonItem:nil];
}
-- (void) _rightButtonClicked {
+- (void) upgradeButtonClicked {
[delegate_ distUpgrade];
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) title { return UCLocalize("CHANGES"); }
+
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate {
+ if ((self = [super init]) != nil) {
database_ = database;
+ [[self navigationItem] setTitle:UCLocalize("CHANGES")];
packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
- list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:NO];
- [self addSubview:list_];
+ list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
+ [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [list_ setRowHeight:73.0f];
+ [[self view] addSubview:list_];
- [list_ setShouldHideHeaderInShortLists:NO];
[list_ setDataSource:self];
- //[list_ setSectionListStyle:1];
-
- UITableColumn *column = [[[UITableColumn alloc]
- initWithTitle:CYLocalize("NAME")
- identifier:@"name"
- width:[self frame].size.width
- ] autorelease];
-
- UITable *table = [list_ table];
- [table setSeparatorStyle:1];
- [table addTableColumn:column];
- [table setDelegate:self];
- [table setReusesTableCells:YES];
-
- [self reloadData];
+ [list_ setDelegate:self];
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+ delegate_ = delegate;
} return self;
}
-- (void) reloadData {
- NSArray *packages = [database_ packages];
-
- [packages_ removeAllObjects];
- [sections_ removeAllObjects];
-
+- (void) _reloadPackages:(NSArray *)packages {
_trace();
for (Package *package in packages)
if (
- [package installed] == nil && [package valid] && [package visible] ||
+ [package uninstalled] && [package valid] && [package visible] ||
[package upgradableAndEssential:YES]
)
[packages_ addObject:package];
_trace();
[packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
_trace();
+}
- Section *upgradable = [[[Section alloc] initWithName:CYLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
- Section *ignored = [[[Section alloc] initWithName:CYLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
+- (void) reloadData {
+ NSArray *packages = [database_ packages];
+
+ [packages_ removeAllObjects];
+ [sections_ removeAllObjects];
+
+ UIProgressHUD *hud([delegate_ addProgressHUD]);
+ // XXX: localize
+ [hud setText:@"Loading Changes"];
+ NSLog(@"HUD:%@::%@", delegate_, hud);
+ [self yieldToSelector:@selector(_reloadPackages:) withObject:packages];
+ [delegate_ removeProgressHUD:hud];
+
+ Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
+ Section *ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
Section *section = nil;
NSDate *last = nil;
unseens = true;
NSDate *seen;
- _profile(ChangesView$reloadData$Remember)
+ _profile(ChangesController$reloadData$Remember)
seen = [package seen];
_end
NSString *name;
if (seen == nil)
- name = CYLocalize("UNKNOWN");
+ name = UCLocalize("UNKNOWN");
else {
name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
[name autorelease];
}
- _profile(ChangesView$reloadData$Allocate)
- name = [NSString stringWithFormat:CYLocalize("NEW_AT"), name];
+ _profile(ChangesController$reloadData$Allocate)
+ name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
[sections_ addObject:section];
_end
[sections_ insertObject:upgradable atIndex:0];
[list_ reloadData];
- [self reloadButtons];
-}
-
-- (void) resetViewAnimated:(BOOL)animated {
- [list_ resetViewAnimated:animated];
-}
-- (NSString *) leftButtonTitle {
- return [(CYBook *)book_ updating] ? nil : CYLocalize("REFRESH");
-}
-
-- (id) rightButtonTitle {
- return upgrades_ == 0 ? nil : [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]];
-}
-
-- (NSString *) title {
- return CYLocalize("CHANGES");
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(upgradeButtonClicked)
+ ];
+ if (upgrades_ > 0) [[self navigationItem] setRightBarButtonItem:rightItem];
+ [rightItem release];
+
+ UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("REFRESH")
+ style:UIBarButtonItemStylePlain
+ target:self
+ action:@selector(refreshButtonClicked)
+ ];
+ if (![[UIApplication sharedApplication] updating]) [[self navigationItem] setLeftBarButtonItem:leftItem];
+ [leftItem release];
}
@end
/* }}} */
-/* Search View {{{ */
-@protocol SearchViewDelegate
-- (void) showKeyboard:(BOOL)show;
-@end
-
-@interface SearchView : RVPage {
- UIView *accessory_;
- UISearchField *field_;
- UITransitionView *transition_;
- FilteredPackageTable *table_;
- UIPreferencesTable *advanced_;
- UIView *dimmed_;
- bool flipped_;
- bool reload_;
+/* Search Controller {{{ */
+@interface SearchController : FilteredPackageController {
+ id search_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithDatabase:(Database *)database;
- (void) reloadData;
@end
-@implementation SearchView
+@implementation SearchController
- (void) dealloc {
- [field_ setDelegate:nil];
-
- [accessory_ release];
- [field_ release];
- [transition_ release];
- [table_ release];
- [advanced_ release];
- [dimmed_ release];
+ [search_ release];
[super dealloc];
}
-- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
- return 1;
-}
-
-- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
- switch (group) {
- case 0: return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("ADVANCED_SEARCH"), CYLocalize("COMING_SOON")];
-
- default: _assert(false);
- }
-}
-
-- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
- switch (group) {
- case 0: return 0;
-
- default: _assert(false);
- }
-}
-
-- (void) _showKeyboard:(BOOL)show {
- CGSize keysize = [UIKeyboard defaultSize];
- CGRect keydown = [book_ pageBounds];
- CGRect keyup = keydown;
- keyup.size.height -= keysize.height - ButtonBarHeight_;
-
- float delay = KeyboardTime_ * ButtonBarHeight_ / keysize.height;
-
- UIFrameAnimation *animation = [[[UIFrameAnimation alloc] initWithTarget:[table_ list]] autorelease];
- [animation setSignificantRectFields:8];
-
- if (show) {
- [animation setStartFrame:keydown];
- [animation setEndFrame:keyup];
- } else {
- [animation setStartFrame:keyup];
- [animation setEndFrame:keydown];
- }
-
- UIAnimator *animator = [UIAnimator sharedAnimator];
-
- [animator
- addAnimations:[NSArray arrayWithObjects:animation, nil]
- withDuration:(KeyboardTime_ - delay)
- start:!show
- ];
-
- if (show)
- [animator performSelector:@selector(startAnimation:) withObject:animation afterDelay:delay];
-
- [delegate_ showKeyboard:show];
-}
-
-- (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
- [self _showKeyboard:YES];
-}
-
-- (void) textFieldDidResignFirstResponder:(UITextField *)field {
- [self _showKeyboard:NO];
+- (void) searchBarSearchButtonClicked:(id)searchBar {
+ [packages_ setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
+ [search_ resignFirstResponder];
+ [self reloadData];
}
-- (void) keyboardInputChanged:(UIFieldEditor *)editor {
- if (reload_) {
- NSString *text([field_ text]);
- [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
- [self reloadData];
- reload_ = false;
- }
+- (void) searchBar:(id)searchBar textDidChange:(NSString *)text {
+ [packages_ setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
+ [self reloadData];
}
-- (void) textFieldClearButtonPressed:(UITextField *)field {
- reload_ = true;
-}
+- (id) title { return nil; }
-- (void) keyboardInputShouldDelete:(id)input {
- reload_ = true;
+- (id) initWithDatabase:(Database *)database {
+ return [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil];
}
-- (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
- if ([text length] != 1 || [text characterAtIndex:0] != '\n') {
- reload_ = true;
- return YES;
- } else {
- [field_ resignFirstResponder];
- return NO;
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ if (!search_) {
+ search_ = [[objc_getClass("UISearchBar") alloc] initWithFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
+ [search_ layoutSubviews];
+ [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
+ UITextField *textField = [search_ searchField];
+ [textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+ [search_ setDelegate:self];
+ [textField setEnablesReturnKeyAutomatically:NO];
+ [[self navigationItem] setTitleView:textField];
}
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
- if ((self = [super initWithBook:book]) != nil) {
- CGRect pageBounds = [book_ pageBounds];
-
- transition_ = [[UITransitionView alloc] initWithFrame:pageBounds];
- [self addSubview:transition_];
-
- advanced_ = [[UIPreferencesTable alloc] initWithFrame:pageBounds];
-
- [advanced_ setReusesTableCells:YES];
- [advanced_ setDataSource:self];
- [advanced_ reloadData];
-
- dimmed_ = [[UIView alloc] initWithFrame:pageBounds];
- CGColor dimmed(space_, 0, 0, 0, 0.5);
- [dimmed_ setBackgroundColor:[UIColor colorWithCGColor:dimmed]];
-
- table_ = [[FilteredPackageTable alloc]
- initWithBook:book
- database:database
- title:nil
- filter:@selector(isUnfilteredAndSearchedForBy:)
- with:nil
- ];
-
- [table_ setShouldHideHeaderInShortLists:NO];
- [transition_ transition:0 toView:table_];
-
- CGRect cnfrect = {{
-#ifdef __OBJC2__
- 6 +
-#endif
- 1, 38}, {17, 18}};
-
- CGRect area;
- area.origin.x = /*cnfrect.origin.x + cnfrect.size.width + 4 +*/ 10;
- area.origin.y = 1;
-
- area.size.width =
-#ifdef __OBJC2__
- 8 +
-#endif
- [self bounds].size.width - area.origin.x - 18;
-
- area.size.height = [UISearchField defaultHeight];
-
- field_ = [[UISearchField alloc] initWithFrame:area];
-
- UIFont *font = [UIFont systemFontOfSize:16];
- [field_ setFont:font];
-
- [field_ setPlaceholder:CYLocalize("SEARCH_EX")];
- [field_ setDelegate:self];
-
- [field_ setPaddingTop:5];
-
- UITextInputTraits *traits([field_ textInputTraits]);
- [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
- [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
- [traits setReturnKeyType:UIReturnKeySearch];
-
- CGRect accrect = {{0, 6}, {6 + cnfrect.size.width + 6 + area.size.width + 6, area.size.height}};
-
- accessory_ = [[UIView alloc] initWithFrame:accrect];
- [accessory_ addSubview:field_];
-
- /*UIPushButton *configure = [[[UIPushButton alloc] initWithFrame:cnfrect] autorelease];
- [configure setShowPressFeedback:YES];
- [configure setImage:[UIImage applicationImageNamed:@"advanced.png"]];
- [configure addTarget:self action:@selector(configurePushed) forEvents:1];
- [accessory_ addSubview:configure];*/
-
- [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- [table_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
- } return self;
-}
-
-- (void) flipPage {
-#ifndef __OBJC2__
- LKAnimation *animation = [LKTransition animation];
- [animation setType:@"oglFlip"];
- [animation setTimingFunction:[LKTimingFunction functionWithName:@"easeInEaseOut"]];
- [animation setFillMode:@"extended"];
- [animation setTransitionFlags:3];
- [animation setDuration:10];
- [animation setSpeed:0.35];
- [animation setSubtype:(flipped_ ? @"fromLeft" : @"fromRight")];
- [[transition_ _layer] addAnimation:animation forKey:0];
- [transition_ transition:0 toView:(flipped_ ? (UIView *) table_ : (UIView *) advanced_)];
- flipped_ = !flipped_;
-#endif
-}
-
-- (void) configurePushed {
- [field_ resignFirstResponder];
- [self flipPage];
-}
-
-- (void) resetViewAnimated:(BOOL)animated {
- if (flipped_)
- [self flipPage];
- [table_ resetViewAnimated:animated];
-}
-
- (void) _reloadData {
}
- (void) reloadData {
- if (flipped_)
- [self flipPage];
- [table_ setObject:[field_ text]];
- _profile(SearchView$reloadData)
- [table_ reloadData];
+ _profile(SearchController$reloadData)
+ [packages_ reloadData];
_end
PrintTimes();
- [table_ resetCursor];
+ [packages_ resetCursor];
}
-- (UIView *) accessoryView {
- return accessory_;
-}
-
-- (NSString *) title {
- return nil;
-}
-
-- (NSString *) backButtonTitle {
- return CYLocalize("SEARCH");
-}
-
-- (void) setDelegate:(id)delegate {
- [table_ setDelegate:delegate];
- [super setDelegate:delegate];
+- (void) didSelectPackage:(Package *)package {
+ [search_ resignFirstResponder];
+ [super didSelectPackage:package];
}
@end
/* }}} */
-
-@interface SettingsView : RVPage {
+/* Settings Controller {{{ */
+@interface SettingsController : CYViewController {
_transient Database *database_;
NSString *name_;
Package *package_;
UIPreferencesControlTableCell *ignoredCell_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package;
+- (id) initWithDatabase:(Database *)database package:(NSString *)package;
@end
-@implementation SettingsView
+@implementation SettingsController
- (void) dealloc {
[table_ setDataSource:nil];
case 0: return nil;
case 1: return nil;
- default: _assert(false);
+ _nodefault
}
return nil;
case 0: return NO;
case 1: return YES;
- default: _assert(false);
+ _nodefault
}
return NO;
case 0: return 1;
case 1: return 1;
- default: _assert(false);
+ _nodefault
}
return 0;
return subscribedCell_;
case 1:
return ignoredCell_;
- default: _assert(false);
+ _nodefault
} break;
case 1: switch (row) {
case 0: {
UIPreferencesControlTableCell *cell([[[UIPreferencesControlTableCell alloc] init] autorelease]);
[cell setShowSelection:NO];
- [cell setTitle:CYLocalize("SHOW_ALL_CHANGES_EX")];
+ [cell setTitle:UCLocalize("SHOW_ALL_CHANGES_EX")];
return cell;
}
- default: _assert(false);
+ _nodefault
} break;
- default: _assert(false);
+ _nodefault
}
return nil;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package {
- if ((self = [super initWithBook:book])) {
+- (id) title { return UCLocalize("SETTINGS"); }
+
+- (id) initWithDatabase:(Database *)database package:(NSString *)package {
+ if ((self = [super init])) {
database_ = database;
name_ = [package retain];
- table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
- [self addSubview:table_];
+ [[self navigationItem] setTitle:UCLocalize("SETTINGS")];
+
+ table_ = [[UIPreferencesTable alloc] initWithFrame:[[self view] bounds]];
+ [[self view] addSubview:table_];
subscribedSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)];
- [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:kUIControlEventMouseUpInside];
+ [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventTouchUpInside];
ignoredSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)];
- [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:kUIControlEventMouseUpInside];
+ [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventTouchUpInside];
subscribedCell_ = [[UIPreferencesControlTableCell alloc] init];
[subscribedCell_ setShowSelection:NO];
- [subscribedCell_ setTitle:CYLocalize("SHOW_ALL_CHANGES")];
+ [subscribedCell_ setTitle:UCLocalize("SHOW_ALL_CHANGES")];
[subscribedCell_ setControl:subscribedSwitch_];
ignoredCell_ = [[UIPreferencesControlTableCell alloc] init];
[ignoredCell_ setShowSelection:NO];
- [ignoredCell_ setTitle:CYLocalize("IGNORE_UPGRADES")];
+ [ignoredCell_ setTitle:UCLocalize("IGNORE_UPGRADES")];
[ignoredCell_ setControl:ignoredSwitch_];
[table_ setDataSource:self];
} return self;
}
-- (void) resetViewAnimated:(BOOL)animated {
- [table_ resetViewAnimated:animated];
-}
-
- (void) reloadData {
if (package_ != nil)
[package_ autorelease];
[table_ reloadData];
}
-- (NSString *) title {
- return CYLocalize("SETTINGS");
-}
-
@end
+/* }}} */
-/* Signature View {{{ */
-@interface SignatureView : BrowserView {
+/* Signature Controller {{{ */
+@interface SignatureController : CYBrowserController {
_transient Database *database_;
NSString *package_;
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package;
+- (id) initWithDatabase:(Database *)database package:(NSString *)package;
@end
-@implementation SignatureView
+@implementation SignatureController
- (void) dealloc {
[package_ release];
[super webView:sender didClearWindowObject:window forFrame:frame];
}
-- (id) initWithBook:(RVBook *)book database:(Database *)database package:(NSString *)package {
- if ((self = [super initWithBook:book]) != nil) {
+- (id) initWithDatabase:(Database *)database package:(NSString *)package {
+ if ((self = [super init]) != nil) {
database_ = database;
package_ = [package retain];
[self reloadData];
} return self;
}
-- (void) resetViewAnimated:(BOOL)animated {
-}
-
- (void) reloadData {
[self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"signature" ofType:@"html"]]];
}
@end
/* }}} */
+/* Role Controller {{{ */
+@interface RoleController : CYViewController {
+ _transient Database *database_;
+ id roledelegate_;
+ UITableView *table_;
+ UISegmentedControl *segment_;
+ UIView *container_;
+}
+@end
+
+@implementation RoleController
+- (void) dealloc {
+ [table_ release];
+ [segment_ release];
+ [container_ release];
+
+ [super dealloc];
+}
+
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate {
+ if ((self = [super init])) {
+ database_ = database;
+ roledelegate_ = delegate;
+
+ [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")];
+
+ NSArray *items = [NSArray arrayWithObjects:
+ UCLocalize("USER"),
+ UCLocalize("HACKER"),
+ UCLocalize("DEVELOPER"),
+ nil];
+ segment_ = [[UISegmentedControl alloc] initWithItems:items];
+ container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)];
+ [container_ addSubview:segment_];
+
+ int index = -1;
+ if ([Role_ isEqualToString:@"User"]) index = 0;
+ if ([Role_ isEqualToString:@"Hacker"]) index = 1;
+ if ([Role_ isEqualToString:@"Developer"]) index = 2;
+ if (index != -1) {
+ [segment_ setSelectedSegmentIndex:index];
+ [self showDoneButton];
+ }
+
+ [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
+ [self resizeSegmentedControl];
+
+ table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
+ [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [table_ setDelegate:self];
+ [table_ setDataSource:self];
+ [[self view] addSubview:table_];
+ [table_ reloadData];
+ } return self;
+}
+
+- (void) resizeSegmentedControl {
+ CGFloat width = [[self view] frame].size.width;
+ [segment_ setFrame:CGRectMake(width / 32.0f, 0, width - (width / 32.0f * 2.0f), 44.0f)];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+
+ [self resizeSegmentedControl];
+}
+
+- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
+ [self resizeSegmentedControl];
+}
+
+- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+ [self resizeSegmentedControl];
+}
+
+- (void) save {
+ NSString *role = nil;
+
+ switch ([segment_ selectedSegmentIndex]) {
+ case 0: role = @"User"; break;
+ case 1: role = @"Hacker"; break;
+ case 2: role = @"Developer"; break;
+
+ _nodefault
+ }
+
+ if (![role isEqualToString:Role_]) {
+ Role_ = role;
+
+ Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ Role_, @"Role",
+ nil];
+
+ [Metadata_ setObject:Settings_ forKey:@"Settings"];
+
+ Changed_ = true;
+
+ [roledelegate_ updateData];
+ }
+}
+
+- (void) segmentChanged:(UISegmentedControl *)control {
+ [self showDoneButton];
+}
+
+- (void) doneButtonClicked {
+ [self save];
+ [[self navigationController] dismissModalViewControllerAnimated:YES];
+}
+
+- (void) showDoneButton {
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("DONE")
+ style:UIBarButtonItemStyleDone
+ target:self
+ action:@selector(doneButtonClicked)
+ ];
+ [[self navigationItem] setRightBarButtonItem:rightItem animated:[[self navigationItem] rightBarButtonItem] == nil];
+ [rightItem release];
+}
+
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
+ // XXX: For not having a single cell in the table, this sure is a lot of sections.
+ return 6;
+}
+
+- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return 0; // :(
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ return nil; // This method is required by the protocol.
+}
+
+- (NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
+ if (section == 1)
+ return UCLocalize("ROLE_EX");
+ if (section == 4)
+ return [NSString stringWithFormat:
+ @"%@: %@\n%@: %@\n%@: %@",
+ UCLocalize("USER"), UCLocalize("USER_EX"),
+ UCLocalize("HACKER"), UCLocalize("HACKER_EX"),
+ UCLocalize("DEVELOPER"), UCLocalize("DEVELOPER_EX")
+ ];
+ else return nil;
+}
+
+- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
+ if (section == 3) return 44.0f;
+ else return 0;
+}
+
+- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
+ if (section == 3) return container_;
+ else return nil;
+}
+
+@end
+/* }}} */
+
+/* Cydia Container {{{ */
+@interface CYContainer : UIViewController <ProgressDelegate> {
+ _transient Database *database_;
+ RefreshBar *refreshbar_;
+
+ bool dropped_;
+ bool updating_;
+ id updatedelegate_;
+ UIViewController *root_;
+}
+
+@end
+
+@implementation CYContainer
+
+// NOTE: UIWindow only sends the top controller these messages,
+// So we have to forward them on.
+
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [root_ viewDidAppear:animated];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [root_ viewWillAppear:animated];
+}
+
+- (void) viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+ [root_ viewDidDisappear:animated];
+}
+
+- (void) viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [root_ viewWillDisappear:animated];
+}
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
+ return YES; /* XXX: return YES; */
+}
+
+- (void) setRootController:(UIViewController *)controller {
+ root_ = controller;
+ [[self view] addSubview:[root_ view]];
+}
+
+- (void) setUpdate:(NSDate *)date {
+ [self beginUpdate];
+}
+
+- (void) beginUpdate {
+ [self dropBar:YES];
+ [refreshbar_ start];
+
+ updating_ = true;
+
+ [NSThread
+ detachNewThreadSelector:@selector(performUpdate)
+ toTarget:self
+ withObject:nil
+ ];
+}
+
+- (void) performUpdate { _pooled
+ Status status;
+ status.setDelegate(self);
+ [database_ updateWithStatus:status];
+
+ [self
+ performSelectorOnMainThread:@selector(completeUpdate)
+ withObject:nil
+ waitUntilDone:NO
+ ];
+}
+
+- (void) completeUpdate {
+ updating_ = false;
+
+ [self raiseBar:YES];
+ [refreshbar_ stop];
+ [updatedelegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
+}
+
+- (void) cancelUpdate {
+ [refreshbar_ cancel];
+ [self completeUpdate];
+}
+
+- (void) cancelPressed {
+ [self cancelUpdate];
+}
+
+- (BOOL) updating {
+ return updating_;
+}
+
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)title {
+ [refreshbar_ setPrompt:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), error]];
+}
+
+- (void) startProgress {
+}
+
+- (void) setProgressTitle:(NSString *)title {
+ [self
+ performSelectorOnMainThread:@selector(_setProgressTitle:)
+ withObject:title
+ waitUntilDone:YES
+ ];
+}
+
+- (bool) isCancelling:(size_t)received {
+ return !updating_;
+}
+
+- (void) setProgressPercent:(float)percent {
+ [self
+ performSelectorOnMainThread:@selector(_setProgressPercent:)
+ withObject:[NSNumber numberWithFloat:percent]
+ waitUntilDone:YES
+ ];
+}
+
+- (void) addProgressOutput:(NSString *)output {
+ [self
+ performSelectorOnMainThread:@selector(_addProgressOutput:)
+ withObject:output
+ waitUntilDone:YES
+ ];
+}
+
+- (void) _setProgressTitle:(NSString *)title {
+ [refreshbar_ setPrompt:title];
+}
+
+- (void) _setProgressPercent:(NSNumber *)percent {
+ [refreshbar_ setProgress:[percent floatValue]];
+}
+
+- (void) _addProgressOutput:(NSString *)output {
+}
+
+- (void) setUpdateDelegate:(id)delegate {
+ updatedelegate_ = delegate;
+}
+
+- (void) dropBar:(BOOL)animated {
+ if (dropped_) return;
+ dropped_ = true;
+
+ [[self view] addSubview:refreshbar_];
+
+ if (animated) [UIView beginAnimations:nil context:NULL];
+ CGRect barframe = [refreshbar_ frame];
+ CGRect viewframe = [[root_ view] frame];
+ viewframe.origin.y += barframe.size.height + 20.0f;
+ viewframe.size.height -= barframe.size.height + 20.0f;
+ [[root_ view] setFrame:viewframe];
+ if (animated) [UIView commitAnimations];
+
+ // Ensure bar has the proper width for our view, it might have changed
+ barframe.size.width = viewframe.size.width;
+ [refreshbar_ setFrame:barframe];
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) raiseBar:(BOOL)animated {
+ if (!dropped_) return;
+ dropped_ = false;
+
+ [refreshbar_ removeFromSuperview];
+
+ if (animated) [UIView beginAnimations:nil context:NULL];
+ CGRect barframe = [refreshbar_ frame];
+ CGRect viewframe = [[root_ view] frame];
+ viewframe.origin.y -= barframe.size.height + 20.0f;
+ viewframe.size.height += barframe.size.height + 20.0f;
+ [[root_ view] setFrame:viewframe];
+ if (animated) [UIView commitAnimations];
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+ if (dropped_) {
+ [self raiseBar:NO];
+ [self dropBar:NO];
+ }
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) dealloc {
+ [refreshbar_ release];
+ [super dealloc];
+}
+
+- (id) initWithDatabase: (Database *)database {
+ if ((self = [super init]) != nil) {
+ database_ = database;
+
+ [[self view] setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+
+ refreshbar_ = [[RefreshBar alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, [UINavigationBar defaultSize].height) delegate:self];
+ } return self;
+}
+
+@end
+/* }}} */
+
+typedef enum {
+ kCydiaTag = 0,
+ kSectionsTag = 1,
+ kChangesTag = 2,
+ kManageTag = 3,
+ kInstalledTag = 4,
+ kSourcesTag = 5,
+ kSearchTag = 6
+} CYTabTag;
@interface Cydia : UIApplication <
- ConfirmationViewDelegate,
- ProgressViewDelegate,
- SearchViewDelegate,
+ ConfirmationControllerDelegate,
+ ProgressControllerDelegate,
CydiaDelegate
> {
UIWindow *window_;
+ CYContainer *container_;
- UIView *underlay_;
- UIView *overlay_;
- CYBook *book_;
- UIToolbar *buttonbar_;
-
- RVBook *confirm_;
+ id tabbar_;
NSMutableArray *essential_;
NSMutableArray *broken_;
Database *database_;
- ProgressView *progress_;
- unsigned tag_;
+ int tag_;
UIKeyboard *keyboard_;
UIProgressHUD *hud_;
- SectionsView *sections_;
- ChangesView *changes_;
- ManageView *manage_;
- SearchView *search_;
+ SectionsController *sections_;
+ ChangesController *changes_;
+ ManageController *manage_;
+ SearchController *search_;
+ SourceTable *sources_;
+ InstalledController *installed_;
+ id queueDelegate_;
- PackageView *package_;
+#if RecyclePackageViews
+ NSMutableArray *details_;
+#endif
+
+ bool loaded_;
}
+- (UIViewController *) _pageForURL:(NSURL *)url withClass:(Class)_class;
+- (void) setPage:(UIViewController *)page;
+
@end
+static _finline void _setHomePage(Cydia *self) {
+ [self setPage:[self _pageForURL:[NSURL URLWithString:CydiaURL(@"")] withClass:[HomeController class]]];
+}
+
@implementation Cydia
+- (void) beginUpdate {
+ [container_ beginUpdate];
+}
+
+- (BOOL) updating {
+ return [container_ updating];
+}
+
+- (UIView *) rotatingContentViewForWindow:(UIWindow *)window {
+ return window_;
+}
+
- (void) _loaded {
if ([broken_ count] != 0) {
int count = [broken_ count];
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:(count == 1 ? CYLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:CYLocalize("HALFINSTALLED_PACKAGES"), count])
- buttons:[NSArray arrayWithObjects:
- CYLocalize("FORCIBLY_CLEAR"),
- CYLocalize("TEMPORARY_IGNORE"),
- nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:(count == 1 ? UCLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:UCLocalize("HALFINSTALLED_PACKAGES"), count])
+ message:UCLocalize("HALFINSTALLED_PACKAGE_EX")
delegate:self
- context:@"fixhalf"
+ cancelButtonTitle:UCLocalize("FORCIBLY_CLEAR")
+ otherButtonTitles:UCLocalize("TEMPORARY_IGNORE"), nil
] autorelease];
- [sheet setBodyText:CYLocalize("HALFINSTALLED_PACKAGE_EX")];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"fixhalf"];
+ [alert show];
} else if (!Ignored_ && [essential_ count] != 0) {
int count = [essential_ count];
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:(count == 1 ? CYLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:CYLocalize("ESSENTIAL_UPGRADES"), count])
- buttons:[NSArray arrayWithObjects:
- CYLocalize("UPGRADE_ESSENTIAL"),
- CYLocalize("COMPLETE_UPGRADE"),
- CYLocalize("TEMPORARY_IGNORE"),
- nil]
- defaultButtonIndex:0
+ UIAlertView *alert = [[[UIAlertView alloc]
+ initWithTitle:(count == 1 ? UCLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:UCLocalize("ESSENTIAL_UPGRADES"), count])
+ message:UCLocalize("ESSENTIAL_UPGRADE_EX")
delegate:self
- context:@"upgrade"
+ cancelButtonTitle:UCLocalize("TEMPORARY_IGNORE")
+ otherButtonTitles:UCLocalize("UPGRADE_ESSENTIAL"), UCLocalize("COMPLETE_UPGRADE"), nil
] autorelease];
- [sheet setBodyText:CYLocalize("ESSENTIAL_UPGRADE_EX")];
- [sheet popupAlertAnimated:YES];
+ [alert setContext:@"upgrade"];
+ [alert show];
}
}
+- (void) _saveConfig {
+ if (Changed_) {
+ _trace();
+ NSString *error(nil);
+ if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
+ _trace();
+ NSError *error(nil);
+ if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
+ NSLog(@"failure to save metadata data: %@", error);
+ _trace();
+ } else {
+ NSLog(@"failure to serialize metadata: %@", error);
+ return;
+ }
+
+ Changed_ = false;
+ }
+}
+
+- (void) _updateData {
+ [self _saveConfig];
+
+ /* XXX: this is just stupid */
+ if (tag_ != 1 && sections_ != nil)
+ [sections_ reloadData];
+ if (tag_ != 2 && changes_ != nil)
+ [changes_ reloadData];
+ if (tag_ != 4 && search_ != nil)
+ [search_ reloadData];
+
+ [[tabbar_ selectedViewController] reloadData];
+}
+
+- (int)indexOfTabWithTag:(int)tag {
+ int i = 0;
+ for (UINavigationController *controller in [tabbar_ viewControllers]) {
+ if ([[controller tabBarItem] tag] == tag) return i;
+ i += 1;
+ }
+
+ return -1;
+}
+
+- (void) _refreshIfPossible {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ Reachability* reachability = [Reachability reachabilityWithHostName:@"cydia.saurik.com"];
+ NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];
+
+ if (loaded_ || ManualRefresh || remoteHostStatus == NotReachable) loaded:
+ [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO];
+ else {
+ loaded_ = true;
+
+ NSDate *update([Metadata_ objectForKey:@"LastUpdate"]);
+
+ if (update != nil) {
+ NSTimeInterval interval([update timeIntervalSinceNow]);
+ if (interval <= 0 && interval > -(15*60))
+ goto loaded;
+ }
+
+ [container_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO];
+ }
+
+ [pool release];
+}
+
+- (void) refreshIfPossible {
+ [NSThread detachNewThreadSelector:@selector(_refreshIfPossible) toTarget:self withObject:nil];
+}
+
- (void) _reloadData {
UIView *block();
- static bool loaded(false);
UIProgressHUD *hud([self addProgressHUD]);
- [hud setText:(loaded ? CYLocalize("RELOADING_DATA") : CYLocalize("LOADING_DATA"))];
- loaded = true;
+ [hud setText:(loaded_ ? UCLocalize("RELOADING_DATA") : UCLocalize("LOADING_DATA"))];
[database_ yieldToSelector:@selector(reloadData) withObject:nil];
_trace();
[essential_ removeAllObjects];
[broken_ removeAllObjects];
- NSArray *packages = [database_ packages];
+ NSArray *packages([database_ packages]);
for (Package *package in packages) {
if ([package half])
[broken_ addObject:package];
if (changes != 0) {
NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
- [buttonbar_ setBadgeValue:badge forButton:3];
- if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
- [buttonbar_ setBadgeAnimated:([essential_ count] != 0) forButton:3];
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setBadgeValue:badge];
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setAnimatedBadge:YES];
+
if ([self respondsToSelector:@selector(setApplicationBadge:)])
[self setApplicationBadge:badge];
else
[self setApplicationBadgeString:badge];
} else {
- [buttonbar_ setBadgeValue:nil forButton:3];
- if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
- [buttonbar_ setBadgeAnimated:NO forButton:3];
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setBadgeValue:nil];
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setAnimatedBadge:NO];
+
if ([self respondsToSelector:@selector(removeApplicationBadge)])
[self removeApplicationBadge];
else // XXX: maybe use setApplicationBadgeString also?
[self setApplicationIconBadgeNumber:0];
}
- Queuing_ = false;
- [buttonbar_ setBadgeValue:nil forButton:4];
-
- [self updateData];
-
- // XXX: what is this line of code for?
- if ([packages count] == 0);
- else if (Loaded_ || ManualRefresh) loaded:
- [self _loaded];
- else {
- Loaded_ = YES;
-
- if (NSDate *update = [Metadata_ objectForKey:@"LastUpdate"]) {
- NSTimeInterval interval([update timeIntervalSinceNow]);
- if (interval <= 0 && interval > -600)
- goto loaded;
- }
+ [self _updateData];
- [book_ update];
- }
-}
-
-- (void) _saveConfig {
- if (Changed_) {
- _trace();
- NSString *error(nil);
- if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
- _trace();
- NSError *error(nil);
- if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
- NSLog(@"failure to save metadata data: %@", error);
- _trace();
- } else {
- NSLog(@"failure to serialize metadata: %@", error);
- return;
- }
-
- Changed_ = false;
- }
+ [self refreshIfPossible];
}
- (void) updateData {
- [self _saveConfig];
-
- /* XXX: this is just stupid */
- if (tag_ != 2 && sections_ != nil)
- [sections_ reloadData];
- if (tag_ != 3 && changes_ != nil)
- [changes_ reloadData];
- if (tag_ != 5 && search_ != nil)
- [search_ reloadData];
-
- [book_ reloadData];
+ [database_ setVisible];
+ [self _updateData];
}
- (void) update_ {
}
- (void) syncData {
- FILE *file = fopen("/etc/apt/sources.list.d/cydia.list", "w");
+ FILE *file(fopen("/etc/apt/sources.list.d/cydia.list", "w"));
_assert(file != NULL);
- NSArray *keys = [Sources_ allKeys];
-
- for (NSString *key in keys) {
- NSDictionary *source = [Sources_ objectForKey:key];
+ for (NSString *key in [Sources_ allKeys]) {
+ NSDictionary *source([Sources_ objectForKey:key]);
fprintf(file, "%s %s %s\n",
[[source objectForKey:@"Type"] UTF8String],
[self _saveConfig];
- [progress_
+ ProgressController *progress = [[[ProgressController alloc] initWithDatabase:database_ delegate:self] autorelease];
+ UINavigationController *navigation = [[[CYNavigationController alloc] initWithRootViewController:progress] autorelease];
+ if (IsWildcat_) [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
+ [container_ presentModalViewController:navigation animated:YES];
+
+ [progress
detachNewThreadSelector:@selector(update_)
toTarget:self
withObject:nil
- title:CYLocalize("UPDATING_SOURCES")
+ title:UCLocalize("UPDATING_SOURCES")
];
}
- (void) reloadData {
@synchronized (self) {
- if (confirm_ == nil)
- [self _reloadData];
+ [self _reloadData];
}
}
_error->Discard();
}
-- (void) popUpBook:(RVBook *)book {
- [underlay_ popSubview:book];
-}
-
- (CGRect) popUpBounds {
- return [underlay_ bounds];
+ return [[tabbar_ view] bounds];
}
-- (void) perform {
- [database_ prepare];
+- (bool) perform {
+ if (![database_ prepare])
+ return false;
- confirm_ = [[RVBook alloc] initWithFrame:[self popUpBounds]];
+ ConfirmationController *page([[[ConfirmationController alloc] initWithDatabase:database_] autorelease]);
+ [page setDelegate:self];
+ id confirm_ = [[CYNavigationController alloc] initWithRootViewController:page];
[confirm_ setDelegate:self];
- ConfirmationView *page([[[ConfirmationView alloc] initWithBook:confirm_ database:database_] autorelease]);
- [page setDelegate:self];
+ if (IsWildcat_) [confirm_ setModalPresentationStyle:UIModalPresentationFormSheet];
+ [container_ presentModalViewController:confirm_ animated:YES];
- [confirm_ setPage:page];
- [self popUpBook:confirm_];
+ return true;
}
- (void) queue {
}
}
-- (void) clearPackage:(Package *)package {
+- (void) clearPackage:(Package *)package {
+ @synchronized (self) {
+ [package clear];
+ [self resolve];
+ [self perform];
+ }
+}
+
+- (void) installPackages:(NSArray *)packages {
@synchronized (self) {
- [package clear];
+ for (Package *package in packages)
+ [package install];
[self resolve];
[self perform];
}
- (void) distUpgrade {
@synchronized (self) {
- [database_ upgrade];
+ if (![database_ upgrade])
+ return;
[self perform];
}
}
-- (void) cancel {
- [self slideUp:[[[UIActionSheet alloc]
- initWithTitle:nil
- buttons:[NSArray arrayWithObjects:CYLocalize("CONTINUE_QUEUING"), CYLocalize("CANCEL_CLEAR"), nil]
- defaultButtonIndex:1
- delegate:self
- context:@"cancel"
- ] autorelease]];
-}
-
- (void) complete {
@synchronized (self) {
[self _reloadData];
-
- if (confirm_ != nil) {
- [confirm_ release];
- confirm_ = nil;
- }
}
}
-- (void) confirm {
- [overlay_ removeFromSuperview];
- reload_ = true;
-
- [progress_
+- (void) confirmWithNavigationController:(UINavigationController *)navigation {
+ ProgressController *progress = [[[ProgressController alloc] initWithDatabase:database_ delegate:self] autorelease];
+
+ if (navigation != nil) {
+ [navigation pushViewController:progress animated:YES];
+ } else {
+ navigation = [[[CYNavigationController alloc] initWithRootViewController:progress] autorelease];
+ if (IsWildcat_) [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
+ [container_ presentModalViewController:navigation animated:YES];
+ }
+
+ [progress
detachNewThreadSelector:@selector(perform)
toTarget:database_
withObject:nil
- title:CYLocalize("RUNNING")
+ title:UCLocalize("RUNNING")
];
}
-- (void) bootstrap_ {
- [database_ update];
- [database_ upgrade];
- [database_ prepare];
- [database_ perform];
+- (void) progressControllerIsComplete:(ProgressController *)progress {
+ [self complete];
}
-/* XXX: replace and localize */
-- (void) bootstrap {
- [progress_
- detachNewThreadSelector:@selector(bootstrap_)
- toTarget:self
- withObject:nil
- title:@"Bootstrap Install"
- ];
-}
+- (void) setPage:(UIViewController *)page {
+ [page setDelegate:self];
-- (void) progressViewIsComplete:(ProgressView *)progress {
- if (confirm_ != nil) {
- [underlay_ addSubview:overlay_];
- [confirm_ popFromSuperviewAnimated:NO];
+ UINavigationController *navController = [tabbar_ selectedViewController];
+ [navController setViewControllers:[NSArray arrayWithObject:page] animated:NO];
+ for (UIViewController *page in [tabbar_ viewControllers]) {
+ if (page != navController) [page setViewControllers:nil];
}
+}
- [self complete];
+- (UIViewController *) _pageForURL:(NSURL *)url withClass:(Class)_class {
+ CYBrowserController *browser = [[[_class alloc] init] autorelease];
+ [browser loadURL:url];
+ return browser;
}
-- (void) setPage:(RVPage *)page {
- [page resetViewAnimated:NO];
- [page setDelegate:self];
- [book_ setPage:page];
+- (SectionsController *) sectionsController {
+ if (sections_ == nil)
+ sections_ = [[SectionsController alloc] initWithDatabase:database_];
+ return sections_;
}
-- (RVPage *) _pageForURL:(NSURL *)url withClass:(Class)_class {
- BrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease];
- [browser loadURL:url];
- return browser;
+- (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_;
}
-- (void) _setHomePage {
- [self setPage:[self _pageForURL:[NSURL URLWithString:@"http://cydia.saurik.com/"] withClass:[HomeView class]]];
+- (SearchController *) searchController {
+ if (search_ == nil)
+ search_ = [[SearchController alloc] initWithDatabase:database_];
+ return search_;
}
-- (SectionsView *) sectionsView {
- if (sections_ == nil)
- sections_ = [[SectionsView alloc] initWithBook:book_ database:database_];
- return sections_;
+- (SourceTable *) sourcesController {
+ if (sources_ == nil)
+ sources_ = [[SourceTable alloc] initWithDatabase:database_];
+ return sources_;
+}
+
+- (InstalledController *) installedController {
+ if (installed_ == nil) {
+ installed_ = [[InstalledController alloc] initWithDatabase:database_];
+ if (IsWildcat_) queueDelegate_ = installed_;
+ }
+ return installed_;
}
-- (void) buttonBarItemTapped:(id)sender {
- unsigned tag = [sender tag];
+- (void) tabBarController:(id)tabBarController didSelectViewController:(UIViewController *)viewController {
+ int tag = [[viewController tabBarItem] tag];
if (tag == tag_) {
- [book_ resetViewAnimated:YES];
+ [[tabbar_ selectedViewController] popToRootViewControllerAnimated:YES];
return;
- } else if (tag_ == 2 && tag != 2)
- [[self sectionsView] resetView];
+ } else if (tag_ == 1) {
+ [[self sectionsController] resetView];
+ }
switch (tag) {
- case 1: [self _setHomePage]; break;
+ case kCydiaTag: _setHomePage(self); break;
- case 2: [self setPage:[self sectionsView]]; break;
- case 3: [self setPage:changes_]; break;
- case 4: [self setPage:manage_]; break;
- case 5: [self setPage:search_]; break;
+ 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;
- default: _assert(false);
+ _nodefault
}
tag_ = tag;
}
-- (void) applicationWillSuspend {
- [database_ clean];
- [super applicationWillSuspend];
+- (void) showSettings {
+ RoleController *role = [[RoleController alloc] initWithDatabase:database_ delegate:self];
+ CYNavigationController *nav = [[CYNavigationController alloc] initWithRootViewController:role];
+ if (IsWildcat_) [nav setModalPresentationStyle:UIModalPresentationFormSheet];
+ [container_ presentModalViewController:nav animated:YES];
}
-- (void) askForSettings {
- NSString *parenthetical(CYLocalize("PARENTHETICAL"));
-
- UIActionSheet *role = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("WHO_ARE_YOU")
- buttons:[NSArray arrayWithObjects:
- [NSString stringWithFormat:parenthetical, CYLocalize("USER"), CYLocalize("USER_EX")],
- [NSString stringWithFormat:parenthetical, CYLocalize("HACKER"), CYLocalize("HACKER_EX")],
- [NSString stringWithFormat:parenthetical, CYLocalize("DEVELOPER"), CYLocalize("DEVELOPER_EX")],
- nil]
- defaultButtonIndex:-1
- delegate:self
- context:@"role"
- ] autorelease];
-
- [role setBodyText:CYLocalize("ROLE_EX")];
- [role popupAlertAnimated:YES];
+- (void) setPackageController:(PackageController *)view {
+ WebThreadLock();
+ [view setPackage:nil];
+#if RecyclePackageViews
+ if ([details_ count] < 3)
+ [details_ addObject:view];
+#endif
+ WebThreadUnlock();
}
-- (void) setPackageView:(PackageView *)view {
- if (package_ == nil)
- package_ = [view retain];
+- (PackageController *) _packageController {
+ return [[[PackageController alloc] initWithDatabase:database_] autorelease];
}
-- (PackageView *) packageView {
- PackageView *view;
+- (PackageController *) packageController {
+#if RecyclePackageViews
+ PackageController *view;
+ size_t count([details_ count]);
- if (package_ == nil)
- view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease];
- else {
- return package_;
- view = [package_ autorelease];
- package_ = nil;
+ if (count == 0) {
+ view = [self _packageController];
+ renew:
+ [details_ addObject:[self _packageController]];
+ } else {
+ view = [[[details_ lastObject] retain] autorelease];
+ [details_ removeLastObject];
+ if (count == 1)
+ goto renew;
}
return view;
+#else
+ return [self _packageController];
+#endif
}
-- (void) finish {
- if (hud_ != nil) {
- [self setStatusBarShowsProgress:NO];
- [self removeProgressHUD:hud_];
+- (void) cancelAndClear:(bool)clear {
+ @synchronized (self) {
+ if (clear) {
+ /* XXX: clear marks instead of reloading data */
+ /*pkgCacheFile &cache([database_ cache]);
+ for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
+ if (!cache[iterator].Keep()) cache->MarkKeep(iterator, false, false);
+ }
- [hud_ autorelease];
- hud_ = nil;
+ [self updateData];
+
+ Queuing_ = false;
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kManageTag] != -1 ? [self indexOfTabWithTag:kManageTag] : [self indexOfTabWithTag:kInstalledTag]] tabBarItem] setBadgeValue:nil];
+ [queueDelegate_ queueStatusDidChange];*/
+ [self reloadData];
+ } else {
+ Queuing_ = true;
- pid_t pid = ExecFork();
- if (pid == 0) {
- execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
- perror("launchctl stop");
+ [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kManageTag] != -1 ? [self indexOfTabWithTag:kManageTag] : [self indexOfTabWithTag:kInstalledTag]] tabBarItem] setBadgeValue:UCLocalize("Q_D")];
+ [[tabbar_ selectedViewController] reloadData];
+
+ [queueDelegate_ queueStatusDidChange];
}
-
- return;
}
-
- if (Role_ == nil) {
- [self askForSettings];
- return;
- }
-
- _trace();
- overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
-
- CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
- book_ = [[CYBook alloc] initWithFrame:CGRectMake(
- 0, 0, screenrect.size.width, screenrect.size.height - 48
- ) database:database_];
-
- [book_ setDelegate:self];
-
- [overlay_ addSubview:book_];
-
- NSArray *buttonitems = [NSArray arrayWithObjects:
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"buttonBarItemTapped:", kUIButtonBarButtonAction,
- @"home-up.png", kUIButtonBarButtonInfo,
- @"home-dn.png", kUIButtonBarButtonSelectedInfo,
- [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
- self, kUIButtonBarButtonTarget,
- @"Cydia", kUIButtonBarButtonTitle,
- @"0", kUIButtonBarButtonType,
- nil],
-
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"buttonBarItemTapped:", kUIButtonBarButtonAction,
- @"install-up.png", kUIButtonBarButtonInfo,
- @"install-dn.png", kUIButtonBarButtonSelectedInfo,
- [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
- self, kUIButtonBarButtonTarget,
- CYLocalize("SECTIONS"), kUIButtonBarButtonTitle,
- @"0", kUIButtonBarButtonType,
- nil],
-
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"buttonBarItemTapped:", kUIButtonBarButtonAction,
- @"changes-up.png", kUIButtonBarButtonInfo,
- @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
- [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
- self, kUIButtonBarButtonTarget,
- CYLocalize("CHANGES"), kUIButtonBarButtonTitle,
- @"0", kUIButtonBarButtonType,
- nil],
-
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"buttonBarItemTapped:", kUIButtonBarButtonAction,
- @"manage-up.png", kUIButtonBarButtonInfo,
- @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
- [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
- self, kUIButtonBarButtonTarget,
- CYLocalize("MANAGE"), kUIButtonBarButtonTitle,
- @"0", kUIButtonBarButtonType,
- nil],
-
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"buttonBarItemTapped:", kUIButtonBarButtonAction,
- @"search-up.png", kUIButtonBarButtonInfo,
- @"search-dn.png", kUIButtonBarButtonSelectedInfo,
- [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
- self, kUIButtonBarButtonTarget,
- CYLocalize("SEARCH"), kUIButtonBarButtonTitle,
- @"0", kUIButtonBarButtonType,
- nil],
- nil];
-
- buttonbar_ = [[UIToolbar alloc]
- initInView:overlay_
- withFrame:CGRectMake(
- 0, screenrect.size.height - ButtonBarHeight_,
- screenrect.size.width, ButtonBarHeight_
- )
- withItemList:buttonitems
- ];
-
- [buttonbar_ setDelegate:self];
- [buttonbar_ setBarStyle:1];
- [buttonbar_ setButtonBarTrackingMode:2];
-
- int buttons[5] = {1, 2, 3, 4, 5};
- [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
- [buttonbar_ showButtonGroup:0 withDuration:0];
-
- for (int i = 0; i != 5; ++i)
- [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
- i * 64 + 2, 1, 60, ButtonBarHeight_
- )];
-
- [buttonbar_ showSelectionForButton:1];
- [overlay_ addSubview:buttonbar_];
-
- [UIKeyboard initImplementationNow];
- CGSize keysize = [UIKeyboard defaultSize];
- CGRect keyrect = {{0, [overlay_ bounds].size.height}, keysize};
- keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
- //[[UIKeyboardImpl sharedInstance] setSoundsEnabled:(Sounds_Keyboard_ ? YES : NO)];
- [overlay_ addSubview:keyboard_];
-
- if (!bootstrap_)
- [underlay_ addSubview:overlay_];
-
- [self reloadData];
-
- [self sectionsView];
- changes_ = [[ChangesView alloc] initWithBook:book_ database:database_];
- search_ = [[SearchView alloc] initWithBook:book_ database:database_];
-
- manage_ = (ManageView *) [[self
- _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]
- withClass:[ManageView class]
- ] retain];
-
- [self setPackageView:[self packageView]];
-
- PrintTimes();
-
- if (bootstrap_)
- [self bootstrap];
- else
- [self _setHomePage];
}
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
-
- if ([context isEqualToString:@"missing"])
- [sheet dismiss];
- else if ([context isEqualToString:@"cancel"]) {
- bool clear;
+- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+ NSString *context([alert context]);
+
+ if ([context isEqualToString:@"fixhalf"]) {
+ if (button == [alert firstOtherButtonIndex]) {
+ @synchronized (self) {
+ for (Package *broken in broken_) {
+ [broken remove];
- switch (button) {
- case 1:
- clear = false;
- break;
-
- case 2:
- clear = true;
- break;
-
- default:
- _assert(false);
- }
-
- [sheet dismiss];
-
- @synchronized (self) {
- if (clear)
- [self _reloadData];
- else {
- Queuing_ = true;
- [buttonbar_ setBadgeValue:CYLocalize("Q_D") forButton:4];
- [book_ reloadData];
- }
-
- if (confirm_ != nil) {
- [confirm_ release];
- confirm_ = nil;
- }
- }
- } else if ([context isEqualToString:@"fixhalf"]) {
- switch (button) {
- case 1:
- @synchronized (self) {
- for (Package *broken in broken_) {
- [broken remove];
-
- NSString *id = [broken id];
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
- }
-
- [self resolve];
- [self perform];
+ NSString *id = [broken id];
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
}
- break;
-
- case 2:
- [broken_ removeAllObjects];
- [self _loaded];
- break;
-
- default:
- _assert(false);
- }
-
- [sheet dismiss];
- } else if ([context isEqualToString:@"role"]) {
- switch (button) {
- case 1: Role_ = @"User"; break;
- case 2: Role_ = @"Hacker"; break;
- case 3: Role_ = @"Developer"; break;
- default:
- Role_ = nil;
- _assert(false);
+ [self resolve];
+ [self perform];
+ }
+ } else if (button == [alert cancelButtonIndex]) {
+ [broken_ removeAllObjects];
+ [self _loaded];
}
- bool reset = Settings_ != nil;
-
- Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- Role_, @"Role",
- nil];
-
- [Metadata_ setObject:Settings_ forKey:@"Settings"];
-
- Changed_ = true;
-
- if (reset)
- [self updateData];
- else
- [self finish];
-
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
} else if ([context isEqualToString:@"upgrade"]) {
- switch (button) {
- case 1:
- @synchronized (self) {
- for (Package *essential in essential_)
- [essential install];
-
- [self resolve];
- [self perform];
- }
- break;
-
- case 2:
- [self distUpgrade];
- break;
-
- case 3:
- Ignored_ = YES;
- break;
+ if (button == [alert firstOtherButtonIndex]) {
+ @synchronized (self) {
+ for (Package *essential in essential_)
+ [essential install];
- default:
- _assert(false);
+ [self resolve];
+ [self perform];
+ }
+ } else if (button == [alert firstOtherButtonIndex] + 1) {
+ [self distUpgrade];
+ } else if (button == [alert cancelButtonIndex]) {
+ Ignored_ = YES;
}
- [sheet dismiss];
+ [alert dismissWithClickedButtonIndex:-1 animated:YES];
}
}
-- (void) reorganize { _pooled
- system("/usr/libexec/cydia/free.sh");
- [self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:NO];
+- (void) system:(NSString *)command { _pooled
+ system([command UTF8String]);
+}
+
+- (void) applicationWillSuspend {
+ [database_ clean];
+ [super applicationWillSuspend];
}
- (void) applicationSuspend:(__GSEvent *)event {
- if (hud_ == nil && ![progress_ isRunning])
+ // FIXME: This needs to be fixed, but we no longer have a progress_.
+ // What's the best solution?
+ if (hud_ == nil)// && ![progress_ isRunning])
[super applicationSuspend:event];
}
- (UIProgressHUD *) addProgressHUD {
UIProgressHUD *hud([[[UIProgressHUD alloc] initWithWindow:window_] autorelease]);
+ [hud setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+
[window_ setUserInteractionEnabled:NO];
[hud show:YES];
- [progress_ addSubview:hud];
+ [[container_ view] addSubview:hud];
return hud;
}
[window_ setUserInteractionEnabled:YES];
}
-- (void) openMailToURL:(NSURL *)url {
-// XXX: this makes me sad
-#if 0
- [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease];
-#else
- [UIApp openURL:url];// asPanel:YES];
-#endif
-}
-
-- (void) clearFirstResponder {
- if (id responder = [window_ firstResponder])
- [responder resignFirstResponder];
-}
-
-- (RVPage *) pageForPackage:(NSString *)name {
+- (UIViewController *) pageForPackage:(NSString *)name {
if (Package *package = [database_ packageWithName:name]) {
- PackageView *view([self packageView]);
+ PackageController *view([self packageController]);
[view setPackage:package];
return view;
} else {
- UIActionSheet *sheet = [[[UIActionSheet alloc]
- initWithTitle:CYLocalize("CANNOT_LOCATE_PACKAGE")
- buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil]
- defaultButtonIndex:0
- delegate:self
- context:@"missing"
- ] autorelease];
-
- [sheet setBodyText:[NSString stringWithFormat:CYLocalize("PACKAGE_CANNOT_BE_FOUND"), name]];
-
- [sheet popupAlertAnimated:YES];
- return nil;
+ 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]];
}
}
-- (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag {
+- (UIViewController *) pageForURL:(NSURL *)url hasTag:(int *)tag {
if (tag != NULL)
- tag = 0;
+ *tag = -1;
+
+ NSString *href([url absoluteString]);
+ if ([href hasPrefix:@"apptapp://package/"])
+ return [self pageForPackage:[href substringFromIndex:18]];
NSString *scheme([[url scheme] lowercaseString]);
if (![scheme isEqualToString:@"cydia"])
path = [@"/" stringByAppendingString:path];
if ([path isEqualToString:@"/add-source"])
- return [[[AddSourceView alloc] initWithBook:book_ database:database_] autorelease];
+ return [[[AddSourceController alloc] initWithDatabase:database_] autorelease];
else if ([path isEqualToString:@"/storage"])
- return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[BrowserView class]];
+ return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[CYBrowserController class]];
else if ([path isEqualToString:@"/sources"])
- return [[[SourceTable alloc] initWithBook:book_ database:database_] autorelease];
+ return [[[SourceTable alloc] initWithDatabase:database_] autorelease];
else if ([path isEqualToString:@"/packages"])
- return [[[InstalledView alloc] initWithBook:book_ database:database_] autorelease];
+ return [[[InstalledController alloc] initWithDatabase:database_] autorelease];
else if ([path hasPrefix:@"/url/"])
- return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[BrowserView class]];
+ 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 [[[SettingsView alloc] initWithBook:book_ database:database_ package:[path substringFromIndex:18]] autorelease];
+ return [[[SettingsController alloc] initWithDatabase:database_ package:[path substringFromIndex:18]] autorelease];
else if ([path hasPrefix:@"/package-signature/"])
- return [[[SignatureView alloc] initWithBook:book_ database:database_ package:[path substringFromIndex:19]] autorelease];
+ 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] initWithBook:book_ database:database_] autorelease];
+ FileTable *files = [[[FileTable alloc] initWithDatabase:database_] autorelease];
[files setPackage:package];
return files;
}
- (void) applicationOpenURL:(NSURL *)url {
[super applicationOpenURL:url];
int tag;
- if (RVPage *page = [self pageForURL:url hasTag:&tag]) {
+ if (UIViewController *page = [self pageForURL:url hasTag:&tag]) {
[self setPage:page];
- [buttonbar_ showSelectionForButton:tag];
tag_ = tag;
+ [tabbar_ setSelectedViewController:(tag_ == -1 ? nil : [[tabbar_ viewControllers] objectAtIndex:tag_])];
}
}
+- (void) applicationWillResignActive:(UIApplication *)application {
+ // Stop refreshing if you get a phone call or lock the device.
+ if ([container_ updating]) [container_ cancelUpdate];
+}
+
- (void) applicationDidFinishLaunching:(id)unused {
- _trace();
+ [CYBrowserController _initialize];
+
+ [NSURLProtocol registerClass:[CydiaURLProtocol class]];
+
Font12_ = [[UIFont systemFontOfSize:12] retain];
Font12Bold_ = [[UIFont boldSystemFontOfSize:12] retain];
Font14_ = [[UIFont systemFontOfSize:14] retain];
Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
- tag_ = 1;
+ tag_ = 0;
essential_ = [[NSMutableArray alloc] initWithCapacity:4];
broken_ = [[NSMutableArray alloc] initWithCapacity:4];
- [NSURLProtocol registerClass:[CydiaURLProtocol class]];
-
- CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
- window_ = [[UIWindow alloc] initWithContentRect:screenrect];
+ UIScreen *screen([UIScreen mainScreen]);
+ window_ = [[UIWindow alloc] initWithFrame:[screen bounds]];
[window_ orderFront:self];
[window_ makeKey:self];
[window_ setHidden:NO];
database_ = [Database sharedInstance];
- progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] database:database_ delegate:self];
- [database_ setDelegate:progress_];
- [window_ setContentView:progress_];
-
- underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
- [progress_ setContentView:underlay_];
-
- [progress_ resetView];
if (
readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL ||
readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL ||
+ //readlink("/usr/bin", NULL, 0) == -1 && errno == EINVAL ||
readlink("/usr/include", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/usr/lib/pam", NULL, 0) == -1 && errno == EINVAL ||
readlink("/usr/libexec", NULL, 0) == -1 && errno == EINVAL ||
- readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL /*||
- readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/
+ readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL ||
+ //readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL ||
+ false
) {
[self setIdleTimerDisabled:YES];
- hud_ = [[self addProgressHUD] retain];
- [hud_ setText:@"Reorganizing\n\nWill Automatically\nClose When Done"];
-
+ hud_ = [self addProgressHUD];
+ [hud_ setText:@"Reorganizing:\n\nWill Automatically\nClose When Done"];
[self setStatusBarShowsProgress:YES];
- [NSThread
- detachNewThreadSelector:@selector(reorganize)
- toTarget:self
- withObject:nil
- ];
- } else
- [self finish];
-}
+ [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
-- (void) showKeyboard:(BOOL)show {
- CGSize keysize = [UIKeyboard defaultSize];
- CGRect keydown = {{0, [overlay_ bounds].size.height}, keysize};
- CGRect keyup = keydown;
- keyup.origin.y -= keysize.height;
+ [self setStatusBarShowsProgress:NO];
+ [self removeProgressHUD:hud_];
+ hud_ = nil;
- UIFrameAnimation *animation = [[[UIFrameAnimation alloc] initWithTarget:keyboard_] autorelease];
- [animation setSignificantRectFields:2];
+ if (ExecFork() == 0) {
+ execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
+ perror("launchctl stop");
+ }
- if (show) {
- [animation setStartFrame:keydown];
- [animation setEndFrame:keyup];
- [keyboard_ activate];
- } else {
- [animation setStartFrame:keyup];
- [animation setEndFrame:keydown];
- [keyboard_ deactivate];
+ return;
}
- [[UIAnimator sharedAnimator]
- addAnimations:[NSArray arrayWithObjects:animation, nil]
- withDuration:KeyboardTime_
- start:YES
+ if (Role_ == nil)
+ [self showSettings];
+
+ _trace();
+
+ NSMutableArray *controllers = [NSMutableArray array];
+ [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+ [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+ [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+ if (IsWildcat_) [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+ [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+ [controllers addObject:[[CYNavigationController alloc] initWithDatabase:database_]];
+
+ 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],
+ 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];
+ } else {
+ [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:kManageTag] autorelease] atIndex:3];
+ }
+
+ for (int i = 0; i < [items count]; i++) {
+ [[controllers objectAtIndex:i] setTabBarItem:[items objectAtIndex:i]];
+ }
-- (void) slideUp:(UIActionSheet *)alert {
- if (Advanced_)
- [alert presentSheetFromButtonBar:buttonbar_];
- else
- [alert presentSheetInView:overlay_];
-}
+ tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_];
+ [tabbar_ setViewControllers:controllers];
+ [tabbar_ setDelegate:self];
+ [tabbar_ setSelectedIndex:0];
-@end
+ container_ = [[CYContainer alloc] initWithDatabase:database_];
+ [container_ setUpdateDelegate:self];
+ [container_ setRootController:tabbar_];
+ [window_ addSubview:[container_ view]];
+ [[tabbar_ view] setFrame:CGRectMake(0, -20.0f, [window_ bounds].size.width, [window_ bounds].size.height)];
-void AddPreferences(NSString *plist) { _pooled
- NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
- _assert(settings != NULL);
- NSMutableArray *items = [settings objectForKey:@"items"];
+ [UIKeyboard initImplementationNow];
- bool cydia(false);
+ [self reloadData];
- for (NSMutableDictionary *item in items) {
- NSString *label = [item objectForKey:@"label"];
- if (label != nil && [label isEqualToString:@"Cydia"]) {
- cydia = true;
- break;
- }
- }
+#if RecyclePackageViews
+ details_ = [[NSMutableArray alloc] initWithCapacity:4];
+ [details_ addObject:[self _packageController]];
+ [details_ addObject:[self _packageController]];
+#endif
- if (!cydia) {
- for (size_t i(0); i != [items count]; ++i) {
- NSDictionary *item([items objectAtIndex:i]);
- NSString *label = [item objectForKey:@"label"];
- if (label != nil && [label isEqualToString:@"General"]) {
- [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
- @"CydiaSettings", @"bundle",
- @"PSLinkCell", @"cell",
- [NSNumber numberWithBool:YES], @"hasIcon",
- [NSNumber numberWithBool:YES], @"isController",
- @"Cydia", @"label",
- nil] atIndex:(i + 1)];
+ PrintTimes();
- break;
- }
- }
+ _setHomePage(self);
+}
- _assert([settings writeToFile:plist atomically:YES] == YES);
+- (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
+ if (item != nil && IsWildcat_) {
+ [sheet showFromBarButtonItem:item animated:YES];
+ } else {
+ [sheet showInView:window_];
}
}
+@end
+
/*IMP alloc_;
id Alloc_(id self, SEL selector) {
id object = alloc_(self, selector);
Class $WebDefaultUIKitDelegate;
-void (*_UIWebDocumentView$_setUIKitDelegate$)(UIWebDocumentView *, SEL, id);
-
-void $UIWebDocumentView$_setUIKitDelegate$(UIWebDocumentView *self, SEL sel, id delegate) {
+MSHook(void, UIWebDocumentView$_setUIKitDelegate$, UIWebDocumentView *self, SEL _cmd, id delegate) {
if (delegate == nil && $WebDefaultUIKitDelegate != nil)
delegate = [$WebDefaultUIKitDelegate sharedUIKitDelegate];
- return _UIWebDocumentView$_setUIKitDelegate$(self, sel, delegate);
+ return _UIWebDocumentView$_setUIKitDelegate$(self, _cmd, delegate);
+}
+
+static NSNumber *shouldPlayKeyboardSounds;
+
+Class $UIHardware;
+
+MSHook(void, UIHardware$_playSystemSound$, Class self, SEL _cmd, int soundIndex) {
+ switch (soundIndex) {
+ case 1104: // Keyboard Button Clicked
+ case 1105: // Keyboard Delete Repeated
+ if (!shouldPlayKeyboardSounds) {
+ NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.preferences.sounds.plist"];
+ shouldPlayKeyboardSounds = [[dict objectForKey:@"keyboard"] ?: (id)kCFBooleanTrue retain];
+ [dict release];
+ }
+ if (![shouldPlayKeyboardSounds boolValue])
+ break;
+ default:
+ _UIHardware$_playSystemSound$(self, _cmd, soundIndex);
+ }
}
int main(int argc, char *argv[]) { _pooled
_trace();
+ if (Class $UIDevice = objc_getClass("UIDevice")) {
+ UIDevice *device([$UIDevice currentDevice]);
+ IsWildcat_ = [device respondsToSelector:@selector(isWildcat)] && [device isWildcat];
+ } else
+ IsWildcat_ = false;
+
PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
/* Library Hacks {{{ */
+ class_addMethod(objc_getClass("WebScriptObject"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &WebScriptObject$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
$WebDefaultUIKitDelegate = objc_getClass("WebDefaultUIKitDelegate");
_UIWebDocumentView$_setUIKitDelegate$ = reinterpret_cast<void (*)(UIWebDocumentView *, SEL, id)>(method_getImplementation(UIWebDocumentView$_setUIKitDelegate$));
method_setImplementation(UIWebDocumentView$_setUIKitDelegate$, reinterpret_cast<IMP>(&$UIWebDocumentView$_setUIKitDelegate$));
}
+
+ $UIHardware = objc_getClass("UIHardware");
+ Method UIHardware$_playSystemSound$(class_getClassMethod($UIHardware, @selector(_playSystemSound:)));
+ if (UIHardware$_playSystemSound$ != NULL) {
+ _UIHardware$_playSystemSound$ = reinterpret_cast<void (*)(Class, SEL, int)>(method_getImplementation(UIHardware$_playSystemSound$));
+ method_setImplementation(UIHardware$_playSystemSound$, reinterpret_cast<IMP>(&$UIHardware$_playSystemSound$));
+ }
/* }}} */
/* Set Locale {{{ */
Locale_ = CFLocaleCopyCurrent();
Languages_ = [NSLocale preferredLanguages];
//CFStringRef locale(CFLocaleGetIdentifier(Locale_));
//NSLog(@"%@", [Languages_ description]);
+
const char *lang;
if (Languages_ == nil || [Languages_ count] == 0)
+ // XXX: consider just setting to C and then falling through?
lang = NULL;
- else
+ else {
lang = [[Languages_ objectAtIndex:0] UTF8String];
- setenv("LANG", lang, true);
+ setenv("LANG", lang, true);
+ }
+
//std::setlocale(LC_ALL, lang);
NSLog(@"Setting Language: %s", lang);
/* }}} */
- // XXX: apr_app_initialize?
- apr_initialize();
+ apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);
/* Parse Arguments {{{ */
bool substrate(false);
}
for (int argi(1); argi != arge; ++argi)
- if (strcmp(args[argi], "--bootstrap") == 0)
- bootstrap_ = true;
- else if (strcmp(args[argi], "--substrate") == 0)
+ if (strcmp(args[argi], "--substrate") == 0)
substrate = true;
else
fprintf(stderr, "unknown argument: %s\n", args[argi]);
}
/* }}} */
- {
- NSString *plist = [Home_ stringByAppendingString:@"/Library/Preferences/com.apple.preferences.sounds.plist"];
- if (NSDictionary *sounds = [NSDictionary dictionaryWithContentsOfFile:plist])
- if (NSNumber *keyboard = [sounds objectForKey:@"keyboard"])
- Sounds_Keyboard_ = [keyboard boolValue];
- }
-
App_ = [[NSBundle mainBundle] bundlePath];
Home_ = NSHomeDirectory();
+ Advanced_ = YES;
setuid(0);
setgid(0);
dealloc_ = dealloc->method_imp;
dealloc->method_imp = (IMP) &Dealloc_;*/
+ /* System Information {{{ */
size_t size;
int maxproc;
perror("sysctlbyname(\"kern.maxproc\", #)");
}
+ sysctlbyname("kern.osversion", NULL, &size, NULL, 0);
+ char *osversion = new char[size];
+ if (sysctlbyname("kern.osversion", osversion, &size, NULL, 0) == -1)
+ perror("sysctlbyname(\"kern.osversion\", ?)");
+ else
+ System_ = [NSString stringWithUTF8String:osversion];
+
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = new char[size];
if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1)
else
Machine_ = machine;
+ if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice")) {
+ if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
+ if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
+ SerialNumber_ = [NSString stringWithString:(NSString *)serial];
+ CFRelease(serial);
+ }
+
+ if (CFTypeRef ecid = IORegistryEntrySearchCFProperty(service, kIODeviceTreePlane, CFSTR("unique-chip-id"), kCFAllocatorDefault, kIORegistryIterateRecursively)) {
+ NSData *data((NSData *) ecid);
+ size_t length([data length]);
+ uint8_t bytes[length];
+ [data getBytes:bytes];
+ char string[length * 2 + 1];
+ for (size_t i(0); i != length; ++i)
+ sprintf(string + i * 2, "%.2X", bytes[length - i - 1]);
+ ChipID_ = [NSString stringWithUTF8String:string];
+ CFRelease(ecid);
+ }
+
+ IOObjectRelease(service);
+ }
+ }
+
UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier];
if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"])
Product_ = [info objectForKey:@"SafariProductVersion"];
Safari_ = [info objectForKey:@"CFBundleVersion"];
}
-
- /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
- AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
-
+ /* }}} */
/* Load Database {{{ */
_trace();
Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease];
Packages_ = [Metadata_ objectForKey:@"Packages"];
Sections_ = [Metadata_ objectForKey:@"Sections"];
Sources_ = [Metadata_ objectForKey:@"Sources"];
+
+ Token_ = [Metadata_ objectForKey:@"Token"];
}
if (Settings_ != nil)
Documents_ = [[[NSMutableArray alloc] initWithCapacity:4] autorelease];
#endif
+ Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
+
+ if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", F_OK) == 0)
+ dlopen("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", RTLD_LAZY | RTLD_GLOBAL);
if (substrate && access("/Applications/WinterBoard.app/WinterBoard.dylib", F_OK) == 0)
dlopen("/Applications/WinterBoard.app/WinterBoard.dylib", RTLD_LAZY | RTLD_GLOBAL);
/*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/
- if (access("/User", F_OK) != 0) {
+ int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
+
+ if (access("/tmp/.cydia.fw", F_OK) == 0) {
+ unlink("/tmp/.cydia.fw");
+ goto firmware;
+ } else if (access("/User", F_OK) != 0 || version < 2) {
+ firmware:
_trace();
system("/usr/libexec/cydia/firmware.sh");
_trace();
_assert(errno == ENOENT);
}
+ /* APT Initialization {{{ */
_assert(pkgInitConfig(*_config));
_assert(pkgInitSystem(*_config, _system));
if (lang != NULL)
_config->Set("APT::Acquire::Translation", lang);
_config->Set("Acquire::http::Timeout", 15);
- _config->Set("Acquire::http::MaxParallel", 4);
-
+ _config->Set("Acquire::http::MaxParallel", 3);
+ /* }}} */
/* Color Choices {{{ */
space_ = CGColorSpaceCreateDeviceRGB();
Green_.Set(space_, 0.0, 0.5, 0.0, 1.0);
Purple_.Set(space_, 0.0, 0.0, 0.7, 1.0);
Purplish_.Set(space_, 0.4, 0.4, 0.8, 1.0);
- /*Purple_.Set(space_, 1.0, 0.3, 0.0, 1.0);
- Purplish_.Set(space_, 1.0, 0.6, 0.4, 1.0); ORANGE */
- /*Purple_.Set(space_, 1.0, 0.5, 0.0, 1.0);
- Purplish_.Set(space_, 1.0, 0.7, 0.2, 1.0); ORANGISH */
- /*Purple_.Set(space_, 0.5, 0.0, 0.7, 1.0);
- Purplish_.Set(space_, 0.7, 0.4, 0.8, 1.0); PURPLE */
-
-//.93
+
InstallingColor_ = [UIColor colorWithRed:0.88f green:1.00f blue:0.88f alpha:1.00f];
RemovingColor_ = [UIColor colorWithRed:1.00f green:0.88f blue:0.88f alpha:1.00f];
/* }}}*/
-
- Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
-
/* UIKit Configuration {{{ */
void (*$GSFontSetUseLegacyFontMetrics)(BOOL)(reinterpret_cast<void (*)(BOOL)>(dlsym(RTLD_DEFAULT, "GSFontSetUseLegacyFontMetrics")));
if ($GSFontSetUseLegacyFontMetrics != NULL)
$GSFontSetUseLegacyFontMetrics(YES);
- UIKeyboardDisableAutomaticAppearance();
+ // XXX: I have a feeling this was important
+ //UIKeyboardDisableAutomaticAppearance();
/* }}} */
+ Colon_ = UCLocalize("COLON_DELIMITED");
+ Error_ = UCLocalize("ERROR");
+ Warning_ = UCLocalize("WARNING");
+
_trace();
int value = UIApplicationMain(argc, argv, @"Cydia", @"Cydia");
CFRelease(Locale_);
return value;
-}
+}
\ No newline at end of file