@magicred-1/react-native-lxmf 0.2.22 → 0.2.24
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/android/src/main/jniLibs/arm64-v8a/liblxmf_rn.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/liblxmf_rn.so +0 -0
- package/android/src/main/jniLibs/x86_64/liblxmf_rn.so +0 -0
- package/build/useLxmf.d.ts +1 -1
- package/example/app/(tabs)/index.tsx +46 -32
- package/ios/RustCore/liblxmf_rn.xcframework/Info.plist +5 -5
- package/ios/RustCore/liblxmf_rn.xcframework/ios-arm64/liblxmf_rn.a +0 -0
- package/ios/RustCore/liblxmf_rn.xcframework/ios-arm64_x86_64-simulator/liblxmf_rn.a +0 -0
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/useLxmf.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface LxmfMessageEvent {
|
|
|
34
34
|
}[];
|
|
35
35
|
}
|
|
36
36
|
export interface LxmfEvent {
|
|
37
|
-
type: 'statusChanged' | 'packetReceived' | 'txReceived' | 'beaconDiscovered' | 'messageReceived' | 'announceReceived' | 'log' | 'error';
|
|
37
|
+
type: 'statusChanged' | 'packetReceived' | 'txReceived' | 'beaconDiscovered' | 'messageReceived' | 'announceReceived' | 'messageQueued' | 'messageDelivered' | 'messageFailed' | 'log' | 'error';
|
|
38
38
|
[key: string]: any;
|
|
39
39
|
}
|
|
40
40
|
/** Node transport mode */
|
|
@@ -6,12 +6,13 @@ import {
|
|
|
6
6
|
ScrollView,
|
|
7
7
|
Share,
|
|
8
8
|
StyleSheet,
|
|
9
|
+
Switch,
|
|
9
10
|
Text,
|
|
10
11
|
TextInput,
|
|
11
12
|
View,
|
|
12
13
|
} from 'react-native';
|
|
13
14
|
import * as SecureStore from 'expo-secure-store';
|
|
14
|
-
import { LxmfModule, LxmfNodeMode, type LxmfEvent, useLxmf } from '@magicred-1/react-native-lxmf';
|
|
15
|
+
import { LxmfModule, LxmfNodeMode, type LxmfEvent, type LxmfMessageEvent, useLxmf } from '@magicred-1/react-native-lxmf';
|
|
15
16
|
|
|
16
17
|
// Persisted identity blob schema (versioned). Stored in expo-secure-store under
|
|
17
18
|
// IDENTITY_KEY — encrypted at rest on iOS (Keychain) and Android (Keystore-backed).
|
|
@@ -78,25 +79,14 @@ function fmtTime(e: LxmfEvent): string {
|
|
|
78
79
|
.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
function decodeLxmfContent(hexOrStr: string | undefined): string {
|
|
84
|
-
if (!hexOrStr) return '';
|
|
85
|
-
const hex = String(hexOrStr);
|
|
86
|
-
if (!/^[0-9a-fA-F]+$/.test(hex)) return hex;
|
|
87
|
-
const len = hex.length / 2;
|
|
88
|
-
if (len <= 96) return `[${len}B raw]`;
|
|
82
|
+
function base64ToUtf8(b64: string): string {
|
|
83
|
+
if (!b64) return '';
|
|
89
84
|
try {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
const decoded = new TextDecoder('utf-8', { fatal: false }).decode(payload);
|
|
95
|
-
const runs = decoded.match(/[\x20-\x7E\n\r\t]{4,}/g) ?? [];
|
|
96
|
-
if (runs.length === 0) return `[${len}B binary]`;
|
|
97
|
-
return runs.reduce((a, b) => a.length >= b.length ? a : b).trim();
|
|
85
|
+
const binary = globalThis.atob(b64);
|
|
86
|
+
const bytes = Uint8Array.from(binary, c => c.codePointAt(0) ?? 0);
|
|
87
|
+
return new TextDecoder('utf-8', { fatal: false }).decode(bytes);
|
|
98
88
|
} catch {
|
|
99
|
-
return
|
|
89
|
+
return '';
|
|
100
90
|
}
|
|
101
91
|
}
|
|
102
92
|
|
|
@@ -205,6 +195,7 @@ export default function HomeScreen() {
|
|
|
205
195
|
const [tcpHost, setTcpHost] = useState('192.168.1.135');
|
|
206
196
|
const [tcpPort, setTcpPort] = useState('4243');
|
|
207
197
|
const [displayName, setDisplayName] = useState('lxmf-mobile');
|
|
198
|
+
const [isBeacon, setIsBeacon] = useState(false);
|
|
208
199
|
const [bleActive, setBleActive] = useState(false);
|
|
209
200
|
const [tcpActive, setTcpActive] = useState(false);
|
|
210
201
|
const [transportMsg, setTransportMsg] = useState('');
|
|
@@ -335,13 +326,14 @@ export default function HomeScreen() {
|
|
|
335
326
|
mode: LxmfNodeMode.ReticulumAndBle,
|
|
336
327
|
tcpInterfaces: [{ host, port }],
|
|
337
328
|
displayName: displayName.trim() || 'lxmf-mobile',
|
|
329
|
+
isBeacon,
|
|
338
330
|
});
|
|
339
331
|
if (ok) {
|
|
340
332
|
setTcpActive(true);
|
|
341
333
|
startBLE();
|
|
342
334
|
setBleActive(true);
|
|
343
335
|
}
|
|
344
|
-
}, [tcpHost, tcpPort, displayName, start, startBLE]);
|
|
336
|
+
}, [tcpHost, tcpPort, displayName, isBeacon, start, startBLE]);
|
|
345
337
|
|
|
346
338
|
const onStopTcp = useCallback(async () => {
|
|
347
339
|
stopBLE();
|
|
@@ -378,6 +370,7 @@ export default function HomeScreen() {
|
|
|
378
370
|
mode: LxmfNodeMode.ReticulumAndBle,
|
|
379
371
|
tcpInterfaces: [{ host, port }],
|
|
380
372
|
displayName: displayName.trim() || 'lxmf-mobile',
|
|
373
|
+
isBeacon,
|
|
381
374
|
});
|
|
382
375
|
if (!ok) {
|
|
383
376
|
setTransportMsg('Failed to start node.');
|
|
@@ -387,7 +380,7 @@ export default function HomeScreen() {
|
|
|
387
380
|
}
|
|
388
381
|
startBLE();
|
|
389
382
|
setBleActive(true);
|
|
390
|
-
}, [isRunning, tcpHost, tcpPort, start, startBLE, displayName]);
|
|
383
|
+
}, [isRunning, tcpHost, tcpPort, isBeacon, start, startBLE, displayName]);
|
|
391
384
|
|
|
392
385
|
const onStopBle = useCallback(async () => {
|
|
393
386
|
stopBLE();
|
|
@@ -505,6 +498,16 @@ export default function HomeScreen() {
|
|
|
505
498
|
autoCapitalize="none"
|
|
506
499
|
autoCorrect={false}
|
|
507
500
|
/>
|
|
501
|
+
<View style={S.switchRow}>
|
|
502
|
+
<Text style={S.switchLabel}>Beacon mode</Text>
|
|
503
|
+
<Switch
|
|
504
|
+
value={isBeacon}
|
|
505
|
+
onValueChange={setIsBeacon}
|
|
506
|
+
disabled={isRunning}
|
|
507
|
+
trackColor={{ false: C.border, true: C.accent }}
|
|
508
|
+
thumbColor={isBeacon ? C.accentBright : C.textDim}
|
|
509
|
+
/>
|
|
510
|
+
</View>
|
|
508
511
|
{transportMsg ? <Text style={S.warn}>{transportMsg}</Text> : null}
|
|
509
512
|
<View style={S.btnRow}>
|
|
510
513
|
<Btn label="Start TCP" onPress={onStartTcp} disabled={!isNativeAvailable || isRunning || !identityHydrated} />
|
|
@@ -624,28 +627,31 @@ export default function HomeScreen() {
|
|
|
624
627
|
<Text style={S.muted}>No messages yet.</Text>
|
|
625
628
|
) : (
|
|
626
629
|
msgEvts.map((e, i) => {
|
|
627
|
-
const
|
|
628
|
-
const
|
|
630
|
+
const msg = e as unknown as LxmfMessageEvent;
|
|
631
|
+
const bodyText = base64ToUtf8(msg.body ?? '');
|
|
632
|
+
const titleText = msg.title ? base64ToUtf8(msg.title) : '';
|
|
633
|
+
const sender = msg.source ?? '';
|
|
629
634
|
return (
|
|
630
635
|
<View key={`${evtKey(e, 'msg-')}-${i}`} style={S.itemCard}>
|
|
631
636
|
<View style={S.announceHeader}>
|
|
632
637
|
<View style={S.announceInfo}>
|
|
633
|
-
<Text selectable style={S.itemTitle}>
|
|
634
|
-
|
|
635
|
-
</Text>
|
|
636
|
-
{
|
|
638
|
+
<Text selectable style={S.itemTitle}>From: {shortHex(sender)}</Text>
|
|
639
|
+
{titleText ? <Text selectable style={S.msgTitle}>{titleText}</Text> : null}
|
|
640
|
+
{bodyText ? <Text selectable style={S.itemBody}>{bodyText}</Text> : null}
|
|
641
|
+
{msg.image ? (
|
|
642
|
+
<Text style={S.mediaBadge}>[img: {msg.image.mimeType}]</Text>
|
|
643
|
+
) : null}
|
|
644
|
+
{msg.files?.length ? (
|
|
645
|
+
<Text style={S.mediaBadge}>[{msg.files.length} file{msg.files.length > 1 ? 's' : ''}]</Text>
|
|
646
|
+
) : null}
|
|
637
647
|
<Text style={S.itemMeta}>{fmtTime(e)}</Text>
|
|
638
648
|
</View>
|
|
639
649
|
{sender ? (
|
|
640
650
|
<View style={S.announceActions}>
|
|
641
|
-
<Pressable
|
|
642
|
-
style={S.copyBtn}
|
|
643
|
-
onPress={() => copyToClipboard(sender)}>
|
|
651
|
+
<Pressable style={S.copyBtn} onPress={() => copyToClipboard(sender)}>
|
|
644
652
|
<Text style={S.copyBtnText}>⎘</Text>
|
|
645
653
|
</Pressable>
|
|
646
|
-
<Pressable
|
|
647
|
-
style={S.sendToBtn}
|
|
648
|
-
onPress={() => { setDest(sender); setSendResult(''); }}>
|
|
654
|
+
<Pressable style={S.sendToBtn} onPress={() => { setDest(sender); setSendResult(''); }}>
|
|
649
655
|
<Text style={S.sendToBtnText}>↩ Reply</Text>
|
|
650
656
|
</Pressable>
|
|
651
657
|
</View>
|
|
@@ -871,4 +877,12 @@ const S = StyleSheet.create({
|
|
|
871
877
|
|
|
872
878
|
// Destination pre-filled indicator
|
|
873
879
|
destFilled: { color: C.accentBright, fontSize: 12, fontFamily: 'monospace' },
|
|
880
|
+
|
|
881
|
+
// Beacon mode toggle row
|
|
882
|
+
switchRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: 4 },
|
|
883
|
+
switchLabel: { color: C.textDim, fontSize: 13 },
|
|
884
|
+
|
|
885
|
+
// Message card extras
|
|
886
|
+
msgTitle: { color: C.text, fontSize: 13, fontWeight: '600', fontStyle: 'italic' },
|
|
887
|
+
mediaBadge: { color: C.accentBright, fontSize: 11, fontFamily: 'monospace', marginTop: 2 },
|
|
874
888
|
});
|
|
@@ -8,32 +8,32 @@
|
|
|
8
8
|
<key>BinaryPath</key>
|
|
9
9
|
<string>liblxmf_rn.a</string>
|
|
10
10
|
<key>LibraryIdentifier</key>
|
|
11
|
-
<string>ios-
|
|
11
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
12
12
|
<key>LibraryPath</key>
|
|
13
13
|
<string>liblxmf_rn.a</string>
|
|
14
14
|
<key>SupportedArchitectures</key>
|
|
15
15
|
<array>
|
|
16
16
|
<string>arm64</string>
|
|
17
|
+
<string>x86_64</string>
|
|
17
18
|
</array>
|
|
18
19
|
<key>SupportedPlatform</key>
|
|
19
20
|
<string>ios</string>
|
|
21
|
+
<key>SupportedPlatformVariant</key>
|
|
22
|
+
<string>simulator</string>
|
|
20
23
|
</dict>
|
|
21
24
|
<dict>
|
|
22
25
|
<key>BinaryPath</key>
|
|
23
26
|
<string>liblxmf_rn.a</string>
|
|
24
27
|
<key>LibraryIdentifier</key>
|
|
25
|
-
<string>ios-
|
|
28
|
+
<string>ios-arm64</string>
|
|
26
29
|
<key>LibraryPath</key>
|
|
27
30
|
<string>liblxmf_rn.a</string>
|
|
28
31
|
<key>SupportedArchitectures</key>
|
|
29
32
|
<array>
|
|
30
33
|
<string>arm64</string>
|
|
31
|
-
<string>x86_64</string>
|
|
32
34
|
</array>
|
|
33
35
|
<key>SupportedPlatform</key>
|
|
34
36
|
<string>ios</string>
|
|
35
|
-
<key>SupportedPlatformVariant</key>
|
|
36
|
-
<string>simulator</string>
|
|
37
37
|
</dict>
|
|
38
38
|
</array>
|
|
39
39
|
<key>CFBundlePackageType</key>
|
|
Binary file
|
|
Binary file
|