Path: blob/main/Natives/LauncherProfileEditorViewController.m
589 views
#import "LauncherNavigationController.h"1#import "LauncherPreferences.h"2#import "LauncherProfileEditorViewController.h"3#import "MinecraftResourceUtils.h"4#import "PickTextField.h"5#import "PLProfiles.h"6#import "ios_uikit_bridge.h"7#import "utils.h"89@interface LauncherProfileEditorViewController()<UIPickerViewDataSource, UIPickerViewDelegate>10@property(nonatomic) NSString* oldName;1112@property(nonatomic) NSArray<NSDictionary *> *versionList;13@property(nonatomic) UITextField* versionTextField;14@property(nonatomic) UISegmentedControl* versionTypeControl;15@property(nonatomic) UIPickerView* versionPickerView;16@property(nonatomic) UIToolbar* versionPickerToolbar;17@property(nonatomic) int versionSelectedAt;18@end1920@implementation LauncherProfileEditorViewController2122- (void)viewDidLoad {23// Setup navigation bar & appearance24self.title = localize(@"Edit profile", nil);25self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionDone)];26self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemClose target:self action:@selector(actionClose)];27self.navigationController.modalInPresentation = YES;28self.prefSectionsVisible = YES;2930// Setup preference getter and setter31__weak LauncherProfileEditorViewController *weakSelf = self;32self.getPreference = ^id(NSString *section, NSString *key){33NSString *value = weakSelf.profile[key];34if (value.length > 0 || ![weakSelf isPickFieldAtSection:section key:key]) {35return value;36} else {37return @"(default)";38}39};40self.setPreference = ^(NSString *section, NSString *key, NSString *value){41if ([value isEqualToString:@"(default)"] && [weakSelf isPickFieldAtSection:section key:key]) {42[weakSelf.profile removeObjectForKey:key];43} else if (value) {44weakSelf.profile[key] = value;45}46};4748// Obtain all the lists49self.oldName = self.getPreference(nil, @"name");50if ([self.oldName length] == 0) {51self.setPreference(nil, @"name", @"New Profile");52}53NSArray *rendererKeys = getRendererKeys(YES);54NSArray *rendererList = getRendererNames(YES);55NSArray *touchControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")]];56NSArray *gamepadControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap/gamepads", getenv("POJAV_HOME")]];57NSMutableArray *javaList = [getPrefObject(@"java.java_homes") allKeys].mutableCopy;58[javaList sortUsingSelector:@selector(compare:)];59javaList[0] = @"(default)";6061// Setup version picker62[self setupVersionPicker];63id typeVersionPicker = ^void(UITableViewCell *cell, NSString *section, NSString *key, NSDictionary *item){64self.typeTextField(cell, section, key, item);65UITextField *textField = (id)cell.accessoryView;66weakSelf.versionTextField = textField;67textField.inputAccessoryView = weakSelf.versionPickerToolbar;68textField.inputView = weakSelf.versionPickerView;69// Auto pick version type70if (self.versionList) return;71if ([MinecraftResourceUtils findVersion:textField.text inList:localVersionList]) {72self.versionTypeControl.selectedSegmentIndex = 0;73} else {74NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:textField.text inList:remoteVersionList];75if (selected) {76NSArray *types = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"];77NSString *type = selected[@"type"];78self.versionTypeControl.selectedSegmentIndex = [types indexOfObject:type];79} else {80// Version not found81self.versionTypeControl.selectedSegmentIndex = 0;82}83}84self.versionSelectedAt = -1;85[self changeVersionType:nil];86};8788self.prefContents = @[89@[90// General settings91@{@"key": @"name",92@"icon": @"tag",93@"title": @"preference.profile.title.name",94@"type": self.typeTextField,95@"placeholder": self.oldName96},97@{@"key": @"lastVersionId",98@"icon": @"archivebox",99@"title": @"preference.profile.title.version",100@"type": typeVersionPicker,101@"placeholder": self.getPreference(nil, @"lastVersionId"),102@"customClass": PickTextField.class103},104@{@"key": @"gameDir",105@"icon": @"folder",106@"title": @"preference.title.game_directory",107@"type": self.typeTextField,108@"placeholder": [NSString stringWithFormat:@". -> /Documents/instances/%@", getPrefObject(@"general.game_directory")]109},110// Video and renderer settings111@{@"key": @"renderer",112@"icon": @"cpu",113@"type": self.typePickField,114@"pickKeys": rendererKeys,115@"pickList": rendererList116},117// Control settings118@{@"key": @"defaultTouchCtrl",119@"icon": @"hand.tap",120@"title": @"preference.profile.title.default_touch_control",121@"type": self.typePickField,122@"pickKeys": touchControlList,123@"pickList": touchControlList124},125@{@"key": @"defaultGamepadCtrl",126@"icon": @"gamecontroller",127@"title": @"preference.profile.title.default_gamepad_control",128@"type": self.typePickField,129@"pickKeys": gamepadControlList,130@"pickList": gamepadControlList131},132// Java tweaks133@{@"key": @"javaVersion",134@"icon": @"cube",135@"title": @"preference.manage_runtime.header.default",136@"type": self.typePickField,137@"pickKeys": javaList,138@"pickList": javaList139},140@{@"key": @"javaArgs",141@"icon": @"slider.vertical.3",142@"title": @"preference.title.java_args",143@"type": self.typeTextField,144@"placeholder": @"(default)"145}146]147];148149[super viewDidLoad];150}151152- (void)actionClose {153[self.navigationController dismissViewControllerAnimated:YES completion:nil];154}155156- (void)actionDone {157// We might be saving without ending editing, so make sure textFieldDidEndEditing is always called158UITextField *currentTextField = [self performSelector:@selector(_firstResponder)];159if ([currentTextField isKindOfClass:UITextField.class] && [currentTextField isDescendantOfView:self.tableView]) {160[self textFieldDidEndEditing:currentTextField];161}162163if ([self.profile[@"name"] length] == 0 && self.oldName.length > 0) {164// Return to its old name165self.profile[@"name"] = self.oldName;166}167168if ([self.oldName isEqualToString:self.profile[@"name"]]) {169// Not a rename, directly create/replace170PLProfiles.current.profiles[self.oldName] = self.profile;171} else if (!PLProfiles.current.profiles[self.profile[@"name"]]) {172// A rename, remove then re-add to update its key name173if (self.oldName.length > 0) {174[PLProfiles.current.profiles removeObjectForKey:self.oldName];175}176PLProfiles.current.profiles[self.profile[@"name"]] = self.profile;177// Update selected name178if ([PLProfiles.current.selectedProfileName isEqualToString:self.oldName]) {179PLProfiles.current.selectedProfileName = self.profile[@"name"];180}181} else {182// Cancel rename since a profile with the same name already exists183showDialog(localize(@"Error", nil), localize(@"profile.error.name_exists", nil));184// Skip dismissing this view controller185return;186}187188[PLProfiles.current save];189[self actionClose];190191// Call LauncherProfilesViewController's viewWillAppear192UINavigationController *navVC = (id) ((UISplitViewController *)self.presentingViewController).viewControllers[1];193[navVC.viewControllers[0] viewWillAppear:NO];194}195196- (BOOL)isPickFieldAtSection:(NSString *)section key:(NSString *)key {197NSDictionary *pref = [self.prefContents[0] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(key == %@)", key]].firstObject;198return pref[@"type"] == self.typePickField;199}200201- (NSArray *)listFilesAtPath:(NSString *)path {202NSMutableArray *files = [NSFileManager.defaultManager contentsOfDirectoryAtPath:path error:nil].mutableCopy;203for (int i = 0; i < files.count;) {204if ([files[i] hasSuffix:@".json"]) {205i++;206} else {207[files removeObjectAtIndex:i];208}209}210[files insertObject:@"(default)" atIndex:0];211return files;212}213214#pragma mark Version picker215216- (void)setupVersionPicker {217self.versionPickerView = [[UIPickerView alloc] init];218self.versionPickerView.delegate = self;219self.versionPickerView.dataSource = self;220self.versionPickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)];221self.versionTypeControl = [[UISegmentedControl alloc] initWithItems:@[222localize(@"Installed", nil),223localize(@"Releases", nil),224localize(@"Snapshot", nil),225localize(@"Old-beta", nil),226localize(@"Old-alpha", nil)227]];228[self.versionTypeControl addTarget:self action:@selector(changeVersionType:) forControlEvents:UIControlEventValueChanged];229self.versionPickerToolbar.items = @[230[[UIBarButtonItem alloc] initWithCustomView:self.versionTypeControl],231[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],232[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(versionClosePicker)]233];234}235236- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {237if (self.versionList.count == 0) {238self.versionTextField.text = @"";239return;240}241self.versionSelectedAt = row;242self.versionTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component];243}244245- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {246return 1;247}248249- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {250return self.versionList.count;251}252253- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {254if (self.versionList.count <= row) return nil;255NSObject *object = self.versionList[row];256if ([object isKindOfClass:[NSString class]]) {257return (NSString*) object;258} else {259return [object valueForKey:@"id"];260}261}262263- (void)versionClosePicker {264[self.versionTextField endEditing:YES];265[self pickerView:self.versionPickerView didSelectRow:[self.versionPickerView selectedRowInComponent:0] inComponent:0];266}267268- (void)changeVersionType:(UISegmentedControl *)sender {269NSArray *newVersionList = self.versionList;270if (sender || !self.versionList) {271if (self.versionTypeControl.selectedSegmentIndex == 0) {272// installed273newVersionList = localVersionList;274} else {275NSString *type = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"][self.versionTypeControl.selectedSegmentIndex];276newVersionList = [remoteVersionList filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(type == %@)", type]];277}278}279280if (self.versionSelectedAt == -1) {281NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:self.versionTextField.text inList:newVersionList];282self.versionSelectedAt = [newVersionList indexOfObject:selected];283} else {284// Find the most matching version for this type285NSObject *lastSelected = nil;286if (self.versionList.count > self.versionSelectedAt) {287lastSelected = self.versionList[self.versionSelectedAt];288}289if (lastSelected != nil) {290NSObject *nearest = [MinecraftResourceUtils findNearestVersion:lastSelected expectedType:self.versionTypeControl.selectedSegmentIndex];291if (nearest != nil) {292self.versionSelectedAt = [newVersionList indexOfObject:(id)nearest];293}294}295lastSelected = nil;296// Get back the currently selected in case none matching version found297self.versionSelectedAt = MIN(abs(self.versionSelectedAt), newVersionList.count - 1);298}299300self.versionList = newVersionList;301[self.versionPickerView reloadAllComponents];302if (self.versionSelectedAt != -1) {303[self.versionPickerView selectRow:self.versionSelectedAt inComponent:0 animated:NO];304[self pickerView:self.versionPickerView didSelectRow:self.versionSelectedAt inComponent:0];305}306}307308@end309310311