Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/PojavLauncher_iOS
Path: blob/main/Natives/LauncherProfileEditorViewController.m
589 views
1
#import "LauncherNavigationController.h"
2
#import "LauncherPreferences.h"
3
#import "LauncherProfileEditorViewController.h"
4
#import "MinecraftResourceUtils.h"
5
#import "PickTextField.h"
6
#import "PLProfiles.h"
7
#import "ios_uikit_bridge.h"
8
#import "utils.h"
9
10
@interface LauncherProfileEditorViewController()<UIPickerViewDataSource, UIPickerViewDelegate>
11
@property(nonatomic) NSString* oldName;
12
13
@property(nonatomic) NSArray<NSDictionary *> *versionList;
14
@property(nonatomic) UITextField* versionTextField;
15
@property(nonatomic) UISegmentedControl* versionTypeControl;
16
@property(nonatomic) UIPickerView* versionPickerView;
17
@property(nonatomic) UIToolbar* versionPickerToolbar;
18
@property(nonatomic) int versionSelectedAt;
19
@end
20
21
@implementation LauncherProfileEditorViewController
22
23
- (void)viewDidLoad {
24
// Setup navigation bar & appearance
25
self.title = localize(@"Edit profile", nil);
26
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionDone)];
27
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemClose target:self action:@selector(actionClose)];
28
self.navigationController.modalInPresentation = YES;
29
self.prefSectionsVisible = YES;
30
31
// Setup preference getter and setter
32
__weak LauncherProfileEditorViewController *weakSelf = self;
33
self.getPreference = ^id(NSString *section, NSString *key){
34
NSString *value = weakSelf.profile[key];
35
if (value.length > 0 || ![weakSelf isPickFieldAtSection:section key:key]) {
36
return value;
37
} else {
38
return @"(default)";
39
}
40
};
41
self.setPreference = ^(NSString *section, NSString *key, NSString *value){
42
if ([value isEqualToString:@"(default)"] && [weakSelf isPickFieldAtSection:section key:key]) {
43
[weakSelf.profile removeObjectForKey:key];
44
} else if (value) {
45
weakSelf.profile[key] = value;
46
}
47
};
48
49
// Obtain all the lists
50
self.oldName = self.getPreference(nil, @"name");
51
if ([self.oldName length] == 0) {
52
self.setPreference(nil, @"name", @"New Profile");
53
}
54
NSArray *rendererKeys = getRendererKeys(YES);
55
NSArray *rendererList = getRendererNames(YES);
56
NSArray *touchControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap", getenv("POJAV_HOME")]];
57
NSArray *gamepadControlList = [self listFilesAtPath:[NSString stringWithFormat:@"%s/controlmap/gamepads", getenv("POJAV_HOME")]];
58
NSMutableArray *javaList = [getPrefObject(@"java.java_homes") allKeys].mutableCopy;
59
[javaList sortUsingSelector:@selector(compare:)];
60
javaList[0] = @"(default)";
61
62
// Setup version picker
63
[self setupVersionPicker];
64
id typeVersionPicker = ^void(UITableViewCell *cell, NSString *section, NSString *key, NSDictionary *item){
65
self.typeTextField(cell, section, key, item);
66
UITextField *textField = (id)cell.accessoryView;
67
weakSelf.versionTextField = textField;
68
textField.inputAccessoryView = weakSelf.versionPickerToolbar;
69
textField.inputView = weakSelf.versionPickerView;
70
// Auto pick version type
71
if (self.versionList) return;
72
if ([MinecraftResourceUtils findVersion:textField.text inList:localVersionList]) {
73
self.versionTypeControl.selectedSegmentIndex = 0;
74
} else {
75
NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:textField.text inList:remoteVersionList];
76
if (selected) {
77
NSArray *types = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"];
78
NSString *type = selected[@"type"];
79
self.versionTypeControl.selectedSegmentIndex = [types indexOfObject:type];
80
} else {
81
// Version not found
82
self.versionTypeControl.selectedSegmentIndex = 0;
83
}
84
}
85
self.versionSelectedAt = -1;
86
[self changeVersionType:nil];
87
};
88
89
self.prefContents = @[
90
@[
91
// General settings
92
@{@"key": @"name",
93
@"icon": @"tag",
94
@"title": @"preference.profile.title.name",
95
@"type": self.typeTextField,
96
@"placeholder": self.oldName
97
},
98
@{@"key": @"lastVersionId",
99
@"icon": @"archivebox",
100
@"title": @"preference.profile.title.version",
101
@"type": typeVersionPicker,
102
@"placeholder": self.getPreference(nil, @"lastVersionId"),
103
@"customClass": PickTextField.class
104
},
105
@{@"key": @"gameDir",
106
@"icon": @"folder",
107
@"title": @"preference.title.game_directory",
108
@"type": self.typeTextField,
109
@"placeholder": [NSString stringWithFormat:@". -> /Documents/instances/%@", getPrefObject(@"general.game_directory")]
110
},
111
// Video and renderer settings
112
@{@"key": @"renderer",
113
@"icon": @"cpu",
114
@"type": self.typePickField,
115
@"pickKeys": rendererKeys,
116
@"pickList": rendererList
117
},
118
// Control settings
119
@{@"key": @"defaultTouchCtrl",
120
@"icon": @"hand.tap",
121
@"title": @"preference.profile.title.default_touch_control",
122
@"type": self.typePickField,
123
@"pickKeys": touchControlList,
124
@"pickList": touchControlList
125
},
126
@{@"key": @"defaultGamepadCtrl",
127
@"icon": @"gamecontroller",
128
@"title": @"preference.profile.title.default_gamepad_control",
129
@"type": self.typePickField,
130
@"pickKeys": gamepadControlList,
131
@"pickList": gamepadControlList
132
},
133
// Java tweaks
134
@{@"key": @"javaVersion",
135
@"icon": @"cube",
136
@"title": @"preference.manage_runtime.header.default",
137
@"type": self.typePickField,
138
@"pickKeys": javaList,
139
@"pickList": javaList
140
},
141
@{@"key": @"javaArgs",
142
@"icon": @"slider.vertical.3",
143
@"title": @"preference.title.java_args",
144
@"type": self.typeTextField,
145
@"placeholder": @"(default)"
146
}
147
]
148
];
149
150
[super viewDidLoad];
151
}
152
153
- (void)actionClose {
154
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
155
}
156
157
- (void)actionDone {
158
// We might be saving without ending editing, so make sure textFieldDidEndEditing is always called
159
UITextField *currentTextField = [self performSelector:@selector(_firstResponder)];
160
if ([currentTextField isKindOfClass:UITextField.class] && [currentTextField isDescendantOfView:self.tableView]) {
161
[self textFieldDidEndEditing:currentTextField];
162
}
163
164
if ([self.profile[@"name"] length] == 0 && self.oldName.length > 0) {
165
// Return to its old name
166
self.profile[@"name"] = self.oldName;
167
}
168
169
if ([self.oldName isEqualToString:self.profile[@"name"]]) {
170
// Not a rename, directly create/replace
171
PLProfiles.current.profiles[self.oldName] = self.profile;
172
} else if (!PLProfiles.current.profiles[self.profile[@"name"]]) {
173
// A rename, remove then re-add to update its key name
174
if (self.oldName.length > 0) {
175
[PLProfiles.current.profiles removeObjectForKey:self.oldName];
176
}
177
PLProfiles.current.profiles[self.profile[@"name"]] = self.profile;
178
// Update selected name
179
if ([PLProfiles.current.selectedProfileName isEqualToString:self.oldName]) {
180
PLProfiles.current.selectedProfileName = self.profile[@"name"];
181
}
182
} else {
183
// Cancel rename since a profile with the same name already exists
184
showDialog(localize(@"Error", nil), localize(@"profile.error.name_exists", nil));
185
// Skip dismissing this view controller
186
return;
187
}
188
189
[PLProfiles.current save];
190
[self actionClose];
191
192
// Call LauncherProfilesViewController's viewWillAppear
193
UINavigationController *navVC = (id) ((UISplitViewController *)self.presentingViewController).viewControllers[1];
194
[navVC.viewControllers[0] viewWillAppear:NO];
195
}
196
197
- (BOOL)isPickFieldAtSection:(NSString *)section key:(NSString *)key {
198
NSDictionary *pref = [self.prefContents[0] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(key == %@)", key]].firstObject;
199
return pref[@"type"] == self.typePickField;
200
}
201
202
- (NSArray *)listFilesAtPath:(NSString *)path {
203
NSMutableArray *files = [NSFileManager.defaultManager contentsOfDirectoryAtPath:path error:nil].mutableCopy;
204
for (int i = 0; i < files.count;) {
205
if ([files[i] hasSuffix:@".json"]) {
206
i++;
207
} else {
208
[files removeObjectAtIndex:i];
209
}
210
}
211
[files insertObject:@"(default)" atIndex:0];
212
return files;
213
}
214
215
#pragma mark Version picker
216
217
- (void)setupVersionPicker {
218
self.versionPickerView = [[UIPickerView alloc] init];
219
self.versionPickerView.delegate = self;
220
self.versionPickerView.dataSource = self;
221
self.versionPickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0)];
222
self.versionTypeControl = [[UISegmentedControl alloc] initWithItems:@[
223
localize(@"Installed", nil),
224
localize(@"Releases", nil),
225
localize(@"Snapshot", nil),
226
localize(@"Old-beta", nil),
227
localize(@"Old-alpha", nil)
228
]];
229
[self.versionTypeControl addTarget:self action:@selector(changeVersionType:) forControlEvents:UIControlEventValueChanged];
230
self.versionPickerToolbar.items = @[
231
[[UIBarButtonItem alloc] initWithCustomView:self.versionTypeControl],
232
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
233
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(versionClosePicker)]
234
];
235
}
236
237
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
238
if (self.versionList.count == 0) {
239
self.versionTextField.text = @"";
240
return;
241
}
242
self.versionSelectedAt = row;
243
self.versionTextField.text = [self pickerView:pickerView titleForRow:row forComponent:component];
244
}
245
246
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
247
return 1;
248
}
249
250
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
251
return self.versionList.count;
252
}
253
254
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
255
if (self.versionList.count <= row) return nil;
256
NSObject *object = self.versionList[row];
257
if ([object isKindOfClass:[NSString class]]) {
258
return (NSString*) object;
259
} else {
260
return [object valueForKey:@"id"];
261
}
262
}
263
264
- (void)versionClosePicker {
265
[self.versionTextField endEditing:YES];
266
[self pickerView:self.versionPickerView didSelectRow:[self.versionPickerView selectedRowInComponent:0] inComponent:0];
267
}
268
269
- (void)changeVersionType:(UISegmentedControl *)sender {
270
NSArray *newVersionList = self.versionList;
271
if (sender || !self.versionList) {
272
if (self.versionTypeControl.selectedSegmentIndex == 0) {
273
// installed
274
newVersionList = localVersionList;
275
} else {
276
NSString *type = @[@"installed", @"release", @"snapshot", @"old_beta", @"old_alpha"][self.versionTypeControl.selectedSegmentIndex];
277
newVersionList = [remoteVersionList filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(type == %@)", type]];
278
}
279
}
280
281
if (self.versionSelectedAt == -1) {
282
NSDictionary *selected = (id)[MinecraftResourceUtils findVersion:self.versionTextField.text inList:newVersionList];
283
self.versionSelectedAt = [newVersionList indexOfObject:selected];
284
} else {
285
// Find the most matching version for this type
286
NSObject *lastSelected = nil;
287
if (self.versionList.count > self.versionSelectedAt) {
288
lastSelected = self.versionList[self.versionSelectedAt];
289
}
290
if (lastSelected != nil) {
291
NSObject *nearest = [MinecraftResourceUtils findNearestVersion:lastSelected expectedType:self.versionTypeControl.selectedSegmentIndex];
292
if (nearest != nil) {
293
self.versionSelectedAt = [newVersionList indexOfObject:(id)nearest];
294
}
295
}
296
lastSelected = nil;
297
// Get back the currently selected in case none matching version found
298
self.versionSelectedAt = MIN(abs(self.versionSelectedAt), newVersionList.count - 1);
299
}
300
301
self.versionList = newVersionList;
302
[self.versionPickerView reloadAllComponents];
303
if (self.versionSelectedAt != -1) {
304
[self.versionPickerView selectRow:self.versionSelectedAt inComponent:0 animated:NO];
305
[self pickerView:self.versionPickerView didSelectRow:self.versionSelectedAt inComponent:0];
306
}
307
}
308
309
@end
310
311