ReviewOS

also looking at this

craft-native/craft

refactor(android): one SharedPreferences helper, after the third caller turned out to be dead

#170
Merged chris wants to merge refactor/android-prefs into main
3 files +165 -113
packages/zig/src/bridge_android_shareditem.zigmodified+9-77
Changes to packages/zig/src/bridge_android_shareditem.zig
@@ -25,6 +25,7 @@
2525const std = ;
2626const jni = ;
2727const bridge_error = ;
28const prefs_api = ;
2829
2930const Jni = jni.Jni;
3031const jobject = jni.jobject;
@@ -38,9 +39,6 @@ pub const A = struct {
3839pub const resolve_global = "_craftSharedKeychainResolve";
3940pub const reject_global = "_craftSharedKeychainReject";
4041
41/// `Context.MODE_PRIVATE`, a compile-time constant the shim's DEX holds as 0.
42const mode_private: i32 = 0;
43
4442const prefix = "craft_shared";
4543
4644/// `if (group.isNotEmpty()) "craft_shared_$group" else "craft_shared"`.
@@ -97,17 +95,7 @@ pub fn valuePayload(allocator: std.mem.Allocator, key: []const u8, value: ?[]con
9795fn openPrefs(j: Jni, allocator: std.mem.Allocator, activity: jobject, group: []const u8) !jobject {
9896 const name = try prefsName(allocator, group);
9997 defer allocator.free(name);
100
101 const activity_cls = try j.objectClass(activity);
102 return j.callObjectMethodA(
103 activity,
104 try j.methodId(
105 activity_cls,
106 "getSharedPreferences",
107 "(Ljava/lang/String;I)Landroid/content/SharedPreferences;",
108 ),
109 &.{ .{ .l = try j.newStringUtf8(allocator, name) }, .{ .i = mode_private } },
110 );
98 return prefs_api.open(j, allocator, activity, name);
11199}
112100
113101/// `prefs.edit().putString(key, value).apply()`.
@@ -122,27 +110,9 @@ pub fn set(
122110 try j.pushLocalFrame(16);
123111 defer _ = j.popLocalFrame(null);
124112
125 const prefs = try openPrefs(j, allocator, activity, group);
126 const editor = try editorFor(j, prefs);
127 const editor_cls = try j.objectClass(editor);
128
129 _ = try j.callObjectMethodA(
130 editor,
131 try j.methodId(
132 editor_cls,
133 "putString",
134 "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;",
135 ),
136 &.{
137 .{ .l = try j.newStringUtf8(allocator, key) },
138 .{ .l = try j.newStringUtf8(allocator, value) },
139 },
140 );
141
142 // `apply` rather than `commit`: it writes on a background thread and
143 // returns void, so a failure is not observable here — which is exactly
144 // what the shim's resolve already promises regardless.
145 try j.callVoidMethodA(editor, try j.methodId(editor_cls, "apply", "()V"), &.{});
113 const editor = try prefs_api.edit(j, try openPrefs(j, allocator, activity, group));
114 try prefs_api.putString(j, allocator, editor, key, value);
115 try prefs_api.apply(j, editor);
146116}
147117
148118/// `prefs.edit().remove(key).apply()`.
@@ -156,20 +126,9 @@ pub fn remove(
156126 try j.pushLocalFrame(16);
157127 defer _ = j.popLocalFrame(null);
158128
159 const prefs = try openPrefs(j, allocator, activity, group);
160 const editor = try editorFor(j, prefs);
161 const editor_cls = try j.objectClass(editor);
162
163 _ = try j.callObjectMethodA(
164 editor,
165 try j.methodId(
166 editor_cls,
167 "remove",
168 "(Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;",
169 ),
170 &.{.{ .l = try j.newStringUtf8(allocator, key) }},
171 );
172 try j.callVoidMethodA(editor, try j.methodId(editor_cls, "apply", "()V"), &.{});
129 const editor = try prefs_api.edit(j, try openPrefs(j, allocator, activity, group));
130 try prefs_api.remove(j, allocator, editor, key);
131 try prefs_api.apply(j, editor);
173132}
174133
175134/// `prefs.getString(key, null)`, null included.
@@ -187,29 +146,7 @@ pub fn get(
187146 defer _ = j.popLocalFrame(null);
188147
189148 const prefs = try openPrefs(j, allocator, activity, group);
190 const value = try j.callObjectMethodA(
191 prefs,
192 try j.methodId(
193 try j.objectClass(prefs),
194 "getString",
195 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
196 ),
197 &.{ .{ .l = try j.newStringUtf8(allocator, key) }, .{ .l = null } },
198 );
199
200 if (value == null) return null;
201 return try j.stringToUtf8(allocator, value);
202}
203
204fn editorFor(j: Jni, prefs: jobject) !jobject {
205 return j.callObjectMethod(
206 prefs,
207 try j.methodId(
208 try j.objectClass(prefs),
209 "edit",
210 "()Landroid/content/SharedPreferences$Editor;",
211 ),
212 );
149 return prefs_api.getString(j, allocator, prefs, key);
213150}
214151
215152// =============================================================================
@@ -287,11 +224,6 @@ test "a key or value carrying a quote survives as JSON" {
287224 try testing.expect(parsed_success.value.object.get("success").?.bool);
288225}
289226
290test "MODE_PRIVATE is zero" {
291 // A compile-time constant in Java, so the shim's DEX holds the literal.
292 try testing.expectEqual(@as(i32, 0), mode_private);
293}
294
295227test "the actions and globals match the shim exactly" {
296228 try testing.expectEqualStrings("setSharedItem", A.set_shared_item);
297229 try testing.expectEqualStrings("getSharedItem", A.get_shared_item);