react-native-storage-inspector 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- package/dist/index.d.mts +56 -86
- package/dist/index.d.ts +56 -86
- package/dist/index.js +669 -755
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +650 -736
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React7 = require('react');
|
|
4
4
|
var reactNative = require('react-native');
|
|
5
5
|
|
|
6
6
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var React7__default = /*#__PURE__*/_interopDefault(React7);
|
|
9
9
|
|
|
10
10
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
11
11
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -41,7 +41,6 @@ function createMMKVAdapter(instance, name) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// src/adapters/async-storage.ts
|
|
44
|
-
var asyncStorage = null;
|
|
45
44
|
function getAsyncStorageFromRequire() {
|
|
46
45
|
try {
|
|
47
46
|
const mod = require("@react-native-async-storage/async-storage");
|
|
@@ -50,8 +49,8 @@ function getAsyncStorageFromRequire() {
|
|
|
50
49
|
return null;
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
|
-
function createAsyncStorageAdapter(
|
|
54
|
-
const getStorage = () =>
|
|
52
|
+
function createAsyncStorageAdapter() {
|
|
53
|
+
const getStorage = () => getAsyncStorageFromRequire();
|
|
55
54
|
return {
|
|
56
55
|
type: "async-storage",
|
|
57
56
|
name: "Async Storage",
|
|
@@ -82,7 +81,6 @@ function createAsyncStorageAdapter(instance) {
|
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
// src/adapters/keychain.ts
|
|
85
|
-
var keychain = null;
|
|
86
84
|
function getKeychainFromRequire() {
|
|
87
85
|
try {
|
|
88
86
|
return require("react-native-keychain");
|
|
@@ -90,14 +88,14 @@ function getKeychainFromRequire() {
|
|
|
90
88
|
return null;
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
|
-
function createKeychainAdapter(
|
|
94
|
-
const getKc = () =>
|
|
91
|
+
function createKeychainAdapter() {
|
|
92
|
+
const getKc = () => getKeychainFromRequire();
|
|
95
93
|
return {
|
|
96
94
|
type: "keychain",
|
|
97
95
|
name: "Keychain",
|
|
98
96
|
async getAllKeys() {
|
|
99
97
|
const kc = getKc();
|
|
100
|
-
if (!kc) return [
|
|
98
|
+
if (!kc) return [];
|
|
101
99
|
const genericServices = [];
|
|
102
100
|
if (typeof kc.getAllGenericPasswordServices === "function") {
|
|
103
101
|
try {
|
|
@@ -106,42 +104,32 @@ function createKeychainAdapter(knownKeys = [], instance) {
|
|
|
106
104
|
} catch {
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
|
-
|
|
110
|
-
return Array.from(merged);
|
|
107
|
+
return genericServices;
|
|
111
108
|
},
|
|
112
109
|
async getItem(key) {
|
|
113
110
|
const kc = getKc();
|
|
114
|
-
if (!kc) return null;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
return creds2.password;
|
|
120
|
-
}
|
|
121
|
-
} catch {
|
|
111
|
+
if (!kc?.getGenericPassword) return null;
|
|
112
|
+
try {
|
|
113
|
+
const creds = await kc.getGenericPassword({ service: key });
|
|
114
|
+
if (creds && typeof creds === "object" && "password" in creds) {
|
|
115
|
+
return creds.password;
|
|
122
116
|
}
|
|
117
|
+
} catch {
|
|
123
118
|
}
|
|
124
|
-
|
|
125
|
-
return creds?.password ?? null;
|
|
119
|
+
return null;
|
|
126
120
|
},
|
|
127
121
|
async setItem(key, value) {
|
|
128
122
|
const kc = getKc();
|
|
129
|
-
if (!kc)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (result2 === false) throw new Error("Keychain set failed");
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const result = await kc.setInternetCredentials(key, key, value);
|
|
123
|
+
if (!kc?.setGenericPassword)
|
|
124
|
+
throw new Error("react-native-keychain is not available");
|
|
125
|
+
const result = await kc.setGenericPassword(key, value, { service: key });
|
|
136
126
|
if (result === false) throw new Error("Keychain set failed");
|
|
137
127
|
},
|
|
138
128
|
async removeItem(key) {
|
|
139
129
|
const kc = getKc();
|
|
140
|
-
if (!kc)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
await kc.resetInternetCredentials(key);
|
|
130
|
+
if (!kc?.resetGenericPassword)
|
|
131
|
+
throw new Error("react-native-keychain is not available");
|
|
132
|
+
await kc.resetGenericPassword({ service: key });
|
|
145
133
|
},
|
|
146
134
|
isAvailable() {
|
|
147
135
|
return getKc() !== null;
|
|
@@ -149,8 +137,20 @@ function createKeychainAdapter(knownKeys = [], instance) {
|
|
|
149
137
|
};
|
|
150
138
|
}
|
|
151
139
|
|
|
140
|
+
// src/utils.ts
|
|
141
|
+
function parsePersistedKeys(raw) {
|
|
142
|
+
if (raw == null || raw === "") return [];
|
|
143
|
+
try {
|
|
144
|
+
const parsed = JSON.parse(raw);
|
|
145
|
+
if (!Array.isArray(parsed)) return [];
|
|
146
|
+
return parsed.filter((item) => typeof item === "string");
|
|
147
|
+
} catch {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
152
|
// src/adapters/secure-store.ts
|
|
153
|
-
var
|
|
153
|
+
var PERSISTED_KEYS_STORAGE_KEY = "__storage_inspector_secure_store_keys__";
|
|
154
154
|
function getSecureStoreFromRequire() {
|
|
155
155
|
try {
|
|
156
156
|
return require("expo-secure-store");
|
|
@@ -158,13 +158,17 @@ function getSecureStoreFromRequire() {
|
|
|
158
158
|
return null;
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
function createSecureStoreAdapter(knownKeys = []
|
|
162
|
-
const getStore = () =>
|
|
161
|
+
function createSecureStoreAdapter(knownKeys = []) {
|
|
162
|
+
const getStore = () => getSecureStoreFromRequire();
|
|
163
163
|
return {
|
|
164
164
|
type: "expo-secure-store",
|
|
165
165
|
name: "Secure Store",
|
|
166
166
|
async getAllKeys() {
|
|
167
|
-
|
|
167
|
+
const store = getStore();
|
|
168
|
+
if (!store) return [];
|
|
169
|
+
const persistedKeysString = await store.getItemAsync(PERSISTED_KEYS_STORAGE_KEY);
|
|
170
|
+
const persistedKeys = parsePersistedKeys(persistedKeysString);
|
|
171
|
+
return [.../* @__PURE__ */ new Set([...knownKeys, ...persistedKeys])];
|
|
168
172
|
},
|
|
169
173
|
async getItem(key) {
|
|
170
174
|
const store = getStore();
|
|
@@ -175,11 +179,26 @@ function createSecureStoreAdapter(knownKeys = [], instance) {
|
|
|
175
179
|
const store = getStore();
|
|
176
180
|
if (!store) throw new Error("expo-secure-store is not available");
|
|
177
181
|
await store.setItemAsync(key, value);
|
|
182
|
+
if (key === PERSISTED_KEYS_STORAGE_KEY) return;
|
|
183
|
+
const persistedKeysString = await store.getItemAsync(PERSISTED_KEYS_STORAGE_KEY);
|
|
184
|
+
const persistedKeys = parsePersistedKeys(persistedKeysString);
|
|
185
|
+
const newPersistedKeys = [.../* @__PURE__ */ new Set([...persistedKeys, key])];
|
|
186
|
+
await store.setItemAsync(
|
|
187
|
+
PERSISTED_KEYS_STORAGE_KEY,
|
|
188
|
+
JSON.stringify(newPersistedKeys)
|
|
189
|
+
);
|
|
178
190
|
},
|
|
179
191
|
async removeItem(key) {
|
|
180
192
|
const store = getStore();
|
|
181
193
|
if (!store) throw new Error("expo-secure-store is not available");
|
|
182
194
|
await store.deleteItemAsync(key);
|
|
195
|
+
const persistedKeysString = await store.getItemAsync(PERSISTED_KEYS_STORAGE_KEY);
|
|
196
|
+
const persistedKeys = parsePersistedKeys(persistedKeysString);
|
|
197
|
+
const newPersistedKeys = persistedKeys.filter((k) => k !== key);
|
|
198
|
+
await store.setItemAsync(
|
|
199
|
+
PERSISTED_KEYS_STORAGE_KEY,
|
|
200
|
+
JSON.stringify(newPersistedKeys)
|
|
201
|
+
);
|
|
183
202
|
},
|
|
184
203
|
isAvailable() {
|
|
185
204
|
return getStore() !== null;
|
|
@@ -187,10 +206,10 @@ function createSecureStoreAdapter(knownKeys = [], instance) {
|
|
|
187
206
|
};
|
|
188
207
|
}
|
|
189
208
|
function useStorageItems(adapter) {
|
|
190
|
-
const [items, setItems] =
|
|
191
|
-
const [loading, setLoading] =
|
|
192
|
-
const [error, setError] =
|
|
193
|
-
const refresh =
|
|
209
|
+
const [items, setItems] = React7.useState([]);
|
|
210
|
+
const [loading, setLoading] = React7.useState(true);
|
|
211
|
+
const [error, setError] = React7.useState(null);
|
|
212
|
+
const refresh = React7.useCallback(async () => {
|
|
194
213
|
if (!adapter || !adapter.isAvailable()) {
|
|
195
214
|
setItems([]);
|
|
196
215
|
setLoading(false);
|
|
@@ -203,7 +222,8 @@ function useStorageItems(adapter) {
|
|
|
203
222
|
const pairs = [];
|
|
204
223
|
for (const key of keys) {
|
|
205
224
|
const value = await adapter.getItem(key);
|
|
206
|
-
|
|
225
|
+
if (value === null) continue;
|
|
226
|
+
pairs.push({ key, value });
|
|
207
227
|
}
|
|
208
228
|
setItems(pairs);
|
|
209
229
|
} catch (e) {
|
|
@@ -213,7 +233,7 @@ function useStorageItems(adapter) {
|
|
|
213
233
|
setLoading(false);
|
|
214
234
|
}
|
|
215
235
|
}, [adapter]);
|
|
216
|
-
|
|
236
|
+
React7.useEffect(() => {
|
|
217
237
|
refresh();
|
|
218
238
|
}, [refresh]);
|
|
219
239
|
return { items, loading, error, refresh };
|
|
@@ -230,7 +250,8 @@ var theme = {
|
|
|
230
250
|
text: "#000000",
|
|
231
251
|
textSecondary: "#666666",
|
|
232
252
|
textMuted: "#999999",
|
|
233
|
-
inverted: "#ffffff"
|
|
253
|
+
inverted: "#ffffff",
|
|
254
|
+
overlayBackdrop: "rgba(0,0,0,0.5)"
|
|
234
255
|
}
|
|
235
256
|
};
|
|
236
257
|
|
|
@@ -251,15 +272,11 @@ var ROTATION = {
|
|
|
251
272
|
chevronDown: "90deg",
|
|
252
273
|
chevronUp: "-90deg"
|
|
253
274
|
};
|
|
254
|
-
function Icon({
|
|
255
|
-
name,
|
|
256
|
-
size = 20,
|
|
257
|
-
tintColor = theme.colors.text,
|
|
258
|
-
iconStyle
|
|
259
|
-
}) {
|
|
275
|
+
function Icon(props) {
|
|
276
|
+
const { name, size = 20, tintColor = theme.colors.text, iconStyle } = props;
|
|
260
277
|
const glyph = GLYPHS[name] ?? "?";
|
|
261
278
|
const rotation = ROTATION[name];
|
|
262
|
-
return /* @__PURE__ */
|
|
279
|
+
return /* @__PURE__ */ React7__default.default.createElement(
|
|
263
280
|
reactNative.Text,
|
|
264
281
|
{
|
|
265
282
|
style: [
|
|
@@ -282,7 +299,6 @@ var { width: SCREEN_WIDTH } = reactNative.Dimensions.get("window");
|
|
|
282
299
|
var LAYOUT = {
|
|
283
300
|
padding: 16,
|
|
284
301
|
fontSize: 14,
|
|
285
|
-
headerHeight: 52,
|
|
286
302
|
rowMinHeight: 48,
|
|
287
303
|
sectionHeaderHeight: 48,
|
|
288
304
|
iconSize: 20,
|
|
@@ -296,333 +312,244 @@ var LAYOUT = {
|
|
|
296
312
|
sectionRadius: 4,
|
|
297
313
|
screenWidth: SCREEN_WIDTH
|
|
298
314
|
};
|
|
299
|
-
|
|
315
|
+
|
|
316
|
+
// src/components/IconButton.tsx
|
|
317
|
+
function IconButton(props) {
|
|
318
|
+
const {
|
|
319
|
+
name,
|
|
320
|
+
onPress,
|
|
321
|
+
size = LAYOUT.iconSize,
|
|
322
|
+
tintColor = theme.colors.text,
|
|
323
|
+
disabled = false,
|
|
324
|
+
hitSlop = LAYOUT.hitSlop,
|
|
325
|
+
style,
|
|
326
|
+
activeOpacity = 0.6
|
|
327
|
+
} = props;
|
|
328
|
+
return /* @__PURE__ */ React7__default.default.createElement(
|
|
329
|
+
reactNative.TouchableOpacity,
|
|
330
|
+
{
|
|
331
|
+
style: [styles2.iconButton, style],
|
|
332
|
+
onPress,
|
|
333
|
+
disabled,
|
|
334
|
+
hitSlop,
|
|
335
|
+
activeOpacity
|
|
336
|
+
},
|
|
337
|
+
/* @__PURE__ */ React7__default.default.createElement(
|
|
338
|
+
Icon,
|
|
339
|
+
{
|
|
340
|
+
name,
|
|
341
|
+
size,
|
|
342
|
+
tintColor: disabled ? theme.colors.textMuted : tintColor
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
}
|
|
300
347
|
var styles2 = reactNative.StyleSheet.create({
|
|
301
|
-
|
|
348
|
+
iconButton: {
|
|
349
|
+
width: LAYOUT.iconButtonSize,
|
|
350
|
+
height: LAYOUT.iconButtonSize,
|
|
351
|
+
alignItems: "center",
|
|
352
|
+
justifyContent: "center"
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// src/strings.ts
|
|
357
|
+
var strings = {
|
|
358
|
+
// StorageInspector
|
|
359
|
+
noAdapterAvailable: "No storage adapter available. Install at least one of: react-native-mmkv, @react-native-async-storage/async-storage, react-native-keychain, expo-secure-store",
|
|
360
|
+
// StorageSection
|
|
361
|
+
keychainHint: "No generic password items yet. Add a key using + above.",
|
|
362
|
+
secureStoreHint: "Secure Store has no list API. Pass secureStoreKeys prop with known keys, or add a key using + above.",
|
|
363
|
+
loading: "Loading\u2026",
|
|
364
|
+
noItems: "No items",
|
|
365
|
+
valueLabel: "Value",
|
|
366
|
+
charCount: (n) => n === 1 ? "1 char" : `${n} chars`,
|
|
367
|
+
deleteItemTitle: (key) => `Delete ${key}?`,
|
|
368
|
+
deleteItemMessage: (key) => `This will permanently delete the ${key} storage item. Do you wish to continue?`,
|
|
369
|
+
clearAllTitle: (name) => `Clear All ${name}?`,
|
|
370
|
+
clearAllMessage: (count, name) => `This will permanently delete all ${count} ${name} items. Do you wish to continue?`,
|
|
371
|
+
// StorageList
|
|
372
|
+
storageNotAvailable: "This storage is not available.",
|
|
373
|
+
keychainHintShort: "No items yet. Add a key below.",
|
|
374
|
+
edit: "Edit",
|
|
375
|
+
delete: "Delete",
|
|
376
|
+
addItem: "Add item",
|
|
377
|
+
// ItemForm
|
|
378
|
+
keyRequired: "Key is required",
|
|
379
|
+
saveFailed: "Save failed",
|
|
380
|
+
editItemTitle: (key) => `Edit ${key}`,
|
|
381
|
+
addItemTitle: (storageName) => `Add ${storageName} Item`,
|
|
382
|
+
storageTypeLabel: (name) => `Storage Type: ${name}`,
|
|
383
|
+
keyLabel: "Key",
|
|
384
|
+
enterKeyPlaceholder: "Enter key",
|
|
385
|
+
enterValuePlaceholder: "Enter value",
|
|
386
|
+
cancel: "Cancel",
|
|
387
|
+
saving: "Saving\u2026",
|
|
388
|
+
save: "Save",
|
|
389
|
+
add: "Add",
|
|
390
|
+
// ConfirmModal defaults
|
|
391
|
+
confirmDelete: "Yes, delete",
|
|
392
|
+
cancelKeep: "No, keep it"
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// src/components/ItemForm.tsx
|
|
396
|
+
function ItemForm(props) {
|
|
397
|
+
const { visible, storageName, editingItem, onSave, onCancel } = props;
|
|
398
|
+
const [key, setKey] = React7.useState("");
|
|
399
|
+
const [value, setValue] = React7.useState("");
|
|
400
|
+
const [saving, setSaving] = React7.useState(false);
|
|
401
|
+
const [error, setError] = React7.useState(null);
|
|
402
|
+
const isEdit = editingItem !== null;
|
|
403
|
+
React7.useEffect(() => {
|
|
404
|
+
if (visible) {
|
|
405
|
+
setKey(editingItem?.key ?? "");
|
|
406
|
+
setValue(editingItem?.value ?? "");
|
|
407
|
+
setError(null);
|
|
408
|
+
}
|
|
409
|
+
}, [visible, editingItem]);
|
|
410
|
+
const handleSubmit = async () => {
|
|
411
|
+
const k = key.trim();
|
|
412
|
+
if (!k) {
|
|
413
|
+
setError(strings.keyRequired);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
setSaving(true);
|
|
417
|
+
setError(null);
|
|
418
|
+
try {
|
|
419
|
+
await onSave(k, value);
|
|
420
|
+
onCancel();
|
|
421
|
+
} catch (e) {
|
|
422
|
+
setError(e instanceof Error ? e.message : strings.saveFailed);
|
|
423
|
+
} finally {
|
|
424
|
+
setSaving(false);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
const title = isEdit ? strings.editItemTitle(editingItem?.key ?? "") : strings.addItemTitle(storageName);
|
|
428
|
+
return /* @__PURE__ */ React7__default.default.createElement(reactNative.Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onCancel }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles3.formOverlay }, /* @__PURE__ */ React7__default.default.createElement(
|
|
429
|
+
reactNative.TouchableOpacity,
|
|
430
|
+
{
|
|
431
|
+
style: { flex: 1, width: "100%" },
|
|
432
|
+
activeOpacity: 1,
|
|
433
|
+
onPress: onCancel
|
|
434
|
+
}
|
|
435
|
+
), /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles3.formModal }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles3.formHeader }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles3.formTitle, numberOfLines: 1 }, title), /* @__PURE__ */ React7__default.default.createElement(
|
|
436
|
+
IconButton,
|
|
437
|
+
{
|
|
438
|
+
name: "close",
|
|
439
|
+
onPress: onCancel,
|
|
440
|
+
size: 24,
|
|
441
|
+
tintColor: theme.colors.textSecondary,
|
|
442
|
+
style: styles3.formCloseButton,
|
|
443
|
+
hitSlop: LAYOUT.hitSlopLarge
|
|
444
|
+
}
|
|
445
|
+
)), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles3.formStorageType }, strings.storageTypeLabel(storageName)), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles3.formLabel }, strings.keyLabel), /* @__PURE__ */ React7__default.default.createElement(
|
|
446
|
+
reactNative.TextInput,
|
|
447
|
+
{
|
|
448
|
+
style: [styles3.formInput, isEdit && styles3.formInputDisabled],
|
|
449
|
+
value: key,
|
|
450
|
+
onChangeText: setKey,
|
|
451
|
+
placeholder: strings.enterKeyPlaceholder,
|
|
452
|
+
placeholderTextColor: theme.colors.textMuted,
|
|
453
|
+
editable: !isEdit,
|
|
454
|
+
autoCapitalize: "none",
|
|
455
|
+
multiline: true
|
|
456
|
+
}
|
|
457
|
+
), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles3.formLabel }, strings.valueLabel), /* @__PURE__ */ React7__default.default.createElement(
|
|
458
|
+
reactNative.TextInput,
|
|
459
|
+
{
|
|
460
|
+
style: styles3.formInput,
|
|
461
|
+
value,
|
|
462
|
+
onChangeText: setValue,
|
|
463
|
+
placeholder: strings.enterValuePlaceholder,
|
|
464
|
+
placeholderTextColor: theme.colors.textMuted,
|
|
465
|
+
multiline: true,
|
|
466
|
+
numberOfLines: 3
|
|
467
|
+
}
|
|
468
|
+
), error ? /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: [styles3.errorText, { marginBottom: 12 }] }, error) : null, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles3.formActions }, /* @__PURE__ */ React7__default.default.createElement(
|
|
469
|
+
reactNative.TouchableOpacity,
|
|
470
|
+
{
|
|
471
|
+
style: [styles3.formButton, styles3.formButtonCancel],
|
|
472
|
+
onPress: onCancel,
|
|
473
|
+
disabled: saving
|
|
474
|
+
},
|
|
475
|
+
/* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: [styles3.formButtonText, styles3.formButtonTextCancel] }, strings.cancel)
|
|
476
|
+
), /* @__PURE__ */ React7__default.default.createElement(
|
|
477
|
+
reactNative.TouchableOpacity,
|
|
478
|
+
{
|
|
479
|
+
style: [styles3.formButton, styles3.formButtonSubmit],
|
|
480
|
+
onPress: handleSubmit,
|
|
481
|
+
disabled: saving
|
|
482
|
+
},
|
|
483
|
+
/* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: [styles3.formButtonText, styles3.formButtonTextSubmit] }, saving ? strings.saving : isEdit ? strings.save : strings.add)
|
|
484
|
+
)))));
|
|
485
|
+
}
|
|
486
|
+
var { colors } = theme;
|
|
487
|
+
var styles3 = reactNative.StyleSheet.create({
|
|
488
|
+
formOverlay: {
|
|
302
489
|
flex: 1,
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
content: {
|
|
307
|
-
flex: 1
|
|
490
|
+
backgroundColor: colors.overlayBackdrop,
|
|
491
|
+
justifyContent: "flex-end",
|
|
492
|
+
alignItems: "center"
|
|
308
493
|
},
|
|
309
|
-
|
|
310
|
-
|
|
494
|
+
formModal: {
|
|
495
|
+
width: "100%",
|
|
496
|
+
maxWidth: LAYOUT.screenWidth,
|
|
497
|
+
backgroundColor: colors.background,
|
|
498
|
+
borderTopLeftRadius: LAYOUT.modalRadius,
|
|
499
|
+
borderTopRightRadius: LAYOUT.modalRadius,
|
|
500
|
+
padding: LAYOUT.padding,
|
|
501
|
+
paddingBottom: LAYOUT.padding + 34
|
|
311
502
|
},
|
|
312
|
-
|
|
313
|
-
height: LAYOUT.headerHeight,
|
|
503
|
+
formHeader: {
|
|
314
504
|
flexDirection: "row",
|
|
315
505
|
alignItems: "center",
|
|
316
506
|
justifyContent: "space-between",
|
|
317
|
-
|
|
318
|
-
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
319
|
-
borderBottomColor: colors.border,
|
|
320
|
-
backgroundColor: colors.background
|
|
321
|
-
},
|
|
322
|
-
headerLeft: {
|
|
323
|
-
minWidth: 44,
|
|
324
|
-
alignItems: "flex-start"
|
|
325
|
-
},
|
|
326
|
-
headerCenter: {
|
|
327
|
-
flex: 1,
|
|
328
|
-
alignItems: "center",
|
|
329
|
-
justifyContent: "center"
|
|
330
|
-
},
|
|
331
|
-
headerRight: {
|
|
332
|
-
minWidth: 44,
|
|
333
|
-
alignItems: "flex-end"
|
|
334
|
-
},
|
|
335
|
-
sectionHeaderLabelWrap: {
|
|
336
|
-
flex: 1
|
|
507
|
+
marginBottom: LAYOUT.padding
|
|
337
508
|
},
|
|
338
|
-
|
|
509
|
+
formTitle: {
|
|
339
510
|
fontSize: 17,
|
|
340
511
|
fontWeight: "600",
|
|
341
|
-
color: colors.text
|
|
512
|
+
color: colors.text,
|
|
513
|
+
flex: 1
|
|
342
514
|
},
|
|
343
|
-
|
|
515
|
+
formCloseButton: {
|
|
344
516
|
width: 44,
|
|
345
517
|
height: 44,
|
|
346
|
-
alignItems: "
|
|
518
|
+
alignItems: "flex-end",
|
|
347
519
|
justifyContent: "center"
|
|
348
520
|
},
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
},
|
|
354
|
-
sectionHeader: {
|
|
355
|
-
height: LAYOUT.sectionHeaderHeight,
|
|
356
|
-
flexDirection: "row",
|
|
357
|
-
alignItems: "center",
|
|
358
|
-
paddingHorizontal: LAYOUT.padding,
|
|
359
|
-
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
360
|
-
borderBottomColor: colors.border,
|
|
361
|
-
backgroundColor: colors.backgroundSecondary,
|
|
362
|
-
marginTop: LAYOUT.padding,
|
|
363
|
-
marginHorizontal: LAYOUT.padding,
|
|
364
|
-
borderRadius: LAYOUT.sectionRadius
|
|
521
|
+
formStorageType: {
|
|
522
|
+
fontSize: 13,
|
|
523
|
+
color: colors.textSecondary,
|
|
524
|
+
marginBottom: 12
|
|
365
525
|
},
|
|
366
|
-
|
|
367
|
-
fontSize:
|
|
526
|
+
formLabel: {
|
|
527
|
+
fontSize: 12,
|
|
368
528
|
fontWeight: "600",
|
|
369
|
-
color: colors.text
|
|
370
|
-
},
|
|
371
|
-
sectionHeaderCount: {
|
|
372
529
|
color: colors.textSecondary,
|
|
373
|
-
|
|
530
|
+
marginBottom: 6
|
|
374
531
|
},
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
532
|
+
formInput: {
|
|
533
|
+
borderWidth: 1,
|
|
534
|
+
borderColor: colors.border,
|
|
535
|
+
borderRadius: 10,
|
|
536
|
+
padding: 12,
|
|
537
|
+
fontSize: LAYOUT.fontSize,
|
|
538
|
+
marginBottom: LAYOUT.padding,
|
|
539
|
+
color: colors.text,
|
|
540
|
+
backgroundColor: colors.background
|
|
379
541
|
},
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
alignItems: "center",
|
|
384
|
-
justifyContent: "center"
|
|
542
|
+
formInputDisabled: {
|
|
543
|
+
backgroundColor: colors.backgroundSecondary,
|
|
544
|
+
color: colors.textSecondary
|
|
385
545
|
},
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
546
|
+
formActions: {
|
|
547
|
+
flexDirection: "row",
|
|
548
|
+
justifyContent: "flex-end",
|
|
549
|
+
gap: 12,
|
|
550
|
+
marginTop: 8
|
|
391
551
|
},
|
|
392
|
-
|
|
393
|
-
minHeight: LAYOUT.rowMinHeight,
|
|
394
|
-
paddingHorizontal: LAYOUT.padding,
|
|
395
|
-
paddingVertical: 12,
|
|
396
|
-
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
397
|
-
borderBottomColor: colors.borderLight,
|
|
398
|
-
backgroundColor: colors.background,
|
|
399
|
-
marginHorizontal: LAYOUT.padding,
|
|
400
|
-
marginBottom: 4
|
|
401
|
-
},
|
|
402
|
-
itemRowCollapsed: {
|
|
403
|
-
flexDirection: "row",
|
|
404
|
-
alignItems: "center",
|
|
405
|
-
alignSelf: "stretch"
|
|
406
|
-
},
|
|
407
|
-
itemKey: {
|
|
408
|
-
flex: 1,
|
|
409
|
-
fontSize: LAYOUT.fontSize,
|
|
410
|
-
fontWeight: "500",
|
|
411
|
-
color: colors.text
|
|
412
|
-
},
|
|
413
|
-
itemChars: {
|
|
414
|
-
fontSize: 12,
|
|
415
|
-
color: colors.textSecondary,
|
|
416
|
-
marginTop: 2
|
|
417
|
-
},
|
|
418
|
-
itemRowActions: {
|
|
419
|
-
flexDirection: "row",
|
|
420
|
-
alignItems: "center",
|
|
421
|
-
marginLeft: LAYOUT.iconGap,
|
|
422
|
-
gap: LAYOUT.iconGap
|
|
423
|
-
},
|
|
424
|
-
itemRowExpanded: {
|
|
425
|
-
paddingTop: 4
|
|
426
|
-
},
|
|
427
|
-
valueBox: {
|
|
428
|
-
backgroundColor: colors.backgroundSecondary,
|
|
429
|
-
borderRadius: 8,
|
|
430
|
-
padding: 12,
|
|
431
|
-
marginTop: 8,
|
|
432
|
-
marginBottom: 8,
|
|
433
|
-
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
434
|
-
borderColor: colors.border
|
|
435
|
-
},
|
|
436
|
-
valueBoxLabel: {
|
|
437
|
-
fontSize: 11,
|
|
438
|
-
fontWeight: "600",
|
|
439
|
-
color: colors.textSecondary,
|
|
440
|
-
marginBottom: 4,
|
|
441
|
-
textTransform: "uppercase"
|
|
442
|
-
},
|
|
443
|
-
valueBoxText: {
|
|
444
|
-
fontSize: LAYOUT.fontSize,
|
|
445
|
-
color: colors.text
|
|
446
|
-
},
|
|
447
|
-
empty: {
|
|
448
|
-
padding: LAYOUT.padding * 2,
|
|
449
|
-
alignItems: "center",
|
|
450
|
-
marginHorizontal: LAYOUT.padding
|
|
451
|
-
},
|
|
452
|
-
emptyText: {
|
|
453
|
-
fontSize: LAYOUT.fontSize,
|
|
454
|
-
color: colors.textMuted
|
|
455
|
-
},
|
|
456
|
-
loading: {
|
|
457
|
-
padding: LAYOUT.padding * 2,
|
|
458
|
-
alignItems: "center",
|
|
459
|
-
marginHorizontal: LAYOUT.padding
|
|
460
|
-
},
|
|
461
|
-
loadingText: {
|
|
462
|
-
fontSize: LAYOUT.fontSize,
|
|
463
|
-
color: colors.textSecondary
|
|
464
|
-
},
|
|
465
|
-
error: {
|
|
466
|
-
padding: LAYOUT.padding,
|
|
467
|
-
backgroundColor: colors.backgroundTertiary,
|
|
468
|
-
marginHorizontal: LAYOUT.padding,
|
|
469
|
-
marginVertical: 8,
|
|
470
|
-
borderRadius: 8
|
|
471
|
-
},
|
|
472
|
-
errorText: {
|
|
473
|
-
fontSize: LAYOUT.fontSize,
|
|
474
|
-
color: colors.text
|
|
475
|
-
},
|
|
476
|
-
keychainHint: {
|
|
477
|
-
padding: LAYOUT.padding,
|
|
478
|
-
marginHorizontal: LAYOUT.padding,
|
|
479
|
-
marginTop: 8,
|
|
480
|
-
marginBottom: 4,
|
|
481
|
-
backgroundColor: colors.backgroundSecondary,
|
|
482
|
-
borderRadius: 8
|
|
483
|
-
},
|
|
484
|
-
keychainHintText: {
|
|
485
|
-
fontSize: LAYOUT.fontSize - 1,
|
|
486
|
-
color: colors.textSecondary
|
|
487
|
-
},
|
|
488
|
-
list: {
|
|
489
|
-
flex: 1
|
|
490
|
-
},
|
|
491
|
-
listContent: {
|
|
492
|
-
flexGrow: 1,
|
|
493
|
-
paddingBottom: LAYOUT.fabSize + LAYOUT.padding + 20
|
|
494
|
-
},
|
|
495
|
-
row: {
|
|
496
|
-
flexDirection: "row",
|
|
497
|
-
alignItems: "center",
|
|
498
|
-
minHeight: LAYOUT.rowMinHeight,
|
|
499
|
-
paddingHorizontal: LAYOUT.padding,
|
|
500
|
-
paddingVertical: 12,
|
|
501
|
-
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
502
|
-
borderBottomColor: colors.borderLight,
|
|
503
|
-
backgroundColor: colors.background,
|
|
504
|
-
marginHorizontal: LAYOUT.padding
|
|
505
|
-
},
|
|
506
|
-
rowKey: {
|
|
507
|
-
flex: 1,
|
|
508
|
-
fontSize: LAYOUT.fontSize,
|
|
509
|
-
fontWeight: "500",
|
|
510
|
-
color: colors.text
|
|
511
|
-
},
|
|
512
|
-
rowValue: {
|
|
513
|
-
fontSize: LAYOUT.fontSize - 1,
|
|
514
|
-
color: colors.textSecondary
|
|
515
|
-
},
|
|
516
|
-
rowActions: {
|
|
517
|
-
flexDirection: "row",
|
|
518
|
-
alignItems: "center",
|
|
519
|
-
marginLeft: LAYOUT.iconGap,
|
|
520
|
-
gap: LAYOUT.iconGap
|
|
521
|
-
},
|
|
522
|
-
rowButton: {
|
|
523
|
-
paddingVertical: 8,
|
|
524
|
-
paddingHorizontal: 12
|
|
525
|
-
},
|
|
526
|
-
rowButtonText: {
|
|
527
|
-
fontSize: 14,
|
|
528
|
-
fontWeight: "600",
|
|
529
|
-
color: colors.text
|
|
530
|
-
},
|
|
531
|
-
rowButtonDanger: {
|
|
532
|
-
color: colors.text
|
|
533
|
-
},
|
|
534
|
-
addButton: {
|
|
535
|
-
position: "absolute",
|
|
536
|
-
bottom: LAYOUT.padding + 16,
|
|
537
|
-
right: LAYOUT.padding + 16,
|
|
538
|
-
width: LAYOUT.fabSize,
|
|
539
|
-
height: LAYOUT.fabSize,
|
|
540
|
-
borderRadius: LAYOUT.fabSize / 2,
|
|
541
|
-
backgroundColor: colors.text,
|
|
542
|
-
alignItems: "center",
|
|
543
|
-
justifyContent: "center"
|
|
544
|
-
},
|
|
545
|
-
addButtonText: {
|
|
546
|
-
fontSize: 16,
|
|
547
|
-
fontWeight: "600",
|
|
548
|
-
color: colors.inverted
|
|
549
|
-
},
|
|
550
|
-
fab: {
|
|
551
|
-
position: "absolute",
|
|
552
|
-
bottom: LAYOUT.padding + 16,
|
|
553
|
-
right: LAYOUT.padding + 16,
|
|
554
|
-
width: LAYOUT.fabSize,
|
|
555
|
-
height: LAYOUT.fabSize,
|
|
556
|
-
borderRadius: LAYOUT.fabSize / 2,
|
|
557
|
-
backgroundColor: colors.text,
|
|
558
|
-
alignItems: "center",
|
|
559
|
-
justifyContent: "center"
|
|
560
|
-
},
|
|
561
|
-
formOverlay: {
|
|
562
|
-
flex: 1,
|
|
563
|
-
backgroundColor: "rgba(0,0,0,0.5)",
|
|
564
|
-
justifyContent: "flex-end",
|
|
565
|
-
alignItems: "center"
|
|
566
|
-
},
|
|
567
|
-
formModal: {
|
|
568
|
-
width: "100%",
|
|
569
|
-
maxWidth: LAYOUT.screenWidth,
|
|
570
|
-
backgroundColor: colors.background,
|
|
571
|
-
borderTopLeftRadius: LAYOUT.modalRadius,
|
|
572
|
-
borderTopRightRadius: LAYOUT.modalRadius,
|
|
573
|
-
padding: LAYOUT.padding,
|
|
574
|
-
paddingBottom: LAYOUT.padding + 34
|
|
575
|
-
},
|
|
576
|
-
formHeader: {
|
|
577
|
-
flexDirection: "row",
|
|
578
|
-
alignItems: "center",
|
|
579
|
-
justifyContent: "space-between",
|
|
580
|
-
marginBottom: LAYOUT.padding
|
|
581
|
-
},
|
|
582
|
-
formTitle: {
|
|
583
|
-
fontSize: 17,
|
|
584
|
-
fontWeight: "600",
|
|
585
|
-
color: colors.text,
|
|
586
|
-
flex: 1
|
|
587
|
-
},
|
|
588
|
-
formCloseButton: {
|
|
589
|
-
width: 44,
|
|
590
|
-
height: 44,
|
|
591
|
-
alignItems: "flex-end",
|
|
592
|
-
justifyContent: "center"
|
|
593
|
-
},
|
|
594
|
-
formStorageType: {
|
|
595
|
-
fontSize: 13,
|
|
596
|
-
color: colors.textSecondary,
|
|
597
|
-
marginBottom: 12
|
|
598
|
-
},
|
|
599
|
-
formLabel: {
|
|
600
|
-
fontSize: 12,
|
|
601
|
-
fontWeight: "600",
|
|
602
|
-
color: colors.textSecondary,
|
|
603
|
-
marginBottom: 6
|
|
604
|
-
},
|
|
605
|
-
formInput: {
|
|
606
|
-
borderWidth: 1,
|
|
607
|
-
borderColor: colors.border,
|
|
608
|
-
borderRadius: 10,
|
|
609
|
-
padding: 12,
|
|
610
|
-
fontSize: LAYOUT.fontSize,
|
|
611
|
-
marginBottom: LAYOUT.padding,
|
|
612
|
-
color: colors.text,
|
|
613
|
-
backgroundColor: colors.background
|
|
614
|
-
},
|
|
615
|
-
formInputDisabled: {
|
|
616
|
-
backgroundColor: colors.backgroundSecondary,
|
|
617
|
-
color: colors.textSecondary
|
|
618
|
-
},
|
|
619
|
-
formActions: {
|
|
620
|
-
flexDirection: "row",
|
|
621
|
-
justifyContent: "flex-end",
|
|
622
|
-
gap: 12,
|
|
623
|
-
marginTop: 8
|
|
624
|
-
},
|
|
625
|
-
formButton: {
|
|
552
|
+
formButton: {
|
|
626
553
|
paddingVertical: 12,
|
|
627
554
|
paddingHorizontal: 20,
|
|
628
555
|
borderRadius: 10,
|
|
@@ -647,16 +574,79 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
647
574
|
formButtonTextSubmit: {
|
|
648
575
|
color: colors.inverted
|
|
649
576
|
},
|
|
577
|
+
errorText: {
|
|
578
|
+
fontSize: LAYOUT.fontSize,
|
|
579
|
+
color: colors.text
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
function ConfirmModal(props) {
|
|
583
|
+
const {
|
|
584
|
+
visible,
|
|
585
|
+
title,
|
|
586
|
+
message,
|
|
587
|
+
confirmLabel = strings.confirmDelete,
|
|
588
|
+
cancelLabel = strings.cancelKeep,
|
|
589
|
+
danger = true,
|
|
590
|
+
onConfirm,
|
|
591
|
+
onCancel
|
|
592
|
+
} = props;
|
|
593
|
+
return /* @__PURE__ */ React7__default.default.createElement(reactNative.Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onCancel }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles4.confirmOverlay }, /* @__PURE__ */ React7__default.default.createElement(
|
|
594
|
+
reactNative.TouchableOpacity,
|
|
595
|
+
{
|
|
596
|
+
style: { flex: 1, width: "100%" },
|
|
597
|
+
activeOpacity: 1,
|
|
598
|
+
onPress: onCancel
|
|
599
|
+
}
|
|
600
|
+
), /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles4.confirmModal }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles4.confirmHeader }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles4.confirmTitle }, title), /* @__PURE__ */ React7__default.default.createElement(
|
|
601
|
+
IconButton,
|
|
602
|
+
{
|
|
603
|
+
name: "close",
|
|
604
|
+
onPress: onCancel,
|
|
605
|
+
size: 24,
|
|
606
|
+
tintColor: theme.colors.textSecondary,
|
|
607
|
+
style: styles4.formCloseButton,
|
|
608
|
+
hitSlop: LAYOUT.hitSlopLarge
|
|
609
|
+
}
|
|
610
|
+
)), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles4.confirmMessage }, message), /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles4.confirmActions }, /* @__PURE__ */ React7__default.default.createElement(
|
|
611
|
+
reactNative.TouchableOpacity,
|
|
612
|
+
{
|
|
613
|
+
style: [styles4.confirmButton, styles4.confirmButtonSecondary],
|
|
614
|
+
onPress: onCancel
|
|
615
|
+
},
|
|
616
|
+
/* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: [styles4.confirmButtonText, styles4.confirmButtonTextSecondary] }, cancelLabel)
|
|
617
|
+
), /* @__PURE__ */ React7__default.default.createElement(
|
|
618
|
+
reactNative.TouchableOpacity,
|
|
619
|
+
{
|
|
620
|
+
style: [
|
|
621
|
+
styles4.confirmButton,
|
|
622
|
+
danger ? styles4.confirmButtonDanger : styles4.formButtonSubmit
|
|
623
|
+
],
|
|
624
|
+
onPress: onConfirm
|
|
625
|
+
},
|
|
626
|
+
/* @__PURE__ */ React7__default.default.createElement(
|
|
627
|
+
reactNative.Text,
|
|
628
|
+
{
|
|
629
|
+
style: [
|
|
630
|
+
styles4.confirmButtonText,
|
|
631
|
+
danger ? styles4.confirmButtonTextDanger : styles4.formButtonTextSubmit
|
|
632
|
+
]
|
|
633
|
+
},
|
|
634
|
+
confirmLabel
|
|
635
|
+
)
|
|
636
|
+
)))));
|
|
637
|
+
}
|
|
638
|
+
var { colors: colors2 } = theme;
|
|
639
|
+
var styles4 = reactNative.StyleSheet.create({
|
|
650
640
|
confirmOverlay: {
|
|
651
641
|
flex: 1,
|
|
652
|
-
backgroundColor:
|
|
642
|
+
backgroundColor: colors2.overlayBackdrop,
|
|
653
643
|
justifyContent: "flex-end",
|
|
654
644
|
alignItems: "center"
|
|
655
645
|
},
|
|
656
646
|
confirmModal: {
|
|
657
647
|
width: "100%",
|
|
658
648
|
maxWidth: LAYOUT.screenWidth,
|
|
659
|
-
backgroundColor:
|
|
649
|
+
backgroundColor: colors2.background,
|
|
660
650
|
borderTopLeftRadius: LAYOUT.modalRadius,
|
|
661
651
|
borderTopRightRadius: LAYOUT.modalRadius,
|
|
662
652
|
padding: LAYOUT.padding,
|
|
@@ -671,12 +661,18 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
671
661
|
confirmTitle: {
|
|
672
662
|
fontSize: 17,
|
|
673
663
|
fontWeight: "600",
|
|
674
|
-
color:
|
|
664
|
+
color: colors2.text,
|
|
675
665
|
flex: 1
|
|
676
666
|
},
|
|
667
|
+
formCloseButton: {
|
|
668
|
+
width: 44,
|
|
669
|
+
height: 44,
|
|
670
|
+
alignItems: "flex-end",
|
|
671
|
+
justifyContent: "center"
|
|
672
|
+
},
|
|
677
673
|
confirmMessage: {
|
|
678
674
|
fontSize: 15,
|
|
679
|
-
color:
|
|
675
|
+
color: colors2.textSecondary,
|
|
680
676
|
lineHeight: 22,
|
|
681
677
|
marginBottom: 20
|
|
682
678
|
},
|
|
@@ -690,295 +686,187 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
690
686
|
borderRadius: 10,
|
|
691
687
|
alignItems: "center"
|
|
692
688
|
},
|
|
693
|
-
confirmButtonSecondary: {
|
|
694
|
-
backgroundColor: "transparent",
|
|
695
|
-
borderWidth: 1,
|
|
696
|
-
borderColor:
|
|
697
|
-
},
|
|
698
|
-
confirmButtonDanger: {
|
|
699
|
-
backgroundColor:
|
|
700
|
-
},
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
},
|
|
708
|
-
|
|
709
|
-
color:
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
disabled,
|
|
730
|
-
hitSlop,
|
|
731
|
-
activeOpacity
|
|
732
|
-
},
|
|
733
|
-
/* @__PURE__ */ React6__default.default.createElement(
|
|
734
|
-
Icon,
|
|
735
|
-
{
|
|
736
|
-
name,
|
|
737
|
-
size,
|
|
738
|
-
tintColor: disabled ? theme.colors.textMuted : tintColor
|
|
739
|
-
}
|
|
740
|
-
)
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
// src/strings.ts
|
|
745
|
-
var strings = {
|
|
746
|
-
// StorageInspector
|
|
747
|
-
noAdapterAvailable: "No storage adapter available. Install at least one of: react-native-mmkv, @react-native-async-storage/async-storage, react-native-keychain, expo-secure-store",
|
|
748
|
-
// StorageSection
|
|
749
|
-
keychainHint: "No generic password items yet. Add a key using + above, or pass keychainKeys for internet credentials.",
|
|
750
|
-
secureStoreHint: "Secure Store has no list API. Pass secureStoreKeys prop with known keys, or add a key using + above.",
|
|
751
|
-
loading: "Loading\u2026",
|
|
752
|
-
noItems: "No items",
|
|
753
|
-
valueLabel: "Value",
|
|
754
|
-
emptyValue: "(empty)",
|
|
755
|
-
charCount: (n) => n === 1 ? "1 char" : `${n} chars`,
|
|
756
|
-
deleteItemTitle: (key) => `Delete ${key}?`,
|
|
757
|
-
deleteItemMessage: (key) => `This will permanently delete the ${key} storage item. Do you wish to continue?`,
|
|
758
|
-
clearAllTitle: (name) => `Clear All ${name}?`,
|
|
759
|
-
clearAllMessage: (count, name) => `This will permanently delete all ${count} ${name} items. Do you wish to continue?`,
|
|
760
|
-
// StorageList
|
|
761
|
-
storageNotAvailable: "This storage is not available.",
|
|
762
|
-
keychainHintShort: "No items yet. Add a key below, or pass keychainKeys for internet credentials.",
|
|
763
|
-
edit: "Edit",
|
|
764
|
-
delete: "Delete",
|
|
765
|
-
addItem: "Add item",
|
|
766
|
-
// ItemForm
|
|
767
|
-
keyRequired: "Key is required",
|
|
768
|
-
saveFailed: "Save failed",
|
|
769
|
-
editItemTitle: (key) => `Edit ${key}`,
|
|
770
|
-
addItemTitle: (storageName) => `Add ${storageName} Item`,
|
|
771
|
-
storageTypeLabel: (name) => `Storage Type: ${name}`,
|
|
772
|
-
keyLabel: "Key",
|
|
773
|
-
enterKeyPlaceholder: "Enter key",
|
|
774
|
-
enterValuePlaceholder: "Enter value",
|
|
775
|
-
cancel: "Cancel",
|
|
776
|
-
saving: "Saving\u2026",
|
|
777
|
-
save: "Save",
|
|
778
|
-
add: "Add",
|
|
779
|
-
// ConfirmModal defaults
|
|
780
|
-
confirmDelete: "Yes, delete",
|
|
781
|
-
cancelKeep: "No, keep it"
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
// src/components/ItemForm.tsx
|
|
785
|
-
function ItemForm({
|
|
786
|
-
visible,
|
|
787
|
-
storageName,
|
|
788
|
-
editingItem,
|
|
789
|
-
onSave,
|
|
790
|
-
onCancel
|
|
791
|
-
}) {
|
|
792
|
-
const [key, setKey] = React6.useState("");
|
|
793
|
-
const [value, setValue] = React6.useState("");
|
|
794
|
-
const [saving, setSaving] = React6.useState(false);
|
|
795
|
-
const [error, setError] = React6.useState(null);
|
|
796
|
-
const isEdit = editingItem !== null;
|
|
797
|
-
React6.useEffect(() => {
|
|
798
|
-
if (visible) {
|
|
799
|
-
setKey(editingItem?.key ?? "");
|
|
800
|
-
setValue(editingItem?.value ?? "");
|
|
801
|
-
setError(null);
|
|
802
|
-
}
|
|
803
|
-
}, [visible, editingItem]);
|
|
804
|
-
const handleSubmit = async () => {
|
|
805
|
-
const k = key.trim();
|
|
806
|
-
if (!k) {
|
|
807
|
-
setError(strings.keyRequired);
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
setSaving(true);
|
|
811
|
-
setError(null);
|
|
812
|
-
try {
|
|
813
|
-
await onSave(k, value);
|
|
814
|
-
onCancel();
|
|
815
|
-
} catch (e) {
|
|
816
|
-
setError(e instanceof Error ? e.message : strings.saveFailed);
|
|
817
|
-
} finally {
|
|
818
|
-
setSaving(false);
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
const title = isEdit ? strings.editItemTitle(editingItem?.key ?? "") : strings.addItemTitle(storageName);
|
|
822
|
-
return /* @__PURE__ */ React6__default.default.createElement(reactNative.Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onCancel }, /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.formOverlay }, /* @__PURE__ */ React6__default.default.createElement(
|
|
823
|
-
reactNative.TouchableOpacity,
|
|
824
|
-
{
|
|
825
|
-
style: { flex: 1, width: "100%" },
|
|
826
|
-
activeOpacity: 1,
|
|
827
|
-
onPress: onCancel
|
|
828
|
-
}
|
|
829
|
-
), /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.formModal }, /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.formHeader }, /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.formTitle, numberOfLines: 1 }, title), /* @__PURE__ */ React6__default.default.createElement(
|
|
830
|
-
IconButton,
|
|
831
|
-
{
|
|
832
|
-
name: "close",
|
|
833
|
-
onPress: onCancel,
|
|
834
|
-
size: 24,
|
|
835
|
-
tintColor: theme.colors.textSecondary,
|
|
836
|
-
style: styles2.formCloseButton,
|
|
837
|
-
hitSlop: LAYOUT.hitSlopLarge
|
|
838
|
-
}
|
|
839
|
-
)), /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.formStorageType }, strings.storageTypeLabel(storageName)), /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.formLabel }, strings.keyLabel), /* @__PURE__ */ React6__default.default.createElement(
|
|
840
|
-
reactNative.TextInput,
|
|
841
|
-
{
|
|
842
|
-
style: [styles2.formInput, isEdit && styles2.formInputDisabled],
|
|
843
|
-
value: key,
|
|
844
|
-
onChangeText: setKey,
|
|
845
|
-
placeholder: strings.enterKeyPlaceholder,
|
|
846
|
-
placeholderTextColor: theme.colors.textMuted,
|
|
847
|
-
editable: !isEdit,
|
|
848
|
-
autoCapitalize: "none",
|
|
849
|
-
multiline: true
|
|
850
|
-
}
|
|
851
|
-
), /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.formLabel }, strings.valueLabel), /* @__PURE__ */ React6__default.default.createElement(
|
|
852
|
-
reactNative.TextInput,
|
|
689
|
+
confirmButtonSecondary: {
|
|
690
|
+
backgroundColor: "transparent",
|
|
691
|
+
borderWidth: 1,
|
|
692
|
+
borderColor: colors2.text
|
|
693
|
+
},
|
|
694
|
+
confirmButtonDanger: {
|
|
695
|
+
backgroundColor: colors2.text
|
|
696
|
+
},
|
|
697
|
+
formButtonSubmit: {
|
|
698
|
+
backgroundColor: colors2.text
|
|
699
|
+
},
|
|
700
|
+
confirmButtonText: {
|
|
701
|
+
fontSize: 16,
|
|
702
|
+
fontWeight: "600"
|
|
703
|
+
},
|
|
704
|
+
confirmButtonTextSecondary: {
|
|
705
|
+
color: colors2.text
|
|
706
|
+
},
|
|
707
|
+
confirmButtonTextDanger: {
|
|
708
|
+
color: colors2.inverted
|
|
709
|
+
},
|
|
710
|
+
formButtonTextSubmit: {
|
|
711
|
+
color: colors2.inverted
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
function ItemRowActions(props) {
|
|
715
|
+
const {
|
|
716
|
+
item,
|
|
717
|
+
onCopy,
|
|
718
|
+
onEdit,
|
|
719
|
+
onDelete,
|
|
720
|
+
showChevron = false,
|
|
721
|
+
chevronDirection = "down"
|
|
722
|
+
} = props;
|
|
723
|
+
return /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles5.itemRowActions }, /* @__PURE__ */ React7__default.default.createElement(IconButton, { name: "copy", onPress: () => onCopy(item) }), /* @__PURE__ */ React7__default.default.createElement(IconButton, { name: "edit", onPress: () => onEdit(item) }), /* @__PURE__ */ React7__default.default.createElement(IconButton, { name: "trash", onPress: () => onDelete(item) }), showChevron && /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles5.iconSlot }, /* @__PURE__ */ React7__default.default.createElement(
|
|
724
|
+
Icon,
|
|
853
725
|
{
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
placeholder: strings.enterValuePlaceholder,
|
|
858
|
-
placeholderTextColor: theme.colors.textMuted,
|
|
859
|
-
multiline: true,
|
|
860
|
-
numberOfLines: 3
|
|
726
|
+
name: chevronDirection === "up" ? "chevronUp" : "chevronDown",
|
|
727
|
+
size: LAYOUT.chevronSize,
|
|
728
|
+
tintColor: theme.colors.text
|
|
861
729
|
}
|
|
862
|
-
)
|
|
863
|
-
reactNative.TouchableOpacity,
|
|
864
|
-
{
|
|
865
|
-
style: [styles2.formButton, styles2.formButtonCancel],
|
|
866
|
-
onPress: onCancel,
|
|
867
|
-
disabled: saving
|
|
868
|
-
},
|
|
869
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: [styles2.formButtonText, styles2.formButtonTextCancel] }, strings.cancel)
|
|
870
|
-
), /* @__PURE__ */ React6__default.default.createElement(
|
|
871
|
-
reactNative.TouchableOpacity,
|
|
872
|
-
{
|
|
873
|
-
style: [styles2.formButton, styles2.formButtonSubmit],
|
|
874
|
-
onPress: handleSubmit,
|
|
875
|
-
disabled: saving
|
|
876
|
-
},
|
|
877
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: [styles2.formButtonText, styles2.formButtonTextSubmit] }, saving ? strings.saving : isEdit ? strings.save : strings.add)
|
|
878
|
-
)))));
|
|
730
|
+
)));
|
|
879
731
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
732
|
+
var styles5 = reactNative.StyleSheet.create({
|
|
733
|
+
itemRowActions: {
|
|
734
|
+
flexDirection: "row",
|
|
735
|
+
alignItems: "center",
|
|
736
|
+
marginLeft: LAYOUT.iconGap,
|
|
737
|
+
gap: LAYOUT.iconGap
|
|
738
|
+
},
|
|
739
|
+
iconSlot: {
|
|
740
|
+
width: LAYOUT.iconButtonSize,
|
|
741
|
+
height: LAYOUT.iconButtonSize,
|
|
742
|
+
alignItems: "center",
|
|
743
|
+
justifyContent: "center"
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
// src/components/StorageList.tsx
|
|
748
|
+
function StorageList(props) {
|
|
749
|
+
const { item, onCopy, onEdit, onDelete } = props;
|
|
750
|
+
const [expandedKeys, setExpandedKeys] = React7.useState(/* @__PURE__ */ new Set());
|
|
751
|
+
const charCount = item.value.length;
|
|
752
|
+
const handleToggleExpanded = () => {
|
|
753
|
+
setExpandedKeys((prev) => {
|
|
754
|
+
const next = new Set(prev);
|
|
755
|
+
if (next.has(item.key)) next.delete(item.key);
|
|
756
|
+
else next.add(item.key);
|
|
757
|
+
return next;
|
|
758
|
+
});
|
|
892
759
|
};
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
style: { flex: 1, width: "100%" },
|
|
897
|
-
activeOpacity: 1,
|
|
898
|
-
onPress: onCancel
|
|
899
|
-
}
|
|
900
|
-
), /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.confirmModal }, /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.confirmHeader }, /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.confirmTitle }, title), /* @__PURE__ */ React6__default.default.createElement(
|
|
901
|
-
IconButton,
|
|
760
|
+
const isExpanded = expandedKeys.has(item.key);
|
|
761
|
+
return /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles6.itemRow }, /* @__PURE__ */ React7__default.default.createElement(reactNative.TouchableOpacity, { onPress: handleToggleExpanded, activeOpacity: 0.7 }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles6.itemRowCollapsed }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: { flex: 1 } }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles6.itemKey, numberOfLines: 1 }, item.key), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles6.itemChars }, strings.charCount(charCount))), !isExpanded ? /* @__PURE__ */ React7__default.default.createElement(
|
|
762
|
+
ItemRowActions,
|
|
902
763
|
{
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
764
|
+
item,
|
|
765
|
+
onCopy,
|
|
766
|
+
onEdit,
|
|
767
|
+
onDelete,
|
|
768
|
+
showChevron: true,
|
|
769
|
+
chevronDirection: "down"
|
|
909
770
|
}
|
|
910
|
-
)
|
|
911
|
-
reactNative.TouchableOpacity,
|
|
912
|
-
{
|
|
913
|
-
style: [styles2.confirmButton, styles2.confirmButtonSecondary],
|
|
914
|
-
onPress: onCancel
|
|
915
|
-
},
|
|
916
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: [styles2.confirmButtonText, styles2.confirmButtonTextSecondary] }, cancelLabel)
|
|
917
|
-
), /* @__PURE__ */ React6__default.default.createElement(
|
|
918
|
-
reactNative.TouchableOpacity,
|
|
919
|
-
{
|
|
920
|
-
style: [
|
|
921
|
-
styles2.confirmButton,
|
|
922
|
-
danger ? styles2.confirmButtonDanger : styles2.formButtonSubmit
|
|
923
|
-
],
|
|
924
|
-
onPress: handleConfirm
|
|
925
|
-
},
|
|
926
|
-
/* @__PURE__ */ React6__default.default.createElement(
|
|
927
|
-
reactNative.Text,
|
|
928
|
-
{
|
|
929
|
-
style: [
|
|
930
|
-
styles2.confirmButtonText,
|
|
931
|
-
danger ? styles2.confirmButtonTextDanger : styles2.formButtonTextSubmit
|
|
932
|
-
]
|
|
933
|
-
},
|
|
934
|
-
confirmLabel
|
|
935
|
-
)
|
|
936
|
-
)))));
|
|
937
|
-
}
|
|
938
|
-
function ItemRowActions({
|
|
939
|
-
item,
|
|
940
|
-
onCopy,
|
|
941
|
-
onEdit,
|
|
942
|
-
onDelete,
|
|
943
|
-
showChevron = false,
|
|
944
|
-
chevronDirection = "down"
|
|
945
|
-
}) {
|
|
946
|
-
return /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.itemRowActions }, /* @__PURE__ */ React6__default.default.createElement(IconButton, { name: "copy", onPress: () => onCopy(item) }), /* @__PURE__ */ React6__default.default.createElement(IconButton, { name: "edit", onPress: () => onEdit(item) }), /* @__PURE__ */ React6__default.default.createElement(IconButton, { name: "trash", onPress: () => onDelete(item) }), showChevron && /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.iconSlot }, /* @__PURE__ */ React6__default.default.createElement(
|
|
771
|
+
) : /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles6.iconSlot }, /* @__PURE__ */ React7__default.default.createElement(
|
|
947
772
|
Icon,
|
|
948
773
|
{
|
|
949
|
-
name:
|
|
774
|
+
name: "chevronUp",
|
|
950
775
|
size: LAYOUT.chevronSize,
|
|
951
776
|
tintColor: theme.colors.text
|
|
952
777
|
}
|
|
778
|
+
)))), isExpanded && /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles6.itemRowExpanded }, /* @__PURE__ */ React7__default.default.createElement(reactNative.TouchableOpacity, { onPress: () => onEdit(item), style: styles6.valueBox }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles6.valueBoxLabel }, strings.valueLabel), /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles6.valueBoxText, selectable: true }, item.value)), /* @__PURE__ */ React7__default.default.createElement(
|
|
779
|
+
ItemRowActions,
|
|
780
|
+
{
|
|
781
|
+
item,
|
|
782
|
+
onCopy,
|
|
783
|
+
onEdit,
|
|
784
|
+
onDelete
|
|
785
|
+
}
|
|
953
786
|
)));
|
|
954
787
|
}
|
|
788
|
+
var { colors: colors3 } = theme;
|
|
789
|
+
var styles6 = reactNative.StyleSheet.create({
|
|
790
|
+
itemRow: {
|
|
791
|
+
minHeight: LAYOUT.rowMinHeight,
|
|
792
|
+
paddingHorizontal: LAYOUT.padding,
|
|
793
|
+
paddingVertical: 12,
|
|
794
|
+
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
795
|
+
borderBottomColor: colors3.borderLight,
|
|
796
|
+
backgroundColor: colors3.background,
|
|
797
|
+
marginHorizontal: LAYOUT.padding,
|
|
798
|
+
marginBottom: 4
|
|
799
|
+
},
|
|
800
|
+
itemRowCollapsed: {
|
|
801
|
+
flexDirection: "row",
|
|
802
|
+
alignItems: "center",
|
|
803
|
+
alignSelf: "stretch"
|
|
804
|
+
},
|
|
805
|
+
itemKey: {
|
|
806
|
+
flex: 1,
|
|
807
|
+
fontSize: LAYOUT.fontSize,
|
|
808
|
+
fontWeight: "500",
|
|
809
|
+
color: colors3.text
|
|
810
|
+
},
|
|
811
|
+
itemChars: {
|
|
812
|
+
fontSize: 12,
|
|
813
|
+
color: colors3.textSecondary,
|
|
814
|
+
marginTop: 2
|
|
815
|
+
},
|
|
816
|
+
iconSlot: {
|
|
817
|
+
width: LAYOUT.iconButtonSize,
|
|
818
|
+
height: LAYOUT.iconButtonSize,
|
|
819
|
+
alignItems: "center",
|
|
820
|
+
justifyContent: "center"
|
|
821
|
+
},
|
|
822
|
+
itemRowExpanded: {
|
|
823
|
+
paddingTop: 4
|
|
824
|
+
},
|
|
825
|
+
valueBox: {
|
|
826
|
+
backgroundColor: colors3.backgroundSecondary,
|
|
827
|
+
borderRadius: 8,
|
|
828
|
+
padding: 12,
|
|
829
|
+
marginTop: 8,
|
|
830
|
+
marginBottom: 8,
|
|
831
|
+
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
832
|
+
borderColor: colors3.border
|
|
833
|
+
},
|
|
834
|
+
valueBoxLabel: {
|
|
835
|
+
fontSize: 11,
|
|
836
|
+
fontWeight: "600",
|
|
837
|
+
color: colors3.textSecondary,
|
|
838
|
+
marginBottom: 4,
|
|
839
|
+
textTransform: "uppercase"
|
|
840
|
+
},
|
|
841
|
+
valueBoxText: {
|
|
842
|
+
fontSize: LAYOUT.fontSize,
|
|
843
|
+
color: colors3.text
|
|
844
|
+
}
|
|
845
|
+
});
|
|
955
846
|
|
|
956
847
|
// src/components/StorageSection.tsx
|
|
957
|
-
function StorageSection({
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
refreshTrigger
|
|
966
|
-
}) {
|
|
848
|
+
function StorageSection(props) {
|
|
849
|
+
const {
|
|
850
|
+
adapter,
|
|
851
|
+
defaultExpanded = true,
|
|
852
|
+
expanded: expandedProp,
|
|
853
|
+
onToggleExpanded,
|
|
854
|
+
refreshTrigger
|
|
855
|
+
} = props;
|
|
967
856
|
const { items, loading, error, refresh } = useStorageItems(adapter);
|
|
968
|
-
const [expandedInternal, setExpandedInternal] =
|
|
857
|
+
const [expandedInternal, setExpandedInternal] = React7.useState(defaultExpanded);
|
|
969
858
|
const expanded = expandedProp !== void 0 ? expandedProp : expandedInternal;
|
|
970
859
|
const handleToggleExpanded = () => {
|
|
971
860
|
if (onToggleExpanded) onToggleExpanded();
|
|
972
861
|
else setExpandedInternal((p) => !p);
|
|
973
862
|
};
|
|
974
|
-
|
|
863
|
+
React7.useEffect(() => {
|
|
975
864
|
if (refreshTrigger !== void 0) refresh();
|
|
976
865
|
}, [refreshTrigger, refresh]);
|
|
977
|
-
const [
|
|
978
|
-
const [
|
|
979
|
-
const [
|
|
980
|
-
const [
|
|
981
|
-
const [clearAllVisible, setClearAllVisible] = React6.useState(false);
|
|
866
|
+
const [formVisible, setFormVisible] = React7.useState(false);
|
|
867
|
+
const [editingItem, setEditingItem] = React7.useState(null);
|
|
868
|
+
const [deleteItem, setDeleteItem] = React7.useState(null);
|
|
869
|
+
const [clearAllVisible, setClearAllVisible] = React7.useState(false);
|
|
982
870
|
const handleAdd = () => {
|
|
983
871
|
setEditingItem(null);
|
|
984
872
|
setFormVisible(true);
|
|
@@ -988,14 +876,7 @@ function StorageSection({
|
|
|
988
876
|
setFormVisible(true);
|
|
989
877
|
};
|
|
990
878
|
const handleSave = async (key, value) => {
|
|
991
|
-
const isNewKey = !editingItem || editingItem.key !== key;
|
|
992
879
|
await adapter.setItem(key, value);
|
|
993
|
-
if (adapter.type === "keychain" && isNewKey) {
|
|
994
|
-
onKeychainKeyAdded?.(key);
|
|
995
|
-
}
|
|
996
|
-
if (adapter.type === "expo-secure-store" && isNewKey) {
|
|
997
|
-
onSecureStoreKeyAdded?.(key);
|
|
998
|
-
}
|
|
999
880
|
await refresh();
|
|
1000
881
|
};
|
|
1001
882
|
const handleDeleteItem = async () => {
|
|
@@ -1023,25 +904,25 @@ function StorageSection({
|
|
|
1023
904
|
};
|
|
1024
905
|
const isKeychain = adapter.type === "keychain";
|
|
1025
906
|
const isSecureStore = adapter.type === "expo-secure-store";
|
|
1026
|
-
const showKeychainHint = isKeychain && items.length === 0
|
|
907
|
+
const showKeychainHint = isKeychain && items.length === 0;
|
|
1027
908
|
const showSecureStoreHint = isSecureStore && items.length === 0;
|
|
1028
909
|
if (!adapter.isAvailable()) return null;
|
|
1029
|
-
return /* @__PURE__ */
|
|
910
|
+
return /* @__PURE__ */ React7__default.default.createElement(React7__default.default.Fragment, null, /* @__PURE__ */ React7__default.default.createElement(
|
|
1030
911
|
reactNative.TouchableOpacity,
|
|
1031
912
|
{
|
|
1032
|
-
style:
|
|
913
|
+
style: styles7.sectionHeader,
|
|
1033
914
|
onPress: handleToggleExpanded,
|
|
1034
915
|
activeOpacity: 0.7
|
|
1035
916
|
},
|
|
1036
|
-
/* @__PURE__ */
|
|
1037
|
-
/* @__PURE__ */
|
|
917
|
+
/* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.sectionHeaderLabelWrap }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.sectionHeaderLabel }, adapter.name, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.sectionHeaderCount }, " (", items.length, ")"))),
|
|
918
|
+
/* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.storageRowActions }, /* @__PURE__ */ React7__default.default.createElement(IconButton, { name: "plus", onPress: handleAdd }), /* @__PURE__ */ React7__default.default.createElement(
|
|
1038
919
|
IconButton,
|
|
1039
920
|
{
|
|
1040
921
|
name: "trash",
|
|
1041
922
|
onPress: () => items.length > 0 && setClearAllVisible(true),
|
|
1042
923
|
disabled: items.length === 0
|
|
1043
924
|
}
|
|
1044
|
-
), /* @__PURE__ */
|
|
925
|
+
), /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.iconSlot }, /* @__PURE__ */ React7__default.default.createElement(
|
|
1045
926
|
Icon,
|
|
1046
927
|
{
|
|
1047
928
|
name: expanded ? "chevronUp" : "chevronDown",
|
|
@@ -1049,60 +930,16 @@ function StorageSection({
|
|
|
1049
930
|
tintColor: theme.colors.text
|
|
1050
931
|
}
|
|
1051
932
|
)))
|
|
1052
|
-
), expanded && /* @__PURE__ */
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
};
|
|
1063
|
-
return /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { key: item.key, style: styles2.itemRow }, /* @__PURE__ */ React6__default.default.createElement(
|
|
1064
|
-
reactNative.TouchableOpacity,
|
|
1065
|
-
{
|
|
1066
|
-
key: item.key,
|
|
1067
|
-
onPress: toggleItemExpanded,
|
|
1068
|
-
activeOpacity: 0.7
|
|
1069
|
-
},
|
|
1070
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.itemRowCollapsed }, /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: { flex: 1 } }, /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.itemKey, numberOfLines: 1 }, item.key), /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.itemChars }, strings.charCount(charCount))), !isItemExpanded ? /* @__PURE__ */ React6__default.default.createElement(
|
|
1071
|
-
ItemRowActions,
|
|
1072
|
-
{
|
|
1073
|
-
item,
|
|
1074
|
-
onCopy: handleCopy,
|
|
1075
|
-
onEdit: handleEdit,
|
|
1076
|
-
onDelete: setDeleteItem,
|
|
1077
|
-
showChevron: true,
|
|
1078
|
-
chevronDirection: "down"
|
|
1079
|
-
}
|
|
1080
|
-
) : /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.iconSlot }, /* @__PURE__ */ React6__default.default.createElement(
|
|
1081
|
-
Icon,
|
|
1082
|
-
{
|
|
1083
|
-
name: "chevronUp",
|
|
1084
|
-
size: LAYOUT.chevronSize,
|
|
1085
|
-
tintColor: theme.colors.text
|
|
1086
|
-
}
|
|
1087
|
-
)))
|
|
1088
|
-
), isItemExpanded && /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.itemRowExpanded }, /* @__PURE__ */ React6__default.default.createElement(
|
|
1089
|
-
reactNative.TouchableOpacity,
|
|
1090
|
-
{
|
|
1091
|
-
onPress: () => handleEdit(item),
|
|
1092
|
-
style: styles2.valueBox
|
|
1093
|
-
},
|
|
1094
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.valueBoxLabel }, strings.valueLabel),
|
|
1095
|
-
/* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.valueBoxText, selectable: true }, item.value || strings.emptyValue)
|
|
1096
|
-
), /* @__PURE__ */ React6__default.default.createElement(
|
|
1097
|
-
ItemRowActions,
|
|
1098
|
-
{
|
|
1099
|
-
item,
|
|
1100
|
-
onCopy: handleCopy,
|
|
1101
|
-
onEdit: handleEdit,
|
|
1102
|
-
onDelete: setDeleteItem
|
|
1103
|
-
}
|
|
1104
|
-
)));
|
|
1105
|
-
}), !loading && items.length === 0 && !showKeychainHint && !showSecureStoreHint ? /* @__PURE__ */ React6__default.default.createElement(reactNative.View, { style: styles2.empty }, /* @__PURE__ */ React6__default.default.createElement(reactNative.Text, { style: styles2.emptyText }, strings.noItems)) : null), /* @__PURE__ */ React6__default.default.createElement(
|
|
933
|
+
), expanded && /* @__PURE__ */ React7__default.default.createElement(React7__default.default.Fragment, null, showKeychainHint ? /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.keychainHint }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.keychainHintText }, strings.keychainHint)) : null, showSecureStoreHint ? /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.keychainHint }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.keychainHintText }, strings.secureStoreHint)) : null, error ? /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.error }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.errorText }, error)) : null, loading ? /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.loading }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.loadingText }, strings.loading)) : items.map((item) => /* @__PURE__ */ React7__default.default.createElement(
|
|
934
|
+
StorageList,
|
|
935
|
+
{
|
|
936
|
+
key: item.key,
|
|
937
|
+
item,
|
|
938
|
+
onCopy: handleCopy,
|
|
939
|
+
onEdit: handleEdit,
|
|
940
|
+
onDelete: setDeleteItem
|
|
941
|
+
}
|
|
942
|
+
)), !loading && items.length === 0 && !showKeychainHint && !showSecureStoreHint ? /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles7.empty }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles7.emptyText }, strings.noItems)) : null), /* @__PURE__ */ React7__default.default.createElement(
|
|
1106
943
|
ItemForm,
|
|
1107
944
|
{
|
|
1108
945
|
visible: formVisible,
|
|
@@ -1114,7 +951,7 @@ function StorageSection({
|
|
|
1114
951
|
setEditingItem(null);
|
|
1115
952
|
}
|
|
1116
953
|
}
|
|
1117
|
-
), /* @__PURE__ */
|
|
954
|
+
), /* @__PURE__ */ React7__default.default.createElement(
|
|
1118
955
|
ConfirmModal,
|
|
1119
956
|
{
|
|
1120
957
|
visible: deleteItem !== null,
|
|
@@ -1123,7 +960,7 @@ function StorageSection({
|
|
|
1123
960
|
onConfirm: handleDeleteItem,
|
|
1124
961
|
onCancel: () => setDeleteItem(null)
|
|
1125
962
|
}
|
|
1126
|
-
), /* @__PURE__ */
|
|
963
|
+
), /* @__PURE__ */ React7__default.default.createElement(
|
|
1127
964
|
ConfirmModal,
|
|
1128
965
|
{
|
|
1129
966
|
visible: clearAllVisible,
|
|
@@ -1134,89 +971,127 @@ function StorageSection({
|
|
|
1134
971
|
}
|
|
1135
972
|
));
|
|
1136
973
|
}
|
|
974
|
+
var { colors: colors4 } = theme;
|
|
975
|
+
var styles7 = reactNative.StyleSheet.create({
|
|
976
|
+
sectionHeader: {
|
|
977
|
+
height: LAYOUT.sectionHeaderHeight,
|
|
978
|
+
flexDirection: "row",
|
|
979
|
+
alignItems: "center",
|
|
980
|
+
paddingHorizontal: LAYOUT.padding,
|
|
981
|
+
borderBottomWidth: reactNative.StyleSheet.hairlineWidth,
|
|
982
|
+
borderBottomColor: colors4.border,
|
|
983
|
+
backgroundColor: colors4.backgroundSecondary,
|
|
984
|
+
marginTop: LAYOUT.padding,
|
|
985
|
+
marginHorizontal: LAYOUT.padding,
|
|
986
|
+
borderRadius: LAYOUT.sectionRadius
|
|
987
|
+
},
|
|
988
|
+
sectionHeaderLabelWrap: {
|
|
989
|
+
flex: 1
|
|
990
|
+
},
|
|
991
|
+
sectionHeaderLabel: {
|
|
992
|
+
fontSize: 15,
|
|
993
|
+
fontWeight: "600",
|
|
994
|
+
color: colors4.text
|
|
995
|
+
},
|
|
996
|
+
sectionHeaderCount: {
|
|
997
|
+
color: colors4.textSecondary,
|
|
998
|
+
fontWeight: "400"
|
|
999
|
+
},
|
|
1000
|
+
storageRowActions: {
|
|
1001
|
+
flexDirection: "row",
|
|
1002
|
+
alignItems: "center",
|
|
1003
|
+
gap: LAYOUT.iconGap
|
|
1004
|
+
},
|
|
1005
|
+
iconSlot: {
|
|
1006
|
+
width: LAYOUT.iconButtonSize,
|
|
1007
|
+
height: LAYOUT.iconButtonSize,
|
|
1008
|
+
alignItems: "center",
|
|
1009
|
+
justifyContent: "center"
|
|
1010
|
+
},
|
|
1011
|
+
keychainHint: {
|
|
1012
|
+
padding: LAYOUT.padding,
|
|
1013
|
+
marginHorizontal: LAYOUT.padding,
|
|
1014
|
+
marginTop: 8,
|
|
1015
|
+
marginBottom: 4,
|
|
1016
|
+
backgroundColor: colors4.backgroundSecondary,
|
|
1017
|
+
borderRadius: 8
|
|
1018
|
+
},
|
|
1019
|
+
keychainHintText: {
|
|
1020
|
+
fontSize: LAYOUT.fontSize - 1,
|
|
1021
|
+
color: colors4.textSecondary
|
|
1022
|
+
},
|
|
1023
|
+
error: {
|
|
1024
|
+
padding: LAYOUT.padding,
|
|
1025
|
+
backgroundColor: colors4.backgroundTertiary,
|
|
1026
|
+
marginHorizontal: LAYOUT.padding,
|
|
1027
|
+
marginVertical: 8,
|
|
1028
|
+
borderRadius: 8
|
|
1029
|
+
},
|
|
1030
|
+
errorText: {
|
|
1031
|
+
fontSize: LAYOUT.fontSize,
|
|
1032
|
+
color: colors4.text
|
|
1033
|
+
},
|
|
1034
|
+
loading: {
|
|
1035
|
+
padding: LAYOUT.padding * 2,
|
|
1036
|
+
alignItems: "center",
|
|
1037
|
+
marginHorizontal: LAYOUT.padding
|
|
1038
|
+
},
|
|
1039
|
+
loadingText: {
|
|
1040
|
+
fontSize: LAYOUT.fontSize,
|
|
1041
|
+
color: colors4.textSecondary
|
|
1042
|
+
},
|
|
1043
|
+
empty: {
|
|
1044
|
+
padding: LAYOUT.padding * 2,
|
|
1045
|
+
alignItems: "center",
|
|
1046
|
+
marginHorizontal: LAYOUT.padding
|
|
1047
|
+
},
|
|
1048
|
+
emptyText: {
|
|
1049
|
+
fontSize: LAYOUT.fontSize,
|
|
1050
|
+
color: colors4.textMuted
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1137
1053
|
|
|
1138
1054
|
// src/components/StorageInspector.tsx
|
|
1139
|
-
function StorageInspector({
|
|
1140
|
-
mmkvInstances = [],
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
secureStoreInstance,
|
|
1146
|
-
customAdapters = []
|
|
1147
|
-
}) {
|
|
1148
|
-
const [keychainKeysAdded, setKeychainKeysAdded] = React6.useState([]);
|
|
1149
|
-
const [secureStoreKeysAdded, setSecureStoreKeysAdded] = React6.useState([]);
|
|
1150
|
-
const [refreshKey, setRefreshKey] = React6.useState(0);
|
|
1151
|
-
const [refreshing, setRefreshing] = React6.useState(false);
|
|
1152
|
-
const [expandedIndices, setExpandedIndices] = React6.useState(() => /* @__PURE__ */ new Set([0]));
|
|
1153
|
-
const keychainKeys = React6.useMemo(
|
|
1154
|
-
() => [...keychainKeysProp ?? [], ...keychainKeysAdded],
|
|
1155
|
-
[keychainKeysProp, keychainKeysAdded]
|
|
1156
|
-
);
|
|
1157
|
-
const secureStoreKeys = React6.useMemo(
|
|
1158
|
-
() => [...secureStoreKeysProp ?? [], ...secureStoreKeysAdded],
|
|
1159
|
-
[secureStoreKeysProp, secureStoreKeysAdded]
|
|
1160
|
-
);
|
|
1161
|
-
const adapters = React6.useMemo(() => {
|
|
1055
|
+
function StorageInspector(props) {
|
|
1056
|
+
const { mmkvInstances = [], secureStoreKeys, customAdapters = [] } = props;
|
|
1057
|
+
const [refreshKey, setRefreshKey] = React7.useState(0);
|
|
1058
|
+
const [refreshing, setRefreshing] = React7.useState(false);
|
|
1059
|
+
const [expandedIndices, setExpandedIndices] = React7.useState(() => /* @__PURE__ */ new Set([0]));
|
|
1060
|
+
const adapters = React7.useMemo(() => {
|
|
1162
1061
|
const list = [];
|
|
1163
1062
|
mmkvInstances.forEach((inst, i) => {
|
|
1164
1063
|
list.push(
|
|
1165
1064
|
createMMKVAdapter(inst, mmkvInstances.length > 1 ? `MMKV ${i + 1}` : "MMKV")
|
|
1166
1065
|
);
|
|
1167
1066
|
});
|
|
1168
|
-
const asyncAdapter = createAsyncStorageAdapter(
|
|
1067
|
+
const asyncAdapter = createAsyncStorageAdapter();
|
|
1169
1068
|
if (asyncAdapter.isAvailable()) list.push(asyncAdapter);
|
|
1170
|
-
const keychainAdapter = createKeychainAdapter(
|
|
1069
|
+
const keychainAdapter = createKeychainAdapter();
|
|
1171
1070
|
if (keychainAdapter.isAvailable()) list.push(keychainAdapter);
|
|
1172
|
-
const secureStoreAdapter = createSecureStoreAdapter(
|
|
1173
|
-
secureStoreKeys,
|
|
1174
|
-
secureStoreInstance
|
|
1175
|
-
);
|
|
1071
|
+
const secureStoreAdapter = createSecureStoreAdapter(secureStoreKeys ?? []);
|
|
1176
1072
|
if (secureStoreAdapter.isAvailable()) list.push(secureStoreAdapter);
|
|
1177
1073
|
list.push(...customAdapters);
|
|
1178
1074
|
return list;
|
|
1179
|
-
}, [
|
|
1180
|
-
mmkvInstances,
|
|
1181
|
-
asyncStorageInstance,
|
|
1182
|
-
keychainKeys,
|
|
1183
|
-
keychainInstance,
|
|
1184
|
-
secureStoreKeys,
|
|
1185
|
-
secureStoreInstance,
|
|
1186
|
-
customAdapters
|
|
1187
|
-
]);
|
|
1188
|
-
const handleKeychainKeyAdded = (key) => {
|
|
1189
|
-
setKeychainKeysAdded(
|
|
1190
|
-
(prev) => prev.includes(key) ? prev : [...prev, key]
|
|
1191
|
-
);
|
|
1192
|
-
};
|
|
1193
|
-
const handleSecureStoreKeyAdded = (key) => {
|
|
1194
|
-
setSecureStoreKeysAdded(
|
|
1195
|
-
(prev) => prev.includes(key) ? prev : [...prev, key]
|
|
1196
|
-
);
|
|
1197
|
-
};
|
|
1075
|
+
}, [mmkvInstances, secureStoreKeys, customAdapters]);
|
|
1198
1076
|
const handleRefresh = () => {
|
|
1199
1077
|
setRefreshing(true);
|
|
1200
1078
|
setRefreshKey((k) => k + 1);
|
|
1201
1079
|
setTimeout(() => setRefreshing(false), 400);
|
|
1202
1080
|
};
|
|
1203
|
-
return /* @__PURE__ */
|
|
1081
|
+
return /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles8.container }, /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles8.content }, adapters.length > 0 ? /* @__PURE__ */ React7__default.default.createElement(React7__default.default.Fragment, null, /* @__PURE__ */ React7__default.default.createElement(
|
|
1204
1082
|
reactNative.ScrollView,
|
|
1205
1083
|
{
|
|
1206
|
-
style:
|
|
1207
|
-
contentContainerStyle:
|
|
1084
|
+
style: styles8.scroll,
|
|
1085
|
+
contentContainerStyle: styles8.scrollContent,
|
|
1208
1086
|
keyboardShouldPersistTaps: "handled",
|
|
1209
1087
|
showsVerticalScrollIndicator: true,
|
|
1210
|
-
refreshControl: /* @__PURE__ */
|
|
1088
|
+
refreshControl: /* @__PURE__ */ React7__default.default.createElement(reactNative.RefreshControl, { refreshing, onRefresh: handleRefresh })
|
|
1211
1089
|
},
|
|
1212
|
-
adapters.map((adapter, index) => /* @__PURE__ */
|
|
1090
|
+
adapters.map((adapter, index) => /* @__PURE__ */ React7__default.default.createElement(
|
|
1213
1091
|
StorageSection,
|
|
1214
1092
|
{
|
|
1215
1093
|
key: `${adapter.type}-${index}`,
|
|
1216
1094
|
adapter,
|
|
1217
|
-
keychainKeys: keychainKeysProp,
|
|
1218
|
-
onKeychainKeyAdded: handleKeychainKeyAdded,
|
|
1219
|
-
onSecureStoreKeyAdded: handleSecureStoreKeyAdded,
|
|
1220
1095
|
expanded: expandedIndices.has(index),
|
|
1221
1096
|
onToggleExpanded: () => {
|
|
1222
1097
|
setExpandedIndices((prev) => {
|
|
@@ -1229,18 +1104,57 @@ function StorageInspector({
|
|
|
1229
1104
|
refreshTrigger: refreshKey
|
|
1230
1105
|
}
|
|
1231
1106
|
))
|
|
1232
|
-
), /* @__PURE__ */
|
|
1107
|
+
), /* @__PURE__ */ React7__default.default.createElement(
|
|
1233
1108
|
IconButton,
|
|
1234
1109
|
{
|
|
1235
1110
|
name: "refresh",
|
|
1236
1111
|
onPress: handleRefresh,
|
|
1237
1112
|
size: 24,
|
|
1238
1113
|
tintColor: theme.colors.inverted,
|
|
1239
|
-
style:
|
|
1114
|
+
style: styles8.fab,
|
|
1240
1115
|
activeOpacity: 0.85
|
|
1241
1116
|
}
|
|
1242
|
-
)) : /* @__PURE__ */
|
|
1117
|
+
)) : /* @__PURE__ */ React7__default.default.createElement(reactNative.View, { style: styles8.empty }, /* @__PURE__ */ React7__default.default.createElement(reactNative.Text, { style: styles8.emptyText }, strings.noAdapterAvailable))));
|
|
1243
1118
|
}
|
|
1119
|
+
var { colors: colors5 } = theme;
|
|
1120
|
+
var styles8 = reactNative.StyleSheet.create({
|
|
1121
|
+
container: {
|
|
1122
|
+
flex: 1,
|
|
1123
|
+
width: "100%",
|
|
1124
|
+
backgroundColor: colors5.background
|
|
1125
|
+
},
|
|
1126
|
+
content: {
|
|
1127
|
+
flex: 1
|
|
1128
|
+
},
|
|
1129
|
+
scroll: {
|
|
1130
|
+
flex: 1
|
|
1131
|
+
},
|
|
1132
|
+
scrollContent: {
|
|
1133
|
+
flexGrow: 1,
|
|
1134
|
+
paddingBottom: LAYOUT.fabSize + LAYOUT.padding + 20,
|
|
1135
|
+
paddingTop: LAYOUT.padding
|
|
1136
|
+
},
|
|
1137
|
+
fab: {
|
|
1138
|
+
position: "absolute",
|
|
1139
|
+
bottom: LAYOUT.padding + 16,
|
|
1140
|
+
right: LAYOUT.padding + 16,
|
|
1141
|
+
width: LAYOUT.fabSize,
|
|
1142
|
+
height: LAYOUT.fabSize,
|
|
1143
|
+
borderRadius: LAYOUT.fabSize / 2,
|
|
1144
|
+
backgroundColor: colors5.text,
|
|
1145
|
+
alignItems: "center",
|
|
1146
|
+
justifyContent: "center"
|
|
1147
|
+
},
|
|
1148
|
+
empty: {
|
|
1149
|
+
padding: LAYOUT.padding * 2,
|
|
1150
|
+
alignItems: "center",
|
|
1151
|
+
marginHorizontal: LAYOUT.padding
|
|
1152
|
+
},
|
|
1153
|
+
emptyText: {
|
|
1154
|
+
fontSize: LAYOUT.fontSize,
|
|
1155
|
+
color: colors5.textMuted
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1244
1158
|
|
|
1245
1159
|
exports.StorageInspector = StorageInspector;
|
|
1246
1160
|
exports.createAsyncStorageAdapter = createAsyncStorageAdapter;
|