Skip to content

Commit 7f91ab0

Browse files
committed
Add option to hide older devices from device lists, always specify boardconfig, add newer iPads (#227)
1 parent f2108a2 commit 7f91ab0

File tree

8 files changed

+261
-108
lines changed

8 files changed

+261
-108
lines changed

src/main/java/airsquared/blobsaver/app/Controller.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@
4646
import java.util.Optional;
4747
import java.util.concurrent.TimeUnit;
4848

49-
@SuppressWarnings({"TextBlockMigration", "EnhancedSwitchMigration"})
49+
@SuppressWarnings({"TextBlockMigration"})
5050
public class Controller {
5151

5252

5353
@FXML private MenuBar menuBar;
54-
@FXML private MenuItem checkForUpdatesMenu, clearAllDataMenu, deleteDeviceMenu;
54+
@FXML private MenuItem checkForUpdatesMenu, clearAllDataMenu, deleteDeviceMenu, backgroundSettingsMenu;
5555

5656
@FXML private ChoiceBox<String> deviceTypeChoiceBox, deviceModelChoiceBox;
5757

@@ -76,6 +76,9 @@ public void initialize() {
7676
}
7777
deviceList.getSelectionModel().selectedItemProperty().addListener((a, b, device) -> loadSavedDevice(device));
7878
deleteDeviceMenu.disableProperty().bind(Bindings.isNull(deviceList.getSelectionModel().selectedItemProperty()));
79+
backgroundSettingsMenu.textProperty().bind(Bindings.when(backgroundSettingsButton.selectedProperty())
80+
.then("Hide Background Settings").otherwise("Show Background Settings"));
81+
backgroundSettingsMenu.setOnAction(e -> backgroundSettingsButton.fire());
7982
}
8083

8184
public void newGithubIssue() { Utils.newGithubIssue(); }
@@ -92,7 +95,6 @@ public void checkRequirements(ObservableValue<?> ignored, String ignored2, Strin
9295
if (!Utils.isEmptyOrNull(identifier) && Devices.doesRequireBoardConfig(identifier)) {
9396
boardConfigField.setDisable(false);
9497
boardConfigField.setEffect(Utils.borderGlow);
95-
boardConfigField.setText(Devices.getBoardConfig(identifier));
9698
} else if (!boardConfigField.isDisable()) {
9799
boardConfigField.setEffect(null);
98100
boardConfigField.setDisable(true);
@@ -245,6 +247,11 @@ public void devicesListFocusLoss(ObservableValue<?> a, boolean b, boolean focuse
245247
if (!focused) deviceList.getSelectionModel().clearSelection();
246248
}
247249

250+
public void showOlderDevicesHandler(Event evt) {
251+
Prefs.setShowOldDevices(((CheckMenuItem) evt.getSource()).isSelected());
252+
Devices.updateLists();
253+
}
254+
248255
public void checkBlobs() { Utils.openURL("https://verify.shsh.host"); }
249256

250257
public void helpLabelHandler(Event evt) {
@@ -258,23 +265,20 @@ public void helpLabelHandler(Event evt) {
258265
ButtonType customOK = new ButtonType("OK", ButtonBar.ButtonData.CANCEL_CLOSE);
259266
Alert alert = new Alert(Alert.AlertType.INFORMATION, "", openURL, customOK);
260267
((Button) alert.getDialogPane().lookupButton(customOK)).setDefaultButton(true);
261-
String url;
262-
switch (labelID) {
268+
String url = switch (labelID) {
263269
case "ipswURLHelp":
264270
alert.setContentText("Get the IPSW download URL for the iOS version from theiphonewiki.com/wiki/Beta_Firmware and paste it here.");
265271
alert.setTitle("Help: IPSW URL");
266272
alert.setHeaderText("Help");
267-
url = "https://www.theiphonewiki.com/wiki/Beta_Firmware";
268-
break;
273+
yield "https://www.theiphonewiki.com/wiki/Beta_Firmware";
269274
case "locationHelp":
270275
alert.setContentText("Click \"Open URL\" to see how to automatically upload blobs you save to the cloud.");
271276
alert.setTitle("Tip: Saving Blobs to the Cloud");
272277
alert.setHeaderText("Tip");
273-
url = "https://github.com/airsquared/blobsaver/wiki/Automatically-saving-blobs-to-the-cloud";
274-
break;
278+
yield "https://github.com/airsquared/blobsaver/wiki/Automatically-saving-blobs-to-the-cloud";
275279
default:
276280
throw new IllegalStateException("Unexpected value for labelID: " + labelID);
277-
}
281+
};
278282
alert.showAndWait();
279283
if (openURL.equals(alert.getResult())) {
280284
Utils.openURL(url);
@@ -308,7 +312,7 @@ public void aboutMenuHandler(Event ignored) {
308312

309313
private void useMacOSMenuBar() {
310314
((VBox) menuBar.getParent()).getChildren().remove(menuBar);
311-
menuBar.getMenus().get(0).getItems().remove(4, 6); // clear old options menu
315+
menuBar.getMenus().get(0).getItems().remove(5, 8); // clear old options menu
312316

313317
MenuToolkit tk = MenuToolkit.toolkit();
314318

@@ -320,11 +324,11 @@ private void useMacOSMenuBar() {
320324
applicationMenu.getItems().add(3, new SeparatorMenuItem());
321325
applicationMenu.getItems().add(4, clearAllDataMenu);
322326

323-
menuBar.getMenus().get(2).getItems().addAll(new SeparatorMenuItem(), tk.createMinimizeMenuItem(), tk.createCycleWindowsItem(),
327+
menuBar.getMenus().get(3).getItems().addAll(new SeparatorMenuItem(), tk.createMinimizeMenuItem(), tk.createCycleWindowsItem(),
324328
new SeparatorMenuItem(), tk.createBringAllToFrontItem());
325-
tk.autoAddWindowMenuItems(menuBar.getMenus().get(2));
329+
tk.autoAddWindowMenuItems(menuBar.getMenus().get(3));
326330

327-
menuBar.getMenus().get(3).getItems().remove(8, 10); // remove about
331+
menuBar.getMenus().get(4).getItems().remove(8, 10); // remove about
328332

329333
tk.setApplicationMenu(applicationMenu);
330334
tk.setGlobalMenuBar(menuBar);

src/main/java/airsquared/blobsaver/app/Devices.java

Lines changed: 72 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
import java.util.Properties;
2929

3030
@SuppressWarnings({"unchecked", "rawtypes"})
31-
public class Devices {
31+
public final class Devices {
3232

33-
private static final ObservableList<String> iPhones = unmodifiableArrayList("iPhone 3G[S]", "iPhone 4 (GSM)",
33+
private static final String[] iPhones = {"iPhone 3G[S]", "iPhone 4 (GSM)",
3434
"iPhone 4 (GSM 2012)", "iPhone 4 (CDMA)", "iPhone 4[S]", "iPhone 5 (GSM)", "iPhone 5 (Global)",
3535
"iPhone 5c (GSM)", "iPhone 5c (Global)", "iPhone 5s (GSM)", "iPhone 5s (Global)",
3636
"iPhone 6+", "iPhone 6", "iPhone 6s", "iPhone 6s+", "iPhone SE", "iPhone 7 (Global)(iPhone9,1)",
@@ -40,108 +40,94 @@ public class Devices {
4040
"iPhone XS Max (China) (iPhone11,4)", "iPhone XS Max (iPhone11,6)", "iPhone XR (iPhone11,8)",
4141
"iPhone 11 (iPhone12,1)", "iPhone 11 Pro (iPhone12,3)", "iPhone 11 Pro Max (iPhone12,5)",
4242
"iPhone SE 2 (iPhone12,8)", "iPhone 12 mini (iPhone13,1)", "iPhone 12 (iPhone13,2)",
43-
"iPhone 12 Pro (iPhone13,3)", "iPhone 12 Pro Max (iPhone13,4)");
44-
45-
private static final ObservableList<String> iPods =
46-
unmodifiableArrayList("iPod Touch 3", "iPod Touch 4", "iPod Touch 5", "iPod Touch 6",
47-
"iPod Touch 7 (iPod9,1)");
48-
49-
private static final ObservableList<String> iPads =
50-
unmodifiableArrayList("iPad 1", "iPad 2 (WiFi)", "iPad 2 (GSM)",
51-
"iPad 2 (CDMA)", "iPad 2 (Mid 2012)", "iPad Mini (Wifi)", "iPad Mini (GSM)", "iPad Mini (Global)",
52-
"iPad 3 (WiFi)", "iPad 3 (CDMA)", "iPad 3 (GSM)", "iPad 4 (WiFi)", "iPad 4 (GSM)", "iPad 4 (Global)",
53-
"iPad Air (Wifi)", "iPad Air (Cellular)", "iPad Air (China)", "iPad Mini 2 (WiFi)", "iPad Mini 2 (Cellular)",
54-
"iPad Mini 2 (China)", "iPad Mini 3 (WiFi)", "iPad Mini 3 (Cellular)", "iPad Mini 3 (China)",
55-
"iPad Mini 4 (Wifi)", "iPad Mini 4 (Cellular)", "iPad Air 2 (WiFi)", "iPad Air 2 (Cellular)",
56-
"iPad Pro 9.7 (Wifi)", "iPad Pro 9.7 (Cellular)", "iPad Pro 12.9 (WiFi)", "iPad Pro 12.9 (Cellular)",
57-
"iPad 5 (Wifi)", "iPad 5 (Cellular)", "iPad Pro 2 12.9 (WiFi)(iPad7,1)", "iPad Pro 2 12.9 (Cellular)(iPad7,2)",
58-
"iPad Pro 10.5 (WiFi)(iPad7,3)", "iPad 10.5 (Cellular)(iPad7,4)", "iPad 6 (WiFi)(iPad 7,5)",
59-
"iPad 6 (Cellular)(iPad7,6)", "iPad 7 (WiFi)(iPad7,11)", "iPad 7 (Cellular)(iPad7,12)",
60-
"iPad Pro 3 11' (WiFi)(iPad8,1)", "iPad Pro 3 11' (WiFi)(iPad8,2)", "iPad Pro 3 11' (Cellular)(iPad8,3)",
61-
"iPad Pro 3 11' (Cellular)(iPad8,4)", "iPad Pro 3 12.9'(WiFi)(iPad8,5)", "iPad Pro 3 12.9 (WiFi)(iPad8,6)",
62-
"iPad Pro 3 12.9 (Cellular)(iPad8,7)", "iPad Pro 3 12.9 (Cellular)(iPad8,8)", "iPad Pro 4 11' (WiFi)(iPad8,9)",
63-
"iPad Pro 4 11' (Cellular)(iPad8,10)", "iPad Pro 4 12.9' (WiFi)(iPad8,11)",
64-
"iPad Pro 4 12.9' (Cellular)(iPad8,12)", "iPad Mini 5 (WiFi)(iPad11,1)", "iPad Mini 5 (Cellular)(iPad11,2)",
65-
"iPad Air 3 (WiFi)(iPad11,3)", "iPad Air 3 (Cellular)(iPad11,4)");
66-
67-
private static final ObservableList<String> AppleTVs =
68-
unmodifiableArrayList("Apple TV 2G", "Apple TV 3", "Apple TV 3 (2013)", "Apple TV 4 (2015)", "Apple TV 4K");
43+
"iPhone 12 Pro (iPhone13,3)", "iPhone 12 Pro Max (iPhone13,4)"};
44+
private static final String[] iPads = {"iPad 1", "iPad 2 (WiFi)", "iPad 2 (GSM)",
45+
"iPad 2 (CDMA)", "iPad 2 (Mid 2012)", "iPad Mini (Wifi)", "iPad Mini (GSM)", "iPad Mini (Global)",
46+
"iPad 3 (WiFi)", "iPad 3 (CDMA)", "iPad 3 (GSM)", "iPad 4 (WiFi)", "iPad 4 (GSM)", "iPad 4 (Global)",
47+
"iPad Air (Wifi)", "iPad Air (Cellular)", "iPad Air (China)", "iPad Mini 2 (WiFi)", "iPad Mini 2 (Cellular)",
48+
"iPad Mini 2 (China)", "iPad Mini 3 (WiFi)", "iPad Mini 3 (Cellular)", "iPad Mini 3 (China)",
49+
"iPad Mini 4 (Wifi)", "iPad Mini 4 (Cellular)", "iPad Air 2 (WiFi)", "iPad Air 2 (Cellular)",
50+
"iPad Pro 9.7 (Wifi)", "iPad Pro 9.7 (Cellular)", "iPad Pro 12.9 (WiFi)", "iPad Pro 12.9 (Cellular)",
51+
"iPad 5 (Wifi)", "iPad 5 (Cellular)", "iPad Pro 2 12.9 (WiFi)(iPad7,1)", "iPad Pro 2 12.9 (Cellular)(iPad7,2)",
52+
"iPad Pro 10.5 (WiFi)(iPad7,3)", "iPad 10.5 (Cellular)(iPad7,4)", "iPad 6 (WiFi)(iPad 7,5)",
53+
"iPad 6 (Cellular)(iPad7,6)", "iPad 7 (WiFi)(iPad7,11)", "iPad 7 (Cellular)(iPad7,12)",
54+
"iPad Pro 3 11' (WiFi)(iPad8,1)", "iPad Pro 3 11' (WiFi)(iPad8,2)", "iPad Pro 3 11' (Cellular)(iPad8,3)",
55+
"iPad Pro 3 11' (Cellular)(iPad8,4)", "iPad Pro 3 12.9'(WiFi)(iPad8,5)", "iPad Pro 3 12.9 (WiFi)(iPad8,6)",
56+
"iPad Pro 3 12.9 (Cellular)(iPad8,7)", "iPad Pro 3 12.9 (Cellular)(iPad8,8)", "iPad Pro 4 11' (WiFi)(iPad8,9)",
57+
"iPad Pro 4 11' (Cellular)(iPad8,10)", "iPad Pro 4 12.9' (WiFi)(iPad8,11)",
58+
"iPad Pro 4 12.9' (Cellular)(iPad8,12)", "iPad Mini 5 (WiFi)(iPad11,1)", "iPad Mini 5 (Cellular)(iPad11,2)",
59+
"iPad Air 3 (WiFi)(iPad11,3)", "iPad Air 3 (Cellular)(iPad11,4)", "iPad 8 (WiFi) (iPad11,6)",
60+
"iPad 8 (Cellular) (iPad11,7)", "iPad Air 4 (WiFi) (iPad13,1)", "iPad Air 4 (Cellular) (iPad13,2)"};
61+
62+
private static final ObservableList<String> iPhoneList = FXCollections.observableArrayList(iPhones);
63+
private static final ObservableList<String> iPadList = FXCollections.observableArrayList(iPads);
64+
65+
private static final ObservableList<String> iPodList = unmodifiableArrayList("iPod Touch 3", "iPod Touch 4",
66+
"iPod Touch 5", "iPod Touch 6", "iPod Touch 7 (iPod9,1)");
67+
68+
private static final ObservableList<String> AppleTVList = unmodifiableArrayList("Apple TV 2G", "Apple TV 3",
69+
"Apple TV 3 (2013)", "Apple TV 4 (2015)", "Apple TV 4K");
6970

7071
private static final ObservableList<String> deviceTypes = unmodifiableArrayList("iPhone", "iPod", "iPad", "AppleTV");
7172

72-
private static final HashMap<String, String> requiresBoardConfig = new HashMap<>();
73+
private static final Map<String, String> boardConfigs;
7374

7475
private static final Map<String, String> deviceModelIdentifiers;
7576

7677
private static final Map<String, String> identifierDeviceModels = new HashMap<>();
7778

7879
static {
7980
try {
80-
Properties properties = new Properties();
81-
properties.load(Devices.class.getResourceAsStream("devicemodels.properties"));
82-
deviceModelIdentifiers = (Map) properties;
81+
deviceModelIdentifiers = loadProperties("devicemodels.properties");
8382
deviceModelIdentifiers.forEach((k, v) -> identifierDeviceModels.put(v, k));
83+
84+
boardConfigs = loadProperties("boardconfigs.properties");
8485
} catch (IOException e) {
8586
throw new UncheckedIOException(e);
8687
}
87-
}
88-
89-
static {
90-
requiresBoardConfig.put("iPhone13,4", "D54pAP");
91-
requiresBoardConfig.put("iPhone13,3", "D53pAP");
92-
requiresBoardConfig.put("iPhone13,2", "D53gAP");
93-
requiresBoardConfig.put("iPhone13,1", "D52gAP");
94-
requiresBoardConfig.put("iPhone12,8", "D79AP");
95-
requiresBoardConfig.put("iPad8,9", "J417AP");
96-
requiresBoardConfig.put("iPad8,10", "J418AP");
97-
requiresBoardConfig.put("iPad8,11", "J420AP");
98-
requiresBoardConfig.put("iPad8,12", "J421AP");
99-
100-
// devices with multiple board configs
101-
requiresBoardConfig.put("iPhone8,1", "");
102-
requiresBoardConfig.put("iPhone8,2", "");
103-
requiresBoardConfig.put("iPhone8,4", "");
104-
requiresBoardConfig.put("iPad7,11", "");
105-
requiresBoardConfig.put("iPad6,11", "");
106-
requiresBoardConfig.put("iPad6,12", "");
107-
}
10888

109-
public static ObservableList<String> getiPhones() {
110-
return iPhones;
89+
updateLists();
11190
}
11291

113-
public static ObservableList<String> getiPods() {
114-
return iPods;
92+
/**
93+
* Updates the device lists based on the user preference to show older devices in the UI or not
94+
*/
95+
public static void updateLists() {
96+
if (Prefs.getShowOldDevices()) {
97+
iPhoneList.setAll(iPhones);
98+
iPadList.setAll(iPads);
99+
} else if (!iPhoneList.get(0).equals("iPhone 6+")) {
100+
iPhoneList.remove(0, iPhoneList.indexOf("iPhone 6+"));
101+
iPadList.remove(0, iPadList.indexOf("iPad Mini 4 (Wifi)"));
102+
}
115103
}
116104

117-
public static ObservableList<String> getiPads() {
118-
return iPads;
105+
public static ObservableList<String> getiPhoneList() {
106+
return iPhoneList;
119107
}
120108

121-
public static ObservableList<String> getAppleTVs() {
122-
return AppleTVs;
123-
}
109+
// other accessors not used
124110

125111
public static ObservableList<String> getDeviceTypes() {
126112
return deviceTypes;
127113
}
128114

129-
static boolean containsIdentifier(String identifier) {
115+
public static boolean containsIdentifier(String identifier) {
130116
return identifierDeviceModels.containsKey(identifier);
131117
}
132118

133-
static String getBoardConfig(String identifier) {
134-
return requiresBoardConfig.get(identifier);
119+
public static String getBoardConfig(String identifier) {
120+
return boardConfigs.get(identifier);
135121
}
136122

137-
static String identifierToModel(String identifier) {
123+
public static String identifierToModel(String identifier) {
138124
if (identifier == null) {
139125
return null;
140126
}
141127
return identifierDeviceModels.get(identifier);
142128
}
143129

144-
static String modelToIdentifier(String deviceModel) {
130+
public static String modelToIdentifier(String deviceModel) {
145131
if (deviceModel == null) {
146132
return null;
147133
}
@@ -151,7 +137,7 @@ static String modelToIdentifier(String deviceModel) {
151137
/**
152138
* @return either "iPhone", "iPod", "iPad", or "AppleTV"
153139
*/
154-
static String getDeviceType(String identifier) {
140+
public static String getDeviceType(String identifier) {
155141
if (identifier.startsWith("iPhone")) {
156142
return "iPhone";
157143
} else if (identifier.startsWith("iPod")) {
@@ -164,17 +150,17 @@ static String getDeviceType(String identifier) {
164150
throw new IllegalArgumentException("Not found: " + identifier);
165151
}
166152

167-
static ObservableList<String> getModelsForType(String deviceType) {
153+
public static ObservableList<String> getModelsForType(String deviceType) {
168154
return switch (deviceType == null ? "" : deviceType) {
169-
case "iPhone" -> iPhones;
170-
case "iPod" -> iPods;
171-
case "iPad" -> iPads;
172-
case "AppleTV" -> AppleTVs;
155+
case "iPhone" -> iPhoneList;
156+
case "iPod" -> iPodList;
157+
case "iPad" -> iPadList;
158+
case "AppleTV" -> AppleTVList;
173159
default -> FXCollections.emptyObservableList();
174160
};
175161
}
176162

177-
static String getOSNameForType(String deviceType) {
163+
public static String getOSNameForType(String deviceType) {
178164
return switch (deviceType == null ? "" : deviceType) {
179165
case "iPhone", "iPod" -> "iOS";
180166
case "iPad" -> "iOS/iPadOS";
@@ -183,21 +169,28 @@ static String getOSNameForType(String deviceType) {
183169
};
184170
}
185171

186-
static String getOSNameForIdentifier(String identifier) {
172+
public static String getOSNameForIdentifier(String identifier) {
187173
return getOSNameForType(getDeviceType(identifier));
188174
}
189175

190-
static boolean doesRequireBoardConfig(String deviceIdentifier) {
191-
return requiresBoardConfig.containsKey(deviceIdentifier) || !containsIdentifier(deviceIdentifier);
176+
public static boolean doesRequireBoardConfig(String deviceIdentifier) {
177+
return !boardConfigs.containsKey(deviceIdentifier);
192178
}
193179

194-
static boolean doesRequireApnonce(String deviceIdentifier) {
180+
public static boolean doesRequireApnonce(String deviceIdentifier) {
195181
return deviceIdentifier.startsWith("iPhone11,") || deviceIdentifier.startsWith("iPhone12,") ||
196-
deviceIdentifier.startsWith("iPad8,") || deviceIdentifier.startsWith("iPad11,");
182+
deviceIdentifier.startsWith("iPhone13,") || deviceIdentifier.startsWith("iPad8,") ||
183+
deviceIdentifier.startsWith("iPad11,");
197184
}
198185

199186
@SafeVarargs
200187
private static <T> ObservableList<T> unmodifiableArrayList(T... items) {
201188
return FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(items));
202189
}
190+
191+
private static Map<String, String> loadProperties(String resourceName) throws IOException {
192+
Properties properties = new Properties();
193+
properties.load(Devices.class.getResourceAsStream(resourceName));
194+
return (Map) properties;
195+
}
203196
}

src/main/java/airsquared/blobsaver/app/Prefs.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,12 @@
3636
import java.util.stream.Collectors;
3737
import java.util.stream.Stream;
3838

39-
public class Prefs {
39+
public final class Prefs {
4040

4141
private static final Preferences appPrefs = Preferences.userRoot().node("airsquared/blobsaver/app");
4242
private static final Preferences savedDevicesPrefs = appPrefs.node("Saved Devices");
4343
private static ObservableList<SavedDevice> savedDevicesList;
4444

45-
public static void setLastAppVersion(@SuppressWarnings("SameParameterValue") String version) {
46-
appPrefs.put("App version", version);
47-
}
48-
49-
public static void setIgnoreVersion(String ignoreVersion) {
50-
appPrefs.put("Ignore Version", ignoreVersion);
51-
}
52-
53-
public static boolean shouldIgnoreVersion(String testForVersion) {
54-
return testForVersion.equals(appPrefs.get("Ignore Version", null));
55-
}
56-
5745
public static void resetPrefs() {
5846
try {
5947
appPrefs.removeNode();
@@ -104,6 +92,26 @@ public static void importOldVersion() {
10492
}
10593
}
10694

95+
public static void setLastAppVersion(@SuppressWarnings("SameParameterValue") String version) {
96+
appPrefs.put("App version", version);
97+
}
98+
99+
public static void setIgnoreVersion(String ignoreVersion) {
100+
appPrefs.put("Ignore Version", ignoreVersion);
101+
}
102+
103+
public static boolean shouldIgnoreVersion(String testForVersion) {
104+
return testForVersion.equals(appPrefs.get("Ignore Version", null));
105+
}
106+
107+
public static void setShowOldDevices(boolean showOldDevices) {
108+
appPrefs.putBoolean("Show Old Devices", showOldDevices);
109+
}
110+
111+
public static boolean getShowOldDevices() {
112+
return appPrefs.getBoolean("Show Old Devices", false);
113+
}
114+
107115
public static Optional<SavedDevice> savedDevice(String name) {
108116
if (savedDeviceExists(name)) {
109117
return Optional.of(new SavedDevice(name));

0 commit comments

Comments
 (0)