Skip to content

Commit 5a4bc72

Browse files
committed
Unify game settings and add reversible settings trials
Share Display and Controls between library and runtime, keep advanced options separate, and stage one-shot previews with Keep/Undo. Refs #16.
1 parent a822a77 commit 5a4bc72

20 files changed

Lines changed: 751 additions & 87 deletions

‎README.md‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@ Use **Settings > Library transfer** to import from J2ME Loader or move installed
3131
games and saves between AbyssME installations. See the
3232
[workflow and limitations](docs/LIBRARY_TRANSFER.md).
3333

34-
For the new Phone controls, open **Game menu > Touch controls** and choose
35-
**Phone** or **Gamepad**. The top-left display button opens live screen settings;
36-
image rotation is saved per game. The screenshots and beta.2 instructions below
34+
Development builds share **Display** and **Controls** pages between the library's
35+
per-game settings and the in-game menu. On Phone, choose **Controls > Touch layout >
36+
Phone / Gamepad**. Use **Try changes** (or **Try in game** from the library), then
37+
**Keep** or **Undo**; unconfirmed changes revert after about 20 seconds of preview.
38+
Phone resolution and the full compatibility editor are under **Advanced**.
39+
The old expert editor still saves ordinary edits directly; its **Fix game** action
40+
now offers a trial instead. See [settings trials](docs/SETTINGS_TRIALS.md).
41+
The screenshots and beta.2 instructions below
3742
describe the published release, not every unreleased change.
3843

3944
New release APKs are on hold pending the licensing decision. Wolphun and the
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package ru.playsoftware.j2meloader.config;
2+
3+
import androidx.test.core.app.ApplicationProvider;
4+
import android.content.Context;
5+
import org.junit.Before;
6+
import org.junit.After;
7+
import org.junit.Test;
8+
import java.io.File;
9+
import java.nio.file.Files;
10+
import static org.junit.Assert.*;
11+
12+
public class SettingsTrialTest {
13+
private File dir;
14+
private ProfileModel model;
15+
@Before public void setup() throws Exception {
16+
Context context = ApplicationProvider.getApplicationContext();
17+
dir = Files.createTempDirectory(context.getCacheDir().toPath(), "settings-trial-").toFile();
18+
model = new ProfileModel(dir);
19+
assertTrue(ProfilesManager.saveConfig(model));
20+
}
21+
@After public void cleanup() { for (File f : dir.listFiles()) assertTrue(f.delete()); assertTrue(dir.delete()); }
22+
23+
@Test public void previewNeverAutosavesAndUndoRestoresAllSettings() {
24+
String properties = model.systemProperties;
25+
ProfilesManager.beginPreview(model);
26+
model.screenWidth = 128; model.screenHeight = 160; model.systemProperties = "test";
27+
model.touchSize = 2; model.orientation = 3;
28+
assertTrue(ProfilesManager.saveConfig(model));
29+
assertEquals(240, ProfilesManager.loadConfig(dir).screenWidth);
30+
ProfilesManager.undoPreview(model);
31+
assertEquals(240, model.screenWidth); assertEquals(properties, model.systemProperties);
32+
assertEquals(0, model.touchSize); assertFalse(ProfilesManager.isPreview(model));
33+
}
34+
@Test public void repeatedPreviewKeepsOriginalBaseline() {
35+
ProfilesManager.beginPreview(model); model.screenWidth = 128;
36+
ProfilesManager.beginPreview(model); model.screenWidth = 176;
37+
ProfilesManager.undoPreview(model); assertEquals(240, model.screenWidth);
38+
}
39+
@Test public void keepCommitsAndNextPreviewUsesNewBaseline() {
40+
ProfilesManager.beginPreview(model); model.screenWidth = 128;
41+
assertTrue(ProfilesManager.keepPreview(model));
42+
assertEquals(128, ProfilesManager.loadConfig(dir).screenWidth);
43+
ProfilesManager.beginPreview(model); model.screenWidth = 176;
44+
ProfilesManager.undoPreview(model); assertEquals(128, model.screenWidth);
45+
}
46+
@Test public void launchDraftIsConsumedOnceAndCrashKeepsConfirmedProfile() throws Exception {
47+
ProfileModel draft = ProfilesManager.copy(model); draft.screenWidth = 128;
48+
SettingsTrial.stage(draft);
49+
assertEquals(240, ProfilesManager.loadConfig(dir).screenWidth);
50+
SettingsTrial.claim(model);
51+
assertEquals(128, model.screenWidth); assertTrue(ProfilesManager.isPreview(model));
52+
ProfileModel nextProcess = ProfilesManager.loadConfig(dir);
53+
SettingsTrial.claim(nextProcess);
54+
assertEquals(240, nextProcess.screenWidth); assertFalse(ProfilesManager.isPreview(nextProcess));
55+
}
56+
@Test public void draftCopyDoesNotAliasMappings() {
57+
model.ensureCustomKeyMappingProfile();
58+
ProfileModel copy = ProfilesManager.copy(model);
59+
copy.keyMappingProfiles.get(copy.activeKeyMappingProfile).name = "Draft only";
60+
assertNotEquals("Draft only", model.keyMappingProfiles.get(model.activeKeyMappingProfile).name);
61+
}
62+
@Test public void failedKeepRetainsUndo() {
63+
ProfilesManager.beginPreview(model); model.screenWidth = 128;
64+
File actual = model.dir; model.dir = new File(dir, "missing");
65+
assertFalse(ProfilesManager.keepPreview(model)); assertTrue(ProfilesManager.isPreview(model));
66+
model.dir = actual; ProfilesManager.undoPreview(model); assertEquals(240, model.screenWidth);
67+
}
68+
@Test public void malformedDraftLeavesConfirmedConfigAlone() throws Exception {
69+
Files.write(new File(dir, "settings-trial.json").toPath(), "bad json".getBytes());
70+
try { SettingsTrial.claim(model); fail(); } catch (java.io.IOException expected) { }
71+
assertEquals(240, model.screenWidth); assertFalse(ProfilesManager.isPreview(model));
72+
assertFalse(new File(dir, "settings-trial.json").exists());
73+
}
74+
@Test public void onlyEngineChangesNeedRestartForUndo() {
75+
ProfilesManager.beginPreview(model);
76+
model.screenWidth = 176; model.screenRotation = 180; model.touchLayout = 1;
77+
assertFalse(ProfilesManager.previewNeedsRestart(model));
78+
model.graphicsMode++;
79+
assertTrue(ProfilesManager.previewNeedsRestart(model));
80+
ProfilesManager.undoPreview(model);
81+
assertFalse(ProfilesManager.previewNeedsRestart(model));
82+
ProfilesManager.beginPreview(model); model.systemProperties = "different";
83+
assertTrue(ProfilesManager.previewNeedsRestart(model));
84+
}
85+
@Test public void trialsNeverTouchSiblingSaveFiles() throws Exception {
86+
File save = new File(dir, "test-save.rms");
87+
byte[] contents = new byte[]{0, 3, -1, 7};
88+
Files.write(save.toPath(), contents);
89+
ProfileModel draft = ProfilesManager.copy(model); draft.screenRotation = 180;
90+
SettingsTrial.stage(draft); SettingsTrial.claim(model); ProfilesManager.undoPreview(model);
91+
SettingsTrial.stage(draft); SettingsTrial.claim(model); assertTrue(ProfilesManager.keepPreview(model));
92+
assertArrayEquals(contents, Files.readAllBytes(save.toPath()));
93+
}
94+
@Test public void interruptedAtomicWriteRecoversConfirmedProfile() throws Exception {
95+
File config = new File(dir, Config.MIDLET_CONFIG_FILE);
96+
assertTrue(config.renameTo(new File(config.getPath() + ".bak")));
97+
Files.write(config.toPath(), "broken".getBytes());
98+
assertEquals(240, ProfilesManager.loadConfig(dir).screenWidth);
99+
}
100+
}

‎app/src/main/AndroidManifest.xml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@
124124
android:exported="true"
125125
android:screenOrientation="landscape"
126126
android:windowSoftInputMode="stateHidden" />
127+
<activity android:name=".config.GameSettingsActivity" android:exported="false"
128+
android:theme="@style/AppTheme.NoActionBar" />
127129
<activity
128130
android:name=".config.CompatibilityTestActivity"
129131
android:exported="false"

0 commit comments

Comments
 (0)