Path: blob/main/Natives/LauncherProfilesViewController.m
589 views
#import "LauncherMenuViewController.h"1#import "LauncherNavigationController.h"2#import "LauncherPreferences.h"3#import "LauncherPrefGameDirViewController.h"4#import "LauncherPrefManageJREViewController.h"5#import "LauncherProfileEditorViewController.h"6#import "LauncherProfilesViewController.h"7//#import "NSFileManager+NRFileManager.h"8#import "PLProfiles.h"9#import "UIKit+AFNetworking.h"10#import "UIKit+hook.h"11#import "installer/FabricInstallViewController.h"12#import "installer/ForgeInstallViewController.h"13#import "installer/ModpackInstallViewController.h"14#import "ios_uikit_bridge.h"15#import "utils.h"1617typedef NS_ENUM(NSUInteger, LauncherProfilesTableSection) {18kInstances,19kProfiles20};2122@interface LauncherProfilesViewController () //<UIContextMenuInteractionDelegate>2324@property(nonatomic) UIBarButtonItem *createButtonItem;25@end2627@implementation LauncherProfilesViewController2829- (id)init {30self = [super init];31self.title = localize(@"Profiles", nil);32return self;33}3435- (NSString *)imageName {36return @"MenuProfiles";37}3839- (void)viewDidLoad40{41[super viewDidLoad];4243UIMenu *createMenu = [UIMenu menuWithTitle:localize(@"profile.title.create", nil) image:nil identifier:nil44options:UIMenuOptionsDisplayInline45children:@[46[UIAction47actionWithTitle:@"Vanilla" image:nil48identifier:@"vanilla" handler:^(UIAction *action) {49[self actionEditProfile:@{50@"name": @"",51@"lastVersionId": @"latest-release"}];52}],53#if 0 // TODO54[UIAction55actionWithTitle:@"OptiFine" image:nil56identifier:@"optifine" handler:createHandler],57#endif58[UIAction59actionWithTitle:@"Fabric/Quilt" image:nil60identifier:@"fabric_or_quilt" handler:^(UIAction *action) {61[self actionCreateFabricProfile];62}],63[UIAction64actionWithTitle:@"Forge" image:nil65identifier:@"forge" handler:^(UIAction *action) {66[self actionCreateForgeProfile];67}],68[UIAction69actionWithTitle:@"Modpack" image:nil70identifier:@"modpack" handler:^(UIAction *action) {71[self actionCreateModpackProfile];72}]73]];74self.createButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd menu:createMenu];7576self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped];77self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;78}7980- (void)viewWillAppear:(BOOL)animated {81[super viewWillAppear:animated];8283// Put navigation buttons back in place84self.navigationItem.rightBarButtonItems = @[[sidebarViewController drawAccountButton], self.createButtonItem];8586// Pickup changes made in the profile editor and switching instance87[PLProfiles updateCurrent];88[self.tableView reloadData];89[self.navigationController performSelector:@selector(reloadProfileList)];90}9192- (void)actionTogglePrefIsolation:(UISwitch *)sender {93if (!sender.isOn) {94setPrefBool(@"internal.isolated", NO);95}96toggleIsolatedPref(sender.isOn);97}9899- (void)actionCreateFabricProfile {100FabricInstallViewController *vc = [FabricInstallViewController new];101[self presentNavigatedViewController:vc];102}103104- (void)actionCreateForgeProfile {105ForgeInstallViewController *vc = [ForgeInstallViewController new];106[self presentNavigatedViewController:vc];107}108109- (void)actionCreateModpackProfile {110ModpackInstallViewController *vc = [ModpackInstallViewController new];111[self presentNavigatedViewController:vc];112}113114- (void)actionEditProfile:(NSDictionary *)profile {115LauncherProfileEditorViewController *vc = [LauncherProfileEditorViewController new];116vc.profile = profile.mutableCopy;117[self presentNavigatedViewController:vc];118}119120- (void)presentNavigatedViewController:(UIViewController *)vc {121UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];122//nav.navigationBar.prefersLargeTitles = YES;123[self presentViewController:nav animated:YES completion:nil];124}125126#pragma mark Table view127128- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {129return 2;130}131132- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {133switch (section) {134case 0: return localize(@"profile.section.instance", nil);135case 1: return localize(@"profile.section.profiles", nil);136}137return nil;138}139140- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {141switch (section) {142case 0: return 2;143case 1: return [PLProfiles.current.profiles count];144}145return 0;146}147148- (void)setupInstanceCell:(UITableViewCell *) cell atRow:(NSInteger)row {149cell.userInteractionEnabled = !getenv("DEMO_LOCK");150if (row == 0) {151cell.imageView.image = [UIImage systemImageNamed:@"folder"];152cell.textLabel.text = localize(@"preference.title.game_directory", nil);153cell.detailTextLabel.text = getenv("DEMO_LOCK") ? @".demo" : getPrefObject(@"general.game_directory");154} else {155NSString *imageName;156if (@available(iOS 15.0, *)) {157imageName = @"folder.badge.gearshape";158} else {159imageName = @"folder.badge.gear";160}161cell.imageView.image = [UIImage systemImageNamed:imageName];162cell.textLabel.text = localize(@"profile.title.separate_preference", nil);163cell.detailTextLabel.text = localize(@"profile.detail.separate_preference", nil);164UISwitch *view = [UISwitch new];165[view setOn:getPrefBool(@"internal.isolated") animated:NO];166[view addTarget:self action:@selector(actionTogglePrefIsolation:) forControlEvents:UIControlEventValueChanged];167cell.accessoryView = view;168}169}170171- (void)setupProfileCell:(UITableViewCell *) cell atRow:(NSInteger)row {172NSMutableDictionary *profile = PLProfiles.current.profiles.allValues[row];173174cell.textLabel.text = profile[@"name"];175cell.detailTextLabel.text = profile[@"lastVersionId"];176cell.imageView.layer.magnificationFilter = kCAFilterNearest;177178UIImage *fallbackImage = [[UIImage imageNamed:@"DefaultProfile"] _imageWithSize:CGSizeMake(40, 40)];179[cell.imageView setImageWithURL:[NSURL URLWithString:profile[@"icon"]] placeholderImage:fallbackImage];180}181182- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath183{184NSString *cellID = indexPath.section == kInstances ? @"InstanceCell" : @"ProfileCell";185UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];186if (cell == nil) {187cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];188cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;189cell.detailTextLabel.numberOfLines = 0;190cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;191if (indexPath.section == kProfiles) {192cell.imageView.frame = CGRectMake(0, 0, 40, 40);193cell.imageView.isSizeFixed = YES;194}195} else {196cell.imageView.image = nil;197cell.userInteractionEnabled = YES;198cell.accessoryView = nil;199}200201if (indexPath.section == kInstances) {202[self setupInstanceCell:cell atRow:indexPath.row];203} else {204[self setupProfileCell:cell atRow:indexPath.row];205}206207cell.textLabel.enabled = cell.detailTextLabel.enabled = cell.userInteractionEnabled;208return cell;209}210211- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {212[tableView deselectRowAtIndexPath:indexPath animated:NO];213214if (indexPath.section == kInstances) {215if (indexPath.row == 0) {216[self.navigationController pushViewController:[LauncherPrefGameDirViewController new] animated:YES];217}218return;219}220221[self actionEditProfile:PLProfiles.current.profiles.allValues[indexPath.row]];222}223224#pragma mark Context Menu configuration225226- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath227{228if (editingStyle != UITableViewCellEditingStyleDelete) return;229230UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];231NSString *title = localize(@"preference.title.confirm", nil);232// reusing the delete runtime message233NSString *message = [NSString stringWithFormat:localize(@"preference.title.confirm.delete_runtime", nil), cell.textLabel.text];234UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];235confirmAlert.popoverPresentationController.sourceView = cell;236confirmAlert.popoverPresentationController.sourceRect = cell.bounds;237UIAlertAction *ok = [UIAlertAction actionWithTitle:localize(@"OK", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {238[PLProfiles.current.profiles removeObjectForKey:cell.textLabel.text];239if ([PLProfiles.current.selectedProfileName isEqualToString:cell.textLabel.text]) {240// The one being deleted is the selected one, switch to the random one now241PLProfiles.current.selectedProfileName = PLProfiles.current.profiles.allKeys[0];242[self.navigationController performSelector:@selector(reloadProfileList)];243} else {244[PLProfiles.current save];245}246[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];247}];248UIAlertAction *cancel = [UIAlertAction actionWithTitle:localize(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];249[confirmAlert addAction:cancel];250[confirmAlert addAction:ok];251[self presentViewController:confirmAlert animated:YES completion:nil];252}253254- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath255{256if (indexPath.section == kInstances || PLProfiles.current.profiles.count==1) {257return UITableViewCellEditingStyleNone;258}259return UITableViewCellEditingStyleDelete;260}261262@end263264265