Files
PojavLauncher_iOS/Natives/LauncherProfileEditorViewController.m
T

306 lines
13 KiB
Objective-C

#import "LauncherNavigationController.h"
#import "LauncherPreferences.h"
#import "LauncherProfileEditorViewController.h"
#import "MinecraftResourceUtils.h"
#import "PickTextField.h"
#import "PLProfiles.h"
#import "ios_uikit_bridge.h"
#import "utils.h"
@interface LauncherProfileEditorViewController()<UIPickerViewDataSource, UIPickerViewDelegate>
@property(nonatomic) NSString* oldName;
@property(nonatomic) NSArray<NSDictionary *> *versionList;
@property(nonatomic) UITextField* versionTextField;
@property(nonatomic) UISegmentedControl* versionTypeControl;
@property(nonatomic) UIPickerView* versionPickerView;
@property(nonatomic) UIToolbar* versionPickerToolbar;
@property(nonatomic) int versionSelectedAt;
@end
@implementation LauncherProfileEditorViewController
- (void)viewDidLoad {
// Setup navigation bar & appearance
self.title = localize(@"Edit profile", nil);
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionDone)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemClose target:self action:@selector(actionClose)];
self.navigationController.modalInPresentation = YES;
self.prefSectionsVisible = YES;
// Setup preference getter and setter
__weak LauncherProfileEditorViewController *weakSelf = self;
self.getPreference = ^id(NSString *section, NSString *key){
NSString *value = weakSelf.profile[key];
if (value.length > 0 || ![weakSelf isPickFieldAtSection:section key:key]) {
return value;
} else {
return @"(default)";
}
};
self.setPreference = ^(NSString *section, NSString *key, NSString *value){
if ([value isEqualToString:@"(default)"] && [weakSelf isPickFieldAtSection:section key:key]) {
[weakSelf.profile removeObjectForKey:key];
} else if (value) {
weakSelf.profile[key] = value;
}
};
// Obtain all the lists
self.oldName = self.getPreference(nil, @"name");
if ([self.oldName length] == 0) {
self.setPreference(nil, @"name", @"New Profile");
}
NSArray *rendererKeys = getRendererKeys(YES);
NSArray *rendererList = getRendererNames(YES);
NSArray *touchControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")]];
NSArray *gamepadControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap/gamepads", getenv("POJAV_HOME")]];
NSMutableArray *javaList = [getPrefObject(@"java.java_homes") allKeys].mutableCopy;
[javaList sortUsingSelector:@selector(compare:)];
javaList[0] = @"(default)";
// Setup version picker
[self setupVersionPicker];
id typeVersionPicker = ^void(UITableViewCell *cell, NSString *section, NSString *key, NSDictionary *item){
self.typeTextField(cell, section, key, item);
UITextField *textField = (id)cell.accessoryView;
weakSelf.versionTextField = textField;
textField.inputAccessoryView = weakSelf.versionPickerToolbar;
textField.inputView = weakSelf.versionPickerView;
// Auto pick version type
if (self.versionList) return;
if ([MinecraftResourceUtils findVersion:textField.text inList:localVersionList]) {
self.versionTypeControl.selectedSegmentIndex = 0;
} else {
NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:textField.text inList:remoteVersionList];
if (selected) {
NSArray *types = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"];
NSString *type = selected[@"type"];
self.versionTypeControl.selectedSegmentIndex = [types indexOfObject:type];
} else {
// Version not found
self.versionTypeControl.selectedSegmentIndex = 0;
}
}
self.versionSelectedAt = -1;
[self changeVersionType:nil];
};
self.prefContents = @[
@[
// General settings
@{@"key": @"name",
@"icon": @"tag",
@"title": @"preference.profile.title.name",
@"type": self.typeTextField,
@"placeholder": self.oldName
},
@{@"key": @"lastVersionId",
@"icon": @"archivebox",
@"title": @"preference.profile.title.version",
@"type": typeVersionPicker,
@"placeholder": self.getPreference(nil, @"lastVersionId"),
@"customClass": PickTextField.class
},
@{@"key": @"gameDir",
@"icon": @"folder",
@"title": @"preference.title.game_directory",
@"type": self.typeTextField,
@"placeholder": [NSString stringWithFormat:@". -> /Documents/instances/%@", getPrefObject(@"general.game_directory")]
},
// Video and renderer settings
@{@"key": @"renderer",
@"icon": @"cpu",
@"type": self.typePickField,
@"pickKeys": rendererKeys,
@"pickList": rendererList
},
// Control settings
@{@"key": @"defaultTouchCtrl",
@"icon": @"hand.tap",
@"title": @"preference.profile.title.default_touch_control",
@"type": self.typePickField,
@"pickKeys": touchControlList,
@"pickList": touchControlList
},
@{@"key": @"defaultGamepadCtrl",
@"icon": @"gamecontroller",
@"title": @"preference.profile.title.default_gamepad_control",
@"type": self.typePickField,
@"pickKeys": gamepadControlList,
@"pickList": gamepadControlList
},
// Java tweaks
@{@"key": @"javaVersion",
@"icon": @"cube",
@"title": @"preference.manage_runtime.header.default",
@"type": self.typePickField,
@"pickKeys": javaList,
@"pickList": javaList
},
@{@"key": @"javaArgs",
@"icon": @"slider.vertical.3",
@"title": @"preference.title.java_args",
@"type": self.typeTextField,
@"placeholder": @"(default)"
}
]
];
[super viewDidLoad];
}
- (void)actionClose {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
- (void)actionDone {
// We might be saving without ending editing, so make sure textFieldDidEndEditing is always called
UITextField *currentTextField = [self performSelector:@selector(_firstResponder)];
if ([currentTextField isKindOfClass:UITextField.class] && [currentTextField isDescendantOfView:self.tableView]) {
[self textFieldDidEndEditing:currentTextField];
}
if ([self.profile[@"name"] length] == 0 && self.oldName.length > 0) {
// Return to its old name
self.profile[@"name"] = self.oldName;
}
if ([self.oldName isEqualToString:self.profile[@"name"]]) {
// Not a rename, directly create/replace
PLProfiles.current.profiles[self.oldName] = self.profile;
} else if (!PLProfiles.current.profiles[self.profile[@"name"]]) {
// A rename, remove then re-add to update its key name
if (self.oldName.length > 0) {
[PLProfiles.current.profiles removeObjectForKey:self.oldName];
}
PLProfiles.current.profiles[self.profile[@"name"]] = self.profile;
// Update selected name
if ([PLProfiles.current.selectedProfileName isEqualToString:self.oldName]) {
PLProfiles.current.selectedProfileName = self.profile[@"name"];
}
} else {
// Cancel rename since a profile with the same name already exists
showDialog(localize(@"Error", nil), localize(@"profile.error.name_exists", nil));
// Skip dismissing this view controller
return;
}
[PLProfiles.current save];
[self actionClose];
// Call LauncherProfilesViewController's viewWillAppear
UINavigationController *navVC = (id) ((UISplitViewController *)self.presentingViewController).viewControllers[1];
[navVC.viewControllers[0] viewWillAppear:NO];
}
- (BOOL)isPickFieldAtSection:(NSString *)section key:(NSString *)key {
NSDictionary *pref = [self.prefContents[0] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(key == %@)", key]].firstObject;
return pref[@"type"] == self.typePickField;
}
- (NSArray *)listFilesAtPath:(NSString *)path {
NSMutableArray *files = [NSFileManager.defaultManager contentsOfDirectoryAtPath:path error:nil].mutableCopy;
for (int i = 0; i < files.count;) {
if ([files[i] hasSuffix:@".json"]) {
i++;
} else {
[files removeObjectAtIndex:i];
}
}
[files insertObject:@"(default)" atIndex:0];
return files;
}
#pragma mark Version picker
- (void)setupVersionPicker {
self.versionPickerView = [[UIPickerView alloc] init];
self.versionPickerView.delegate = self;
self.versionPickerView.dataSource = self;
self.versionPickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)];
self.versionTypeControl = [[UISegmentedControl alloc] initWithItems:@[
localize(@"Installed", nil),
localize(@"Releases", nil),
localize(@"Snapshot", nil),
localize(@"Old-beta", nil),
localize(@"Old-alpha", nil)
]];
[self.versionTypeControl addTarget:self action:@selector(changeVersionType:) forControlEvents:UIControlEventValueChanged];
self.versionPickerToolbar.items = @[
[[UIBarButtonItem alloc] initWithCustomView:self.versionTypeControl],
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(versionClosePicker)]
];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (self.versionList.count == 0) {
self.versionTextField.text = @"";
return;
}
self.versionSelectedAt = row;
self.versionTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.versionList.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if (self.versionList.count <= row) return nil;
NSObject *object = self.versionList[row];
if ([object isKindOfClass:[NSString class]]) {
return (NSString*) object;
} else {
return [object valueForKey:@"id"];
}
}
- (void)versionClosePicker {
[self.versionTextField endEditing:YES];
[self pickerView:self.versionPickerView didSelectRow:[self.versionPickerView selectedRowInComponent:0] inComponent:0];
}
- (void)changeVersionType:(UISegmentedControl *)sender {
if (sender || !self.versionList) {
if (self.versionTypeControl.selectedSegmentIndex == 0) {
// installed
self.versionList = localVersionList;
} else {
NSString *type = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"][self.versionTypeControl.selectedSegmentIndex];
self.versionList = [remoteVersionList filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(type == %@)", type]];
}
[self.versionPickerView reloadAllComponents];
}
if (self.versionSelectedAt == -1) {
NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:self.versionTextField.text inList:self.versionList];
self.versionSelectedAt = [self.versionList indexOfObject:selected];
} else {
// Find the most matching version for this type
NSObject *lastSelected = nil;
if (self.versionList.count > 0 && self.versionSelectedAt >= 0) {
lastSelected = self.versionList[self.versionSelectedAt];
}
if (self.versionSelectedAt < 0 && lastSelected != nil) {
NSObject *nearest = [MinecraftResourceUtils findNearestVersion:lastSelected expectedType:self.versionTypeControl.selectedSegmentIndex];
if (nearest != nil) {
self.versionSelectedAt = [self.versionList indexOfObject:(id)nearest];
}
}
lastSelected = nil;
// Get back the currently selected in case none matching version found
self.versionSelectedAt = MIN(abs(self.versionSelectedAt), self.versionList.count - 1);
}
[self.versionPickerView selectRow:self.versionSelectedAt inComponent:0 animated:NO];
[self pickerView:self.versionPickerView didSelectRow:self.versionSelectedAt inComponent:0];
}
@end