2022-09-02 23:19:48 +08:00
# import "TSAppTableViewController.h"
# import "TSApplicationsManager.h"
2022-09-12 15:06:07 +08:00
@ interface UIImage ( )
+ ( UIImage * ) _applicationIconImageForBundleIdentifier : ( NSString * ) id format : ( NSInteger ) format scale : ( double ) scale ;
@ end
2022-09-02 23:19:48 +08:00
@ implementation TSAppTableViewController
2022-09-13 01:23:09 +08:00
- ( void ) loadCachedAppPaths
{
_cachedAppPaths = [ [ TSApplicationsManager sharedInstance ] installedAppPaths ] ;
}
- ( instancetype ) init
{
self = [ super init ] ;
if ( self )
{
[ self loadCachedAppPaths ] ;
_placeholderIcon = [ UIImage _applicationIconImageForBundleIdentifier : @ "com.apple.WebSheet" format : 10 scale : [ UIScreen mainScreen ] . scale ] ;
2022-09-13 02:52:04 +08:00
_cachedIcons = [ NSMutableDictionary new ] ;
2022-09-13 01:23:09 +08:00
}
return self ;
}
2022-09-02 23:19:48 +08:00
- ( void ) reloadTable
{
2022-09-13 01:23:09 +08:00
[ self loadCachedAppPaths ] ;
dispatch_async ( dispatch_get _main _queue ( ) , ^
{
[ self . tableView reloadData ] ;
} ) ;
2022-09-02 23:19:48 +08:00
}
- ( void ) loadView
{
2022-09-13 01:23:09 +08:00
[ super loadView ] ;
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( reloadTable )
name : @ "ApplicationsChanged"
object : nil ] ;
2022-09-02 23:19:48 +08:00
}
- ( void ) viewDidLoad {
2022-09-13 01:23:09 +08:00
[ super viewDidLoad ] ;
self . tableView . allowsMultipleSelectionDuringEditing = NO ;
2022-09-02 23:19:48 +08:00
}
2022-09-10 02:22:34 +08:00
- ( void ) showError : ( NSError * ) error
{
2022-09-13 01:23:09 +08:00
UIAlertController * errorAlert = [ UIAlertController alertControllerWithTitle : [ NSString stringWithFormat : @ "Error %ld" , error . code ] message : error . localizedDescription preferredStyle : UIAlertControllerStyleAlert ] ;
UIAlertAction * closeAction = [ UIAlertAction actionWithTitle : @ "Close" style : UIAlertActionStyleDefault handler : nil ] ;
[ errorAlert addAction : closeAction ] ;
[ self presentViewController : errorAlert animated : YES completion : nil ] ;
2022-09-10 02:22:34 +08:00
}
2022-09-12 22:10:50 +08:00
- ( void ) openAppPressedForRowAtIndexPath : ( NSIndexPath * ) indexPath
{
2022-09-13 01:23:09 +08:00
TSApplicationsManager * appsManager = [ TSApplicationsManager sharedInstance ] ;
2022-09-12 22:10:50 +08:00
2022-09-13 01:23:09 +08:00
NSString * appPath = _cachedAppPaths [ indexPath . row ] ;
NSString * appId = [ appsManager appIdForAppPath : appPath ] ;
BOOL didOpen = [ appsManager openApplicationWithBundleID : appId ] ;
2022-09-12 22:10:50 +08:00
2022-09-13 01:23:09 +08:00
// if we failed to open the app , show an alert
if ( ! didOpen ) {
NSString * failMessage = [ NSString stringWithFormat : @ "Failed to open %@" , appId ] ;
UIAlertController * didFailController = [ UIAlertController alertControllerWithTitle : failMessage message : nil preferredStyle : UIAlertControllerStyleAlert ] ;
UIAlertAction * cancelAction = [ UIAlertAction actionWithTitle : @ "Cancel" style : UIAlertActionStyleCancel handler : nil ] ;
2022-09-12 22:10:50 +08:00
2022-09-13 01:23:09 +08:00
[ didFailController addAction : cancelAction ] ;
[ self presentViewController : didFailController animated : YES completion : nil ] ;
}
2022-09-12 22:10:50 +08:00
}
2022-09-10 02:22:34 +08:00
- ( void ) uninstallPressedForRowAtIndexPath : ( NSIndexPath * ) indexPath
{
2022-09-13 01:23:09 +08:00
TSApplicationsManager * appsManager = [ TSApplicationsManager sharedInstance ] ;
NSString * appPath = _cachedAppPaths [ indexPath . row ] ;
NSString * appId = [ appsManager appIdForAppPath : appPath ] ;
NSString * appName = [ appsManager displayNameForAppPath : appPath ] ;
UIAlertController * confirmAlert = [ UIAlertController alertControllerWithTitle : @ "Confirm Uninstallation" message : [ NSString stringWithFormat : @ "Uninstalling the app '%@' will delete the app and all data associated to it." , appName ] preferredStyle : UIAlertControllerStyleAlert ] ;
UIAlertAction * uninstallAction = [ UIAlertAction actionWithTitle : @ "Uninstall" style : UIAlertActionStyleDestructive handler : ^ ( UIAlertAction * action )
{
if ( appId )
{
[ appsManager uninstallApp : appId ] ;
}
else
{
[ appsManager uninstallAppByPath : appPath ] ;
}
} ] ;
[ confirmAlert addAction : uninstallAction ] ;
UIAlertAction * cancelAction = [ UIAlertAction actionWithTitle : @ "Cancel" style : UIAlertActionStyleCancel handler : nil ] ;
[ confirmAlert addAction : cancelAction ] ;
[ self presentViewController : confirmAlert animated : YES completion : nil ] ;
2022-09-10 02:22:34 +08:00
}
- ( void ) deselectRow
{
2022-09-13 01:23:09 +08:00
[ self . tableView deselectRowAtIndexPath : [ self . tableView indexPathForSelectedRow ] animated : YES ] ;
2022-09-10 02:22:34 +08:00
}
2022-09-02 23:19:48 +08:00
# pragma mark - Table view data source
- ( NSInteger ) numberOfSectionsInTableView : ( UITableView * ) tableView {
2022-09-13 01:23:09 +08:00
return 1 ;
2022-09-02 23:19:48 +08:00
}
- ( NSInteger ) tableView : ( UITableView * ) tableView numberOfRowsInSection : ( NSInteger ) section {
2022-09-13 01:23:09 +08:00
return _cachedAppPaths . count ;
2022-09-02 23:19:48 +08:00
}
- ( UITableViewCell * ) tableView : ( UITableView * ) tableView cellForRowAtIndexPath : ( NSIndexPath * ) indexPath {
2022-09-13 01:23:09 +08:00
UITableViewCell * cell = [ tableView dequeueReusableCellWithIdentifier : @ "ApplicationCell" ] ;
if ( ! cell ) {
cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleSubtitle reuseIdentifier : @ "ApplicationCell" ] ;
}
NSString * appPath = _cachedAppPaths [ indexPath . row ] ;
NSString * appId = [ [ TSApplicationsManager sharedInstance ] appIdForAppPath : appPath ] ;
NSString * appVersion = [ [ TSApplicationsManager sharedInstance ] versionStringForAppPath : appPath ] ;
// Configure the cell . . .
cell . textLabel . text = [ [ TSApplicationsManager sharedInstance ] displayNameForAppPath : appPath ] ;
cell . detailTextLabel . text = [ NSString stringWithFormat : @ "%@ • %@" , appVersion , appId ] ;
cell . imageView . layer . borderWidth = 0.2 ;
cell . imageView . layer . borderColor = [ UIColor blackColor ] . CGColor ;
cell . imageView . layer . cornerRadius = 13.8 ;
2022-09-13 02:52:04 +08:00
UIImage * cachedIcon = _cachedIcons [ appId ] ;
if ( cachedIcon )
2022-09-13 01:23:09 +08:00
{
2022-09-13 02:52:04 +08:00
cell . imageView . image = cachedIcon ;
}
else
{
cell . imageView . image = _placeholderIcon ;
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^
{
// usleep ( 1000 * 5000 ) ; // ( test delay for debugging )
UIImage * iconImage = [ UIImage _applicationIconImageForBundleIdentifier : appId format : 10 scale : [ UIScreen mainScreen ] . scale ] ;
_cachedIcons [ appId ] = iconImage ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
if ( [ tableView . indexPathsForVisibleRows containsObject : indexPath ] )
{
cell . imageView . image = iconImage ;
}
} ) ;
2022-09-13 01:23:09 +08:00
} ) ;
2022-09-13 02:52:04 +08:00
}
2022-09-13 01:23:09 +08:00
cell . preservesSuperviewLayoutMargins = NO ;
cell . separatorInset = UIEdgeInsetsZero ;
cell . layoutMargins = UIEdgeInsetsZero ;
return cell ;
2022-09-02 23:19:48 +08:00
}
2022-09-12 15:06:07 +08:00
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForRowAtIndexPath : ( NSIndexPath * ) indexPath {
2022-09-13 01:23:09 +08:00
return 80.0 f ;
2022-09-12 15:06:07 +08:00
}
2022-09-02 23:19:48 +08:00
- ( void ) tableView : ( UITableView * ) tableView commitEditingStyle : ( UITableViewCellEditingStyle ) editingStyle forRowAtIndexPath : ( NSIndexPath * ) indexPath
{
2022-09-13 01:23:09 +08:00
if ( editingStyle = = UITableViewCellEditingStyleDelete )
{
[ self uninstallPressedForRowAtIndexPath : indexPath ] ;
}
2022-09-10 02:22:34 +08:00
}
- ( void ) tableView : ( UITableView * ) tableView didSelectRowAtIndexPath : ( NSIndexPath * ) indexPath
{
2022-09-13 01:23:09 +08:00
TSApplicationsManager * appsManager = [ TSApplicationsManager sharedInstance ] ;
NSString * appPath = _cachedAppPaths [ indexPath . row ] ;
NSString * appId = [ appsManager appIdForAppPath : appPath ] ;
NSString * appName = [ appsManager displayNameForAppPath : appPath ] ;
UIAlertController * appSelectAlert = [ UIAlertController alertControllerWithTitle : appName message : appId preferredStyle : UIAlertControllerStyleActionSheet ] ;
/ * UIAlertAction * detachAction = [ UIAlertAction actionWithTitle : @ "Detach from TrollStore" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action )
{
int detachRet = [ appsManager detachFromApp : appId ] ;
if ( detachRet ! = 0 )
{
[ self showError : [ appsManager errorForCode : detachRet ] ] ;
}
[ self deselectRow ] ;
} ] ;
[ appSelectAlert addAction : detachAction ] ; * /
UIAlertAction * openAction = [ UIAlertAction actionWithTitle : @ "Open" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action )
{
[ self openAppPressedForRowAtIndexPath : indexPath ] ;
[ self deselectRow ] ;
} ] ;
[ appSelectAlert addAction : openAction ] ;
UIAlertAction * uninstallAction = [ UIAlertAction actionWithTitle : @ "Uninstall App" style : UIAlertActionStyleDestructive handler : ^ ( UIAlertAction * action )
{
[ self uninstallPressedForRowAtIndexPath : indexPath ] ;
[ self deselectRow ] ;
} ] ;
[ appSelectAlert addAction : uninstallAction ] ;
UIAlertAction * cancelAction = [ UIAlertAction actionWithTitle : @ "Cancel" style : UIAlertActionStyleCancel handler : ^ ( UIAlertAction * action )
{
[ self deselectRow ] ;
} ] ;
[ appSelectAlert addAction : cancelAction ] ;
2022-09-10 02:22:34 +08:00
appSelectAlert . popoverPresentationController . sourceView = tableView ;
appSelectAlert . popoverPresentationController . sourceRect = [ tableView rectForRowAtIndexPath : indexPath ] ;
2022-09-13 01:23:09 +08:00
[ self presentViewController : appSelectAlert animated : YES completion : nil ] ;
2022-09-02 23:19:48 +08:00
}
@ end