267 lines
10 KiB
Objective-C
267 lines
10 KiB
Objective-C
#import "LauncherMenuViewController.h"
|
|
#import "LauncherNavigationController.h"
|
|
#import "LauncherPreferences.h"
|
|
#import "LauncherPrefGameDirViewController.h"
|
|
#import "LauncherPrefManageJREViewController.h"
|
|
#import "LauncherProfileEditorViewController.h"
|
|
#import "LauncherProfilesViewController.h"
|
|
//#import "NSFileManager+NRFileManager.h"
|
|
#import "PLProfiles.h"
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
|
#import "UIKit+AFNetworking.h"
|
|
#pragma clang diagnostic pop
|
|
#import "UIKit+hook.h"
|
|
#import "installer/FabricInstallViewController.h"
|
|
#import "installer/ForgeInstallViewController.h"
|
|
#import "installer/ModpackInstallViewController.h"
|
|
#import "ios_uikit_bridge.h"
|
|
#import "utils.h"
|
|
|
|
typedef NS_ENUM(NSUInteger, LauncherProfilesTableSection) {
|
|
kInstances,
|
|
kProfiles
|
|
};
|
|
|
|
@interface LauncherProfilesViewController () //<UIContextMenuInteractionDelegate>
|
|
|
|
@property(nonatomic) UIBarButtonItem *createButtonItem;
|
|
@end
|
|
|
|
@implementation LauncherProfilesViewController
|
|
|
|
- (id)init {
|
|
self = [super init];
|
|
self.title = localize(@"Profiles", nil);
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)imageName {
|
|
return @"MenuProfiles";
|
|
}
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
|
|
UIMenu *createMenu = [UIMenu menuWithTitle:localize(@"profile.title.create", nil) image:nil identifier:nil
|
|
options:UIMenuOptionsDisplayInline
|
|
children:@[
|
|
[UIAction
|
|
actionWithTitle:@"Vanilla" image:nil
|
|
identifier:@"vanilla" handler:^(UIAction *action) {
|
|
[self actionEditProfile:@{
|
|
@"name": @"",
|
|
@"lastVersionId": @"latest-release"}];
|
|
}],
|
|
#if 0 // TODO
|
|
[UIAction
|
|
actionWithTitle:@"OptiFine" image:nil
|
|
identifier:@"optifine" handler:createHandler],
|
|
#endif
|
|
[UIAction
|
|
actionWithTitle:@"Fabric/Quilt" image:nil
|
|
identifier:@"fabric_or_quilt" handler:^(UIAction *action) {
|
|
[self actionCreateFabricProfile];
|
|
}],
|
|
[UIAction
|
|
actionWithTitle:@"Forge" image:nil
|
|
identifier:@"forge" handler:^(UIAction *action) {
|
|
[self actionCreateForgeProfile];
|
|
}],
|
|
[UIAction
|
|
actionWithTitle:@"Modpack" image:nil
|
|
identifier:@"modpack" handler:^(UIAction *action) {
|
|
[self actionCreateModpackProfile];
|
|
}]
|
|
]];
|
|
self.createButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd menu:createMenu];
|
|
|
|
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped];
|
|
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
|
|
}
|
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
|
[super viewWillAppear:animated];
|
|
|
|
// Put navigation buttons back in place
|
|
self.navigationItem.rightBarButtonItems = @[[sidebarViewController drawAccountButton], self.createButtonItem];
|
|
|
|
// Pickup changes made in the profile editor and switching instance
|
|
[PLProfiles updateCurrent];
|
|
[self.tableView reloadData];
|
|
[self.navigationController performSelector:@selector(reloadProfileList)];
|
|
}
|
|
|
|
- (void)actionTogglePrefIsolation:(UISwitch *)sender {
|
|
if (!sender.isOn) {
|
|
setPrefBool(@"internal.isolated", NO);
|
|
}
|
|
toggleIsolatedPref(sender.isOn);
|
|
}
|
|
|
|
- (void)actionCreateFabricProfile {
|
|
FabricInstallViewController *vc = [FabricInstallViewController new];
|
|
[self presentNavigatedViewController:vc];
|
|
}
|
|
|
|
- (void)actionCreateForgeProfile {
|
|
ForgeInstallViewController *vc = [ForgeInstallViewController new];
|
|
[self presentNavigatedViewController:vc];
|
|
}
|
|
|
|
- (void)actionCreateModpackProfile {
|
|
ModpackInstallViewController *vc = [ModpackInstallViewController new];
|
|
[self presentNavigatedViewController:vc];
|
|
}
|
|
|
|
- (void)actionEditProfile:(NSDictionary *)profile {
|
|
LauncherProfileEditorViewController *vc = [LauncherProfileEditorViewController new];
|
|
vc.profile = profile.mutableCopy;
|
|
[self presentNavigatedViewController:vc];
|
|
}
|
|
|
|
- (void)presentNavigatedViewController:(UIViewController *)vc {
|
|
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
|
|
//nav.navigationBar.prefersLargeTitles = YES;
|
|
[self presentViewController:nav animated:YES completion:nil];
|
|
}
|
|
|
|
#pragma mark Table view
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
|
return 2;
|
|
}
|
|
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
|
switch (section) {
|
|
case 0: return localize(@"profile.section.instance", nil);
|
|
case 1: return localize(@"profile.section.profiles", nil);
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
|
switch (section) {
|
|
case 0: return 2;
|
|
case 1: return [PLProfiles.current.profiles count];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- (void)setupInstanceCell:(UITableViewCell *) cell atRow:(NSInteger)row {
|
|
cell.userInteractionEnabled = !getenv("DEMO_LOCK");
|
|
if (row == 0) {
|
|
cell.imageView.image = [UIImage systemImageNamed:@"folder"];
|
|
cell.textLabel.text = localize(@"preference.title.game_directory", nil);
|
|
cell.detailTextLabel.text = getenv("DEMO_LOCK") ? @".demo" : getPrefObject(@"general.game_directory");
|
|
} else {
|
|
NSString *imageName;
|
|
if (@available(iOS 15.0, *)) {
|
|
imageName = @"folder.badge.gearshape";
|
|
} else {
|
|
imageName = @"folder.badge.gear";
|
|
}
|
|
cell.imageView.image = [UIImage systemImageNamed:imageName];
|
|
cell.textLabel.text = localize(@"profile.title.separate_preference", nil);
|
|
cell.detailTextLabel.text = localize(@"profile.detail.separate_preference", nil);
|
|
UISwitch *view = [UISwitch new];
|
|
[view setOn:getPrefBool(@"internal.isolated") animated:NO];
|
|
[view addTarget:self action:@selector(actionTogglePrefIsolation:) forControlEvents:UIControlEventValueChanged];
|
|
cell.accessoryView = view;
|
|
}
|
|
}
|
|
|
|
- (void)setupProfileCell:(UITableViewCell *) cell atRow:(NSInteger)row {
|
|
NSMutableDictionary *profile = PLProfiles.current.profiles.allValues[row];
|
|
|
|
cell.textLabel.text = profile[@"name"];
|
|
cell.detailTextLabel.text = profile[@"lastVersionId"];
|
|
cell.imageView.layer.magnificationFilter = kCAFilterNearest;
|
|
|
|
UIImage *fallbackImage = [[UIImage imageNamed:@"DefaultProfile"] _imageWithSize:CGSizeMake(40, 40)];
|
|
[cell.imageView setImageWithURL:[NSURL URLWithString:profile[@"icon"]] placeholderImage:fallbackImage];
|
|
}
|
|
|
|
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
NSString *cellID = indexPath.section == kInstances ? @"InstanceCell" : @"ProfileCell";
|
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
|
|
if (cell == nil) {
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
cell.detailTextLabel.numberOfLines = 0;
|
|
cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
if (indexPath.section == kProfiles) {
|
|
cell.imageView.frame = CGRectMake(0, 0, 40, 40);
|
|
cell.imageView.isSizeFixed = YES;
|
|
}
|
|
} else {
|
|
cell.imageView.image = nil;
|
|
cell.userInteractionEnabled = YES;
|
|
cell.accessoryView = nil;
|
|
}
|
|
|
|
if (indexPath.section == kInstances) {
|
|
[self setupInstanceCell:cell atRow:indexPath.row];
|
|
} else {
|
|
[self setupProfileCell:cell atRow:indexPath.row];
|
|
}
|
|
|
|
cell.textLabel.enabled = cell.detailTextLabel.enabled = cell.userInteractionEnabled;
|
|
return cell;
|
|
}
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
|
|
|
if (indexPath.section == kInstances) {
|
|
if (indexPath.row == 0) {
|
|
[self.navigationController pushViewController:[LauncherPrefGameDirViewController new] animated:YES];
|
|
}
|
|
return;
|
|
}
|
|
|
|
[self actionEditProfile:PLProfiles.current.profiles.allValues[indexPath.row]];
|
|
}
|
|
|
|
#pragma mark Context Menu configuration
|
|
|
|
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
if (editingStyle != UITableViewCellEditingStyleDelete) return;
|
|
|
|
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
|
|
NSString *title = localize(@"preference.title.confirm", nil);
|
|
// reusing the delete runtime message
|
|
NSString *message = [NSString stringWithFormat:localize(@"preference.title.confirm.delete_runtime", nil), cell.textLabel.text];
|
|
UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];
|
|
confirmAlert.popoverPresentationController.sourceView = cell;
|
|
confirmAlert.popoverPresentationController.sourceRect = cell.bounds;
|
|
UIAlertAction *ok = [UIAlertAction actionWithTitle:localize(@"OK", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
|
|
[PLProfiles.current.profiles removeObjectForKey:cell.textLabel.text];
|
|
if ([PLProfiles.current.selectedProfileName isEqualToString:cell.textLabel.text]) {
|
|
// The one being deleted is the selected one, switch to the random one now
|
|
PLProfiles.current.selectedProfileName = PLProfiles.current.profiles.allKeys[0];
|
|
[self.navigationController performSelector:@selector(reloadProfileList)];
|
|
} else {
|
|
[PLProfiles.current save];
|
|
}
|
|
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
}];
|
|
UIAlertAction *cancel = [UIAlertAction actionWithTitle:localize(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
|
|
[confirmAlert addAction:cancel];
|
|
[confirmAlert addAction:ok];
|
|
[self presentViewController:confirmAlert animated:YES completion:nil];
|
|
}
|
|
|
|
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
if (indexPath.section == kInstances || PLProfiles.current.profiles.count==1) {
|
|
return UITableViewCellEditingStyleNone;
|
|
}
|
|
return UITableViewCellEditingStyleDelete;
|
|
}
|
|
|
|
@end
|