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