@thelacanians/vue-native-runtime 0.1.2 → 0.3.0
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/dist/index.cjs +1763 -107
- package/dist/index.d.cts +1946 -132
- package/dist/index.d.ts +1946 -132
- package/dist/index.js +1732 -108
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ function createTextNode(text) {
|
|
|
43
43
|
};
|
|
44
44
|
return markRaw(node);
|
|
45
45
|
}
|
|
46
|
-
function createCommentNode(
|
|
46
|
+
function createCommentNode(_text) {
|
|
47
47
|
const node = {
|
|
48
48
|
id: getNextNodeId(),
|
|
49
49
|
type: "__COMMENT__",
|
|
@@ -56,7 +56,7 @@ function createCommentNode(text) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// src/bridge.ts
|
|
59
|
-
var
|
|
59
|
+
var _NativeBridgeImpl = class _NativeBridgeImpl {
|
|
60
60
|
constructor() {
|
|
61
61
|
/** Pending operations waiting to be flushed to native */
|
|
62
62
|
this.pendingOps = [];
|
|
@@ -66,7 +66,8 @@ var NativeBridgeImpl = class {
|
|
|
66
66
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
67
67
|
/** Pending async callbacks from native module invocations */
|
|
68
68
|
this.pendingCallbacks = /* @__PURE__ */ new Map();
|
|
69
|
-
/** Auto-incrementing callback ID for async native module calls
|
|
69
|
+
/** Auto-incrementing callback ID for async native module calls.
|
|
70
|
+
* Wraps around at MAX_SAFE_CALLBACK_ID to prevent overflow. */
|
|
70
71
|
this.nextCallbackId = 1;
|
|
71
72
|
/** Global event listeners: eventName -> Set of callbacks */
|
|
72
73
|
this.globalEventHandlers = /* @__PURE__ */ new Map();
|
|
@@ -98,10 +99,14 @@ var NativeBridgeImpl = class {
|
|
|
98
99
|
const json = JSON.stringify(ops);
|
|
99
100
|
const flushFn = globalThis.__VN_flushOperations;
|
|
100
101
|
if (typeof flushFn === "function") {
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
try {
|
|
103
|
+
flushFn(json);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error("[VueNative] Error in __VN_flushOperations:", err);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
103
108
|
console.warn(
|
|
104
|
-
"[VueNative] __VN_flushOperations is not registered. Make sure the
|
|
109
|
+
"[VueNative] __VN_flushOperations is not registered. Make sure the native runtime has been initialized."
|
|
105
110
|
);
|
|
106
111
|
}
|
|
107
112
|
}
|
|
@@ -261,7 +266,12 @@ var NativeBridgeImpl = class {
|
|
|
261
266
|
*/
|
|
262
267
|
invokeNativeModule(moduleName, methodName, args = [], timeoutMs = 3e4) {
|
|
263
268
|
return new Promise((resolve, reject) => {
|
|
264
|
-
const callbackId = this.nextCallbackId
|
|
269
|
+
const callbackId = this.nextCallbackId;
|
|
270
|
+
if (this.nextCallbackId >= _NativeBridgeImpl.MAX_CALLBACK_ID) {
|
|
271
|
+
this.nextCallbackId = 1;
|
|
272
|
+
} else {
|
|
273
|
+
this.nextCallbackId++;
|
|
274
|
+
}
|
|
265
275
|
const timeoutId = setTimeout(() => {
|
|
266
276
|
if (this.pendingCallbacks.has(callbackId)) {
|
|
267
277
|
this.pendingCallbacks.delete(callbackId);
|
|
@@ -332,9 +342,9 @@ var NativeBridgeImpl = class {
|
|
|
332
342
|
}
|
|
333
343
|
const handlers = this.globalEventHandlers.get(eventName);
|
|
334
344
|
if (handlers) {
|
|
335
|
-
handlers.forEach((
|
|
345
|
+
handlers.forEach((h28) => {
|
|
336
346
|
try {
|
|
337
|
-
|
|
347
|
+
h28(payload);
|
|
338
348
|
} catch (err) {
|
|
339
349
|
console.error(`[VueNative] Error in global event handler "${eventName}":`, err);
|
|
340
350
|
}
|
|
@@ -356,6 +366,9 @@ var NativeBridgeImpl = class {
|
|
|
356
366
|
this.globalEventHandlers.clear();
|
|
357
367
|
}
|
|
358
368
|
};
|
|
369
|
+
/** Maximum callback ID before wraparound (safe for 32-bit signed int) */
|
|
370
|
+
_NativeBridgeImpl.MAX_CALLBACK_ID = 2147483647;
|
|
371
|
+
var NativeBridgeImpl = _NativeBridgeImpl;
|
|
359
372
|
if (typeof globalThis.__DEV__ === "undefined") {
|
|
360
373
|
;
|
|
361
374
|
globalThis.__DEV__ = true;
|
|
@@ -374,17 +387,21 @@ function toEventName(key) {
|
|
|
374
387
|
return key.slice(2).toLowerCase();
|
|
375
388
|
}
|
|
376
389
|
function patchStyle(nodeId, prevStyle, nextStyle) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
390
|
+
try {
|
|
391
|
+
const prev = prevStyle || {};
|
|
392
|
+
const next = nextStyle || {};
|
|
393
|
+
for (const key in next) {
|
|
394
|
+
if (next[key] !== prev[key]) {
|
|
395
|
+
NativeBridge.updateStyle(nodeId, key, next[key]);
|
|
396
|
+
}
|
|
382
397
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
398
|
+
for (const key in prev) {
|
|
399
|
+
if (!(key in next)) {
|
|
400
|
+
NativeBridge.updateStyle(nodeId, key, null);
|
|
401
|
+
}
|
|
387
402
|
}
|
|
403
|
+
} catch (err) {
|
|
404
|
+
console.error(`[VueNative] Error patching style on node ${nodeId}:`, err);
|
|
388
405
|
}
|
|
389
406
|
}
|
|
390
407
|
var nodeOps = {
|
|
@@ -437,22 +454,26 @@ var nodeOps = {
|
|
|
437
454
|
* - all else -> updateProp
|
|
438
455
|
*/
|
|
439
456
|
patchProp(el, key, prevValue, nextValue) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
457
|
+
try {
|
|
458
|
+
if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase()) {
|
|
459
|
+
const eventName = toEventName(key);
|
|
460
|
+
if (prevValue) {
|
|
461
|
+
NativeBridge.removeEventListener(el.id, eventName);
|
|
462
|
+
}
|
|
463
|
+
if (nextValue) {
|
|
464
|
+
NativeBridge.addEventListener(el.id, eventName, nextValue);
|
|
465
|
+
}
|
|
466
|
+
return;
|
|
444
467
|
}
|
|
445
|
-
if (
|
|
446
|
-
|
|
468
|
+
if (key === "style") {
|
|
469
|
+
patchStyle(el.id, prevValue, nextValue);
|
|
470
|
+
return;
|
|
447
471
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
return;
|
|
472
|
+
el.props[key] = nextValue;
|
|
473
|
+
NativeBridge.updateProp(el.id, key, nextValue);
|
|
474
|
+
} catch (err) {
|
|
475
|
+
console.error(`[VueNative] Error patching prop "${key}" on node ${el.id}:`, err);
|
|
453
476
|
}
|
|
454
|
-
el.props[key] = nextValue;
|
|
455
|
-
NativeBridge.updateProp(el.id, key, nextValue);
|
|
456
477
|
},
|
|
457
478
|
/**
|
|
458
479
|
* Insert a child node into a parent, optionally before an anchor node.
|
|
@@ -467,30 +488,34 @@ var nodeOps = {
|
|
|
467
488
|
}
|
|
468
489
|
}
|
|
469
490
|
child.parent = parent;
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
parent.children.push(child);
|
|
476
|
-
}
|
|
477
|
-
if (child.type !== "__COMMENT__") {
|
|
478
|
-
if (anchor.type !== "__COMMENT__") {
|
|
479
|
-
NativeBridge.insertBefore(parent.id, child.id, anchor.id);
|
|
491
|
+
try {
|
|
492
|
+
if (anchor) {
|
|
493
|
+
const anchorIdx = parent.children.indexOf(anchor);
|
|
494
|
+
if (anchorIdx !== -1) {
|
|
495
|
+
parent.children.splice(anchorIdx, 0, child);
|
|
480
496
|
} else {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
497
|
+
parent.children.push(child);
|
|
498
|
+
}
|
|
499
|
+
if (child.type !== "__COMMENT__") {
|
|
500
|
+
if (anchor.type !== "__COMMENT__") {
|
|
501
|
+
NativeBridge.insertBefore(parent.id, child.id, anchor.id);
|
|
484
502
|
} else {
|
|
485
|
-
|
|
503
|
+
const realAnchor = findNextNonComment(parent, anchor);
|
|
504
|
+
if (realAnchor) {
|
|
505
|
+
NativeBridge.insertBefore(parent.id, child.id, realAnchor.id);
|
|
506
|
+
} else {
|
|
507
|
+
NativeBridge.appendChild(parent.id, child.id);
|
|
508
|
+
}
|
|
486
509
|
}
|
|
487
510
|
}
|
|
511
|
+
} else {
|
|
512
|
+
parent.children.push(child);
|
|
513
|
+
if (child.type !== "__COMMENT__") {
|
|
514
|
+
NativeBridge.appendChild(parent.id, child.id);
|
|
515
|
+
}
|
|
488
516
|
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
if (child.type !== "__COMMENT__") {
|
|
492
|
-
NativeBridge.appendChild(parent.id, child.id);
|
|
493
|
-
}
|
|
517
|
+
} catch (err) {
|
|
518
|
+
console.error(`[VueNative] Error inserting node ${child.id} into ${parent.id}:`, err);
|
|
494
519
|
}
|
|
495
520
|
},
|
|
496
521
|
/**
|
|
@@ -504,8 +529,12 @@ var nodeOps = {
|
|
|
504
529
|
parent.children.splice(idx, 1);
|
|
505
530
|
}
|
|
506
531
|
child.parent = null;
|
|
507
|
-
|
|
508
|
-
|
|
532
|
+
try {
|
|
533
|
+
if (child.type !== "__COMMENT__") {
|
|
534
|
+
NativeBridge.removeChild(parent.id, child.id);
|
|
535
|
+
}
|
|
536
|
+
} catch (err) {
|
|
537
|
+
console.error(`[VueNative] Error removing node ${child.id}:`, err);
|
|
509
538
|
}
|
|
510
539
|
}
|
|
511
540
|
},
|
|
@@ -545,7 +574,10 @@ var VView = defineComponent({
|
|
|
545
574
|
props: {
|
|
546
575
|
style: Object,
|
|
547
576
|
testID: String,
|
|
548
|
-
accessibilityLabel: String
|
|
577
|
+
accessibilityLabel: String,
|
|
578
|
+
accessibilityRole: String,
|
|
579
|
+
accessibilityHint: String,
|
|
580
|
+
accessibilityState: Object
|
|
549
581
|
},
|
|
550
582
|
setup(props, { slots }) {
|
|
551
583
|
return () => h("VView", { ...props }, slots.default?.());
|
|
@@ -563,7 +595,10 @@ var VText = defineComponent2({
|
|
|
563
595
|
type: Boolean,
|
|
564
596
|
default: false
|
|
565
597
|
},
|
|
566
|
-
|
|
598
|
+
accessibilityLabel: String,
|
|
599
|
+
accessibilityRole: String,
|
|
600
|
+
accessibilityHint: String,
|
|
601
|
+
accessibilityState: Object
|
|
567
602
|
},
|
|
568
603
|
setup(props, { slots }) {
|
|
569
604
|
return () => h2("VText", { ...props }, slots.default?.());
|
|
@@ -585,7 +620,11 @@ var VButton = defineComponent3({
|
|
|
585
620
|
default: 0.7
|
|
586
621
|
},
|
|
587
622
|
onPress: Function,
|
|
588
|
-
onLongPress: Function
|
|
623
|
+
onLongPress: Function,
|
|
624
|
+
accessibilityLabel: String,
|
|
625
|
+
accessibilityRole: String,
|
|
626
|
+
accessibilityHint: String,
|
|
627
|
+
accessibilityState: Object
|
|
589
628
|
},
|
|
590
629
|
setup(props, { slots }) {
|
|
591
630
|
return () => h3(
|
|
@@ -635,7 +674,11 @@ var VInput = defineComponent4({
|
|
|
635
674
|
type: Boolean,
|
|
636
675
|
default: false
|
|
637
676
|
},
|
|
638
|
-
style: Object
|
|
677
|
+
style: Object,
|
|
678
|
+
accessibilityLabel: String,
|
|
679
|
+
accessibilityRole: String,
|
|
680
|
+
accessibilityHint: String,
|
|
681
|
+
accessibilityState: Object
|
|
639
682
|
},
|
|
640
683
|
emits: ["update:modelValue", "focus", "blur", "submit"],
|
|
641
684
|
setup(props, { emit }) {
|
|
@@ -663,6 +706,10 @@ var VInput = defineComponent4({
|
|
|
663
706
|
maxLength: props.maxLength,
|
|
664
707
|
multiline: props.multiline,
|
|
665
708
|
style: props.style,
|
|
709
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
710
|
+
accessibilityRole: props.accessibilityRole,
|
|
711
|
+
accessibilityHint: props.accessibilityHint,
|
|
712
|
+
accessibilityState: props.accessibilityState,
|
|
666
713
|
onChangetext,
|
|
667
714
|
onFocus,
|
|
668
715
|
onBlur,
|
|
@@ -686,7 +733,11 @@ var VSwitch = defineComponent5({
|
|
|
686
733
|
},
|
|
687
734
|
onTintColor: String,
|
|
688
735
|
thumbTintColor: String,
|
|
689
|
-
style: Object
|
|
736
|
+
style: Object,
|
|
737
|
+
accessibilityLabel: String,
|
|
738
|
+
accessibilityRole: String,
|
|
739
|
+
accessibilityHint: String,
|
|
740
|
+
accessibilityState: Object
|
|
690
741
|
},
|
|
691
742
|
emits: ["update:modelValue", "change"],
|
|
692
743
|
setup(props, { emit }) {
|
|
@@ -701,6 +752,10 @@ var VSwitch = defineComponent5({
|
|
|
701
752
|
onTintColor: props.onTintColor,
|
|
702
753
|
thumbTintColor: props.thumbTintColor,
|
|
703
754
|
style: props.style,
|
|
755
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
756
|
+
accessibilityRole: props.accessibilityRole,
|
|
757
|
+
accessibilityHint: props.accessibilityHint,
|
|
758
|
+
accessibilityState: props.accessibilityState,
|
|
704
759
|
onChange
|
|
705
760
|
});
|
|
706
761
|
}
|
|
@@ -773,7 +828,11 @@ var VScrollView = defineComponent7({
|
|
|
773
828
|
type: Boolean,
|
|
774
829
|
default: false
|
|
775
830
|
},
|
|
776
|
-
style: Object
|
|
831
|
+
style: Object,
|
|
832
|
+
accessibilityLabel: String,
|
|
833
|
+
accessibilityRole: String,
|
|
834
|
+
accessibilityHint: String,
|
|
835
|
+
accessibilityState: Object
|
|
777
836
|
},
|
|
778
837
|
emits: ["scroll", "refresh"],
|
|
779
838
|
setup(props, { slots, emit }) {
|
|
@@ -795,6 +854,10 @@ var VScrollView = defineComponent7({
|
|
|
795
854
|
contentContainerStyle: props.contentContainerStyle,
|
|
796
855
|
refreshing: props.refreshing,
|
|
797
856
|
style: props.style,
|
|
857
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
858
|
+
accessibilityRole: props.accessibilityRole,
|
|
859
|
+
accessibilityHint: props.accessibilityHint,
|
|
860
|
+
accessibilityState: props.accessibilityState,
|
|
798
861
|
onScroll,
|
|
799
862
|
onRefresh
|
|
800
863
|
},
|
|
@@ -815,7 +878,10 @@ var VImage = defineComponent8({
|
|
|
815
878
|
},
|
|
816
879
|
style: Object,
|
|
817
880
|
testID: String,
|
|
818
|
-
accessibilityLabel: String
|
|
881
|
+
accessibilityLabel: String,
|
|
882
|
+
accessibilityRole: String,
|
|
883
|
+
accessibilityHint: String,
|
|
884
|
+
accessibilityState: Object
|
|
819
885
|
},
|
|
820
886
|
emits: ["load", "error"],
|
|
821
887
|
setup(props, { emit }) {
|
|
@@ -863,7 +929,11 @@ var VSlider = defineComponent11({
|
|
|
863
929
|
modelValue: { type: Number, default: 0 },
|
|
864
930
|
min: { type: Number, default: 0 },
|
|
865
931
|
max: { type: Number, default: 1 },
|
|
866
|
-
style: { type: Object, default: () => ({}) }
|
|
932
|
+
style: { type: Object, default: () => ({}) },
|
|
933
|
+
accessibilityLabel: String,
|
|
934
|
+
accessibilityRole: String,
|
|
935
|
+
accessibilityHint: String,
|
|
936
|
+
accessibilityState: Object
|
|
867
937
|
},
|
|
868
938
|
emits: ["update:modelValue", "change"],
|
|
869
939
|
setup(props, { emit }) {
|
|
@@ -872,6 +942,10 @@ var VSlider = defineComponent11({
|
|
|
872
942
|
value: props.modelValue,
|
|
873
943
|
minimumValue: props.min,
|
|
874
944
|
maximumValue: props.max,
|
|
945
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
946
|
+
accessibilityRole: props.accessibilityRole,
|
|
947
|
+
accessibilityHint: props.accessibilityHint,
|
|
948
|
+
accessibilityState: props.accessibilityState,
|
|
875
949
|
onChange: (val) => {
|
|
876
950
|
emit("update:modelValue", val);
|
|
877
951
|
emit("change", val);
|
|
@@ -1158,6 +1232,352 @@ var VActionSheet = defineComponent20({
|
|
|
1158
1232
|
}
|
|
1159
1233
|
});
|
|
1160
1234
|
|
|
1235
|
+
// src/components/VRefreshControl.ts
|
|
1236
|
+
import { defineComponent as defineComponent21, h as h21 } from "@vue/runtime-core";
|
|
1237
|
+
var VRefreshControl = defineComponent21({
|
|
1238
|
+
name: "VRefreshControl",
|
|
1239
|
+
props: {
|
|
1240
|
+
refreshing: {
|
|
1241
|
+
type: Boolean,
|
|
1242
|
+
default: false
|
|
1243
|
+
},
|
|
1244
|
+
onRefresh: Function,
|
|
1245
|
+
tintColor: String,
|
|
1246
|
+
title: String,
|
|
1247
|
+
style: Object
|
|
1248
|
+
},
|
|
1249
|
+
setup(props) {
|
|
1250
|
+
return () => h21("VRefreshControl", {
|
|
1251
|
+
refreshing: props.refreshing,
|
|
1252
|
+
onRefresh: props.onRefresh,
|
|
1253
|
+
tintColor: props.tintColor,
|
|
1254
|
+
title: props.title
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
// src/components/VPressable.ts
|
|
1260
|
+
import { defineComponent as defineComponent22, h as h22 } from "@vue/runtime-core";
|
|
1261
|
+
var VPressable = defineComponent22({
|
|
1262
|
+
name: "VPressable",
|
|
1263
|
+
props: {
|
|
1264
|
+
style: Object,
|
|
1265
|
+
disabled: {
|
|
1266
|
+
type: Boolean,
|
|
1267
|
+
default: false
|
|
1268
|
+
},
|
|
1269
|
+
activeOpacity: {
|
|
1270
|
+
type: Number,
|
|
1271
|
+
default: 0.7
|
|
1272
|
+
},
|
|
1273
|
+
onPress: Function,
|
|
1274
|
+
onPressIn: Function,
|
|
1275
|
+
onPressOut: Function,
|
|
1276
|
+
onLongPress: Function,
|
|
1277
|
+
accessibilityLabel: String,
|
|
1278
|
+
accessibilityRole: String,
|
|
1279
|
+
accessibilityHint: String,
|
|
1280
|
+
accessibilityState: Object
|
|
1281
|
+
},
|
|
1282
|
+
setup(props, { slots }) {
|
|
1283
|
+
return () => h22(
|
|
1284
|
+
"VPressable",
|
|
1285
|
+
{
|
|
1286
|
+
...props,
|
|
1287
|
+
onPress: props.disabled ? void 0 : props.onPress,
|
|
1288
|
+
onPressIn: props.disabled ? void 0 : props.onPressIn,
|
|
1289
|
+
onPressOut: props.disabled ? void 0 : props.onPressOut,
|
|
1290
|
+
onLongPress: props.disabled ? void 0 : props.onLongPress
|
|
1291
|
+
},
|
|
1292
|
+
slots.default?.()
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
// src/components/VSectionList.ts
|
|
1298
|
+
import { defineComponent as defineComponent23, h as h23 } from "@vue/runtime-core";
|
|
1299
|
+
var VSectionList = defineComponent23({
|
|
1300
|
+
name: "VSectionList",
|
|
1301
|
+
props: {
|
|
1302
|
+
/** Array of section objects, each with a title and data array */
|
|
1303
|
+
sections: {
|
|
1304
|
+
type: Array,
|
|
1305
|
+
required: true
|
|
1306
|
+
},
|
|
1307
|
+
/** Extract a unique key from each item. Defaults to index as string. */
|
|
1308
|
+
keyExtractor: {
|
|
1309
|
+
type: Function,
|
|
1310
|
+
default: (_item, index) => String(index)
|
|
1311
|
+
},
|
|
1312
|
+
/** Estimated height per row in points. Default: 44 */
|
|
1313
|
+
estimatedItemHeight: {
|
|
1314
|
+
type: Number,
|
|
1315
|
+
default: 44
|
|
1316
|
+
},
|
|
1317
|
+
/** Whether section headers stick to the top when scrolling. Default: true */
|
|
1318
|
+
stickySectionHeaders: {
|
|
1319
|
+
type: Boolean,
|
|
1320
|
+
default: true
|
|
1321
|
+
},
|
|
1322
|
+
/** Show vertical scroll indicator. Default: true */
|
|
1323
|
+
showsScrollIndicator: {
|
|
1324
|
+
type: Boolean,
|
|
1325
|
+
default: true
|
|
1326
|
+
},
|
|
1327
|
+
/** Enable bounce at scroll boundaries. Default: true */
|
|
1328
|
+
bounces: {
|
|
1329
|
+
type: Boolean,
|
|
1330
|
+
default: true
|
|
1331
|
+
},
|
|
1332
|
+
style: {
|
|
1333
|
+
type: Object,
|
|
1334
|
+
default: () => ({})
|
|
1335
|
+
}
|
|
1336
|
+
},
|
|
1337
|
+
emits: ["scroll", "endReached"],
|
|
1338
|
+
setup(props, { slots, emit }) {
|
|
1339
|
+
return () => {
|
|
1340
|
+
const sections = props.sections ?? [];
|
|
1341
|
+
const children = [];
|
|
1342
|
+
if (slots.header) {
|
|
1343
|
+
children.push(
|
|
1344
|
+
h23("VView", { key: "__header__", style: { flexShrink: 0 } }, slots.header())
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
const totalItems = sections.reduce((sum, s) => sum + (s.data?.length ?? 0), 0);
|
|
1348
|
+
if (totalItems === 0 && slots.empty) {
|
|
1349
|
+
children.push(
|
|
1350
|
+
h23("VView", { key: "__empty__", style: { flexShrink: 0 } }, slots.empty())
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex++) {
|
|
1354
|
+
const section = sections[sectionIndex];
|
|
1355
|
+
if (slots.sectionHeader) {
|
|
1356
|
+
children.push(
|
|
1357
|
+
h23(
|
|
1358
|
+
"VView",
|
|
1359
|
+
{
|
|
1360
|
+
key: `__section_header_${sectionIndex}__`,
|
|
1361
|
+
__sectionHeader: true,
|
|
1362
|
+
style: { flexShrink: 0 }
|
|
1363
|
+
},
|
|
1364
|
+
slots.sectionHeader({ section, index: sectionIndex })
|
|
1365
|
+
)
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
const items = section.data ?? [];
|
|
1369
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
1370
|
+
const item = items[itemIndex];
|
|
1371
|
+
children.push(
|
|
1372
|
+
h23(
|
|
1373
|
+
"VView",
|
|
1374
|
+
{
|
|
1375
|
+
key: `${sectionIndex}_${props.keyExtractor(item, itemIndex)}`,
|
|
1376
|
+
style: { flexShrink: 0 }
|
|
1377
|
+
},
|
|
1378
|
+
slots.item?.({ item, index: itemIndex, section }) ?? []
|
|
1379
|
+
)
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
if (slots.sectionFooter) {
|
|
1383
|
+
children.push(
|
|
1384
|
+
h23(
|
|
1385
|
+
"VView",
|
|
1386
|
+
{
|
|
1387
|
+
key: `__section_footer_${sectionIndex}__`,
|
|
1388
|
+
style: { flexShrink: 0 }
|
|
1389
|
+
},
|
|
1390
|
+
slots.sectionFooter({ section, index: sectionIndex })
|
|
1391
|
+
)
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (slots.footer) {
|
|
1396
|
+
children.push(
|
|
1397
|
+
h23("VView", { key: "__footer__", style: { flexShrink: 0 } }, slots.footer())
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
return h23(
|
|
1401
|
+
"VSectionList",
|
|
1402
|
+
{
|
|
1403
|
+
style: props.style,
|
|
1404
|
+
estimatedItemHeight: props.estimatedItemHeight,
|
|
1405
|
+
stickySectionHeaders: props.stickySectionHeaders,
|
|
1406
|
+
showsScrollIndicator: props.showsScrollIndicator,
|
|
1407
|
+
bounces: props.bounces,
|
|
1408
|
+
onScroll: (e) => emit("scroll", e),
|
|
1409
|
+
onEndReached: () => emit("endReached")
|
|
1410
|
+
},
|
|
1411
|
+
children
|
|
1412
|
+
);
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
// src/components/VCheckbox.ts
|
|
1418
|
+
import { defineComponent as defineComponent24, h as h24 } from "@vue/runtime-core";
|
|
1419
|
+
var VCheckbox = defineComponent24({
|
|
1420
|
+
name: "VCheckbox",
|
|
1421
|
+
props: {
|
|
1422
|
+
modelValue: {
|
|
1423
|
+
type: Boolean,
|
|
1424
|
+
default: false
|
|
1425
|
+
},
|
|
1426
|
+
disabled: {
|
|
1427
|
+
type: Boolean,
|
|
1428
|
+
default: false
|
|
1429
|
+
},
|
|
1430
|
+
label: {
|
|
1431
|
+
type: String,
|
|
1432
|
+
default: void 0
|
|
1433
|
+
},
|
|
1434
|
+
checkColor: String,
|
|
1435
|
+
tintColor: String,
|
|
1436
|
+
style: Object,
|
|
1437
|
+
accessibilityLabel: String,
|
|
1438
|
+
accessibilityHint: String
|
|
1439
|
+
},
|
|
1440
|
+
emits: ["update:modelValue", "change"],
|
|
1441
|
+
setup(props, { emit }) {
|
|
1442
|
+
const onChange = (payload) => {
|
|
1443
|
+
const value = typeof payload === "boolean" ? payload : !!(payload?.value ?? payload);
|
|
1444
|
+
emit("update:modelValue", value);
|
|
1445
|
+
emit("change", value);
|
|
1446
|
+
};
|
|
1447
|
+
return () => h24("VCheckbox", {
|
|
1448
|
+
value: props.modelValue,
|
|
1449
|
+
disabled: props.disabled,
|
|
1450
|
+
label: props.label,
|
|
1451
|
+
checkColor: props.checkColor,
|
|
1452
|
+
tintColor: props.tintColor,
|
|
1453
|
+
style: props.style,
|
|
1454
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
1455
|
+
accessibilityHint: props.accessibilityHint,
|
|
1456
|
+
onChange
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
|
|
1461
|
+
// src/components/VRadio.ts
|
|
1462
|
+
import { defineComponent as defineComponent25, h as h25 } from "@vue/runtime-core";
|
|
1463
|
+
var VRadio = defineComponent25({
|
|
1464
|
+
name: "VRadio",
|
|
1465
|
+
props: {
|
|
1466
|
+
modelValue: {
|
|
1467
|
+
type: String,
|
|
1468
|
+
default: void 0
|
|
1469
|
+
},
|
|
1470
|
+
options: {
|
|
1471
|
+
type: Array,
|
|
1472
|
+
required: true
|
|
1473
|
+
},
|
|
1474
|
+
disabled: {
|
|
1475
|
+
type: Boolean,
|
|
1476
|
+
default: false
|
|
1477
|
+
},
|
|
1478
|
+
tintColor: String,
|
|
1479
|
+
style: Object,
|
|
1480
|
+
accessibilityLabel: String
|
|
1481
|
+
},
|
|
1482
|
+
emits: ["update:modelValue", "change"],
|
|
1483
|
+
setup(props, { emit }) {
|
|
1484
|
+
const onChange = (payload) => {
|
|
1485
|
+
const value = payload?.value ?? payload;
|
|
1486
|
+
emit("update:modelValue", value);
|
|
1487
|
+
emit("change", value);
|
|
1488
|
+
};
|
|
1489
|
+
return () => h25("VRadio", {
|
|
1490
|
+
selectedValue: props.modelValue,
|
|
1491
|
+
options: props.options,
|
|
1492
|
+
disabled: props.disabled,
|
|
1493
|
+
tintColor: props.tintColor,
|
|
1494
|
+
style: props.style,
|
|
1495
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
1496
|
+
onChange
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
});
|
|
1500
|
+
|
|
1501
|
+
// src/components/VDropdown.ts
|
|
1502
|
+
import { defineComponent as defineComponent26, h as h26 } from "@vue/runtime-core";
|
|
1503
|
+
var VDropdown = defineComponent26({
|
|
1504
|
+
name: "VDropdown",
|
|
1505
|
+
props: {
|
|
1506
|
+
modelValue: {
|
|
1507
|
+
type: String,
|
|
1508
|
+
default: void 0
|
|
1509
|
+
},
|
|
1510
|
+
options: {
|
|
1511
|
+
type: Array,
|
|
1512
|
+
required: true
|
|
1513
|
+
},
|
|
1514
|
+
placeholder: {
|
|
1515
|
+
type: String,
|
|
1516
|
+
default: "Select..."
|
|
1517
|
+
},
|
|
1518
|
+
disabled: {
|
|
1519
|
+
type: Boolean,
|
|
1520
|
+
default: false
|
|
1521
|
+
},
|
|
1522
|
+
tintColor: String,
|
|
1523
|
+
style: Object,
|
|
1524
|
+
accessibilityLabel: String
|
|
1525
|
+
},
|
|
1526
|
+
emits: ["update:modelValue", "change"],
|
|
1527
|
+
setup(props, { emit }) {
|
|
1528
|
+
const onChange = (payload) => {
|
|
1529
|
+
const value = payload?.value ?? payload;
|
|
1530
|
+
emit("update:modelValue", value);
|
|
1531
|
+
emit("change", value);
|
|
1532
|
+
};
|
|
1533
|
+
return () => h26("VDropdown", {
|
|
1534
|
+
selectedValue: props.modelValue,
|
|
1535
|
+
options: props.options,
|
|
1536
|
+
placeholder: props.placeholder,
|
|
1537
|
+
disabled: props.disabled,
|
|
1538
|
+
tintColor: props.tintColor,
|
|
1539
|
+
style: props.style,
|
|
1540
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
1541
|
+
onChange
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
|
|
1546
|
+
// src/components/VVideo.ts
|
|
1547
|
+
import { defineComponent as defineComponent27, h as h27 } from "@vue/runtime-core";
|
|
1548
|
+
var VVideo = defineComponent27({
|
|
1549
|
+
name: "VVideo",
|
|
1550
|
+
props: {
|
|
1551
|
+
source: Object,
|
|
1552
|
+
autoplay: { type: Boolean, default: false },
|
|
1553
|
+
loop: { type: Boolean, default: false },
|
|
1554
|
+
muted: { type: Boolean, default: false },
|
|
1555
|
+
paused: { type: Boolean, default: false },
|
|
1556
|
+
controls: { type: Boolean, default: true },
|
|
1557
|
+
volume: { type: Number, default: 1 },
|
|
1558
|
+
resizeMode: {
|
|
1559
|
+
type: String,
|
|
1560
|
+
default: "cover"
|
|
1561
|
+
},
|
|
1562
|
+
poster: String,
|
|
1563
|
+
style: Object,
|
|
1564
|
+
testID: String,
|
|
1565
|
+
accessibilityLabel: String
|
|
1566
|
+
},
|
|
1567
|
+
emits: ["ready", "play", "pause", "end", "error", "progress"],
|
|
1568
|
+
setup(props, { emit }) {
|
|
1569
|
+
return () => h27("VVideo", {
|
|
1570
|
+
...props,
|
|
1571
|
+
onReady: (e) => emit("ready", e),
|
|
1572
|
+
onPlay: () => emit("play"),
|
|
1573
|
+
onPause: () => emit("pause"),
|
|
1574
|
+
onEnd: () => emit("end"),
|
|
1575
|
+
onError: (e) => emit("error", e),
|
|
1576
|
+
onProgress: (e) => emit("progress", e)
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
|
|
1161
1581
|
// src/directives/vShow.ts
|
|
1162
1582
|
var vShow = {
|
|
1163
1583
|
beforeMount(el, { value }) {
|
|
@@ -1169,16 +1589,61 @@ var vShow = {
|
|
|
1169
1589
|
}
|
|
1170
1590
|
};
|
|
1171
1591
|
|
|
1172
|
-
// src/
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1592
|
+
// src/errorBoundary.ts
|
|
1593
|
+
import { defineComponent as defineComponent28, ref, watch, onErrorCaptured } from "@vue/runtime-core";
|
|
1594
|
+
var ErrorBoundary = defineComponent28({
|
|
1595
|
+
name: "ErrorBoundary",
|
|
1596
|
+
props: {
|
|
1597
|
+
onError: Function,
|
|
1598
|
+
resetKeys: {
|
|
1599
|
+
type: Array,
|
|
1600
|
+
default: () => []
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
setup(props, { slots }) {
|
|
1604
|
+
const error = ref(null);
|
|
1605
|
+
const errorInfo = ref("");
|
|
1606
|
+
onErrorCaptured((err, _instance, info) => {
|
|
1607
|
+
const normalizedError = err instanceof Error ? err : new Error(String(err));
|
|
1608
|
+
error.value = normalizedError;
|
|
1609
|
+
errorInfo.value = info;
|
|
1610
|
+
if (props.onError) {
|
|
1611
|
+
props.onError(normalizedError, info);
|
|
1612
|
+
}
|
|
1613
|
+
return false;
|
|
1614
|
+
});
|
|
1615
|
+
function reset() {
|
|
1616
|
+
error.value = null;
|
|
1617
|
+
errorInfo.value = "";
|
|
1618
|
+
}
|
|
1619
|
+
watch(
|
|
1620
|
+
() => props.resetKeys,
|
|
1621
|
+
() => {
|
|
1622
|
+
if (error.value) {
|
|
1623
|
+
reset();
|
|
1624
|
+
}
|
|
1625
|
+
},
|
|
1626
|
+
{ deep: true }
|
|
1627
|
+
);
|
|
1628
|
+
return () => {
|
|
1629
|
+
if (error.value && slots.fallback) {
|
|
1630
|
+
return slots.fallback({ error: error.value, errorInfo: errorInfo.value, reset });
|
|
1631
|
+
}
|
|
1632
|
+
return slots.default?.();
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
|
|
1637
|
+
// src/index.ts
|
|
1638
|
+
export * from "@vue/runtime-core";
|
|
1639
|
+
|
|
1640
|
+
// src/stylesheet.ts
|
|
1641
|
+
var validStyleProperties = /* @__PURE__ */ new Set([
|
|
1642
|
+
// Layout (Yoga / Flexbox)
|
|
1643
|
+
"flex",
|
|
1644
|
+
"flexDirection",
|
|
1645
|
+
"flexWrap",
|
|
1646
|
+
"flexGrow",
|
|
1182
1647
|
"flexShrink",
|
|
1183
1648
|
"flexBasis",
|
|
1184
1649
|
"justifyContent",
|
|
@@ -1213,6 +1678,7 @@ var validStyleProperties = /* @__PURE__ */ new Set([
|
|
|
1213
1678
|
"gap",
|
|
1214
1679
|
"rowGap",
|
|
1215
1680
|
"columnGap",
|
|
1681
|
+
"direction",
|
|
1216
1682
|
"display",
|
|
1217
1683
|
"overflow",
|
|
1218
1684
|
"zIndex",
|
|
@@ -1260,7 +1726,15 @@ var validStyleProperties = /* @__PURE__ */ new Set([
|
|
|
1260
1726
|
"resizeMode",
|
|
1261
1727
|
"tintColor",
|
|
1262
1728
|
// Transform
|
|
1263
|
-
"transform"
|
|
1729
|
+
"transform",
|
|
1730
|
+
// Accessibility
|
|
1731
|
+
"accessibilityLabel",
|
|
1732
|
+
"accessibilityRole",
|
|
1733
|
+
"accessibilityHint",
|
|
1734
|
+
"accessibilityState",
|
|
1735
|
+
"accessibilityValue",
|
|
1736
|
+
"accessible",
|
|
1737
|
+
"importantForAccessibility"
|
|
1264
1738
|
]);
|
|
1265
1739
|
function createStyleSheet(styles) {
|
|
1266
1740
|
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : true;
|
|
@@ -1318,9 +1792,9 @@ function useAsyncStorage() {
|
|
|
1318
1792
|
}
|
|
1319
1793
|
|
|
1320
1794
|
// src/composables/useClipboard.ts
|
|
1321
|
-
import { ref } from "@vue/runtime-core";
|
|
1795
|
+
import { ref as ref2 } from "@vue/runtime-core";
|
|
1322
1796
|
function useClipboard() {
|
|
1323
|
-
const content =
|
|
1797
|
+
const content = ref2("");
|
|
1324
1798
|
function copy(text) {
|
|
1325
1799
|
return NativeBridge.invokeNativeModule("Clipboard", "copy", [text]).then(() => void 0);
|
|
1326
1800
|
}
|
|
@@ -1334,16 +1808,16 @@ function useClipboard() {
|
|
|
1334
1808
|
}
|
|
1335
1809
|
|
|
1336
1810
|
// src/composables/useDeviceInfo.ts
|
|
1337
|
-
import { ref as
|
|
1811
|
+
import { ref as ref3, onMounted } from "@vue/runtime-core";
|
|
1338
1812
|
function useDeviceInfo() {
|
|
1339
|
-
const model =
|
|
1340
|
-
const systemVersion =
|
|
1341
|
-
const systemName =
|
|
1342
|
-
const name =
|
|
1343
|
-
const screenWidth =
|
|
1344
|
-
const screenHeight =
|
|
1345
|
-
const scale =
|
|
1346
|
-
const isLoaded =
|
|
1813
|
+
const model = ref3("");
|
|
1814
|
+
const systemVersion = ref3("");
|
|
1815
|
+
const systemName = ref3("");
|
|
1816
|
+
const name = ref3("");
|
|
1817
|
+
const screenWidth = ref3(0);
|
|
1818
|
+
const screenHeight = ref3(0);
|
|
1819
|
+
const scale = ref3(1);
|
|
1820
|
+
const isLoaded = ref3(false);
|
|
1347
1821
|
async function fetchInfo() {
|
|
1348
1822
|
const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
|
|
1349
1823
|
model.value = info.model ?? "";
|
|
@@ -1372,10 +1846,10 @@ function useDeviceInfo() {
|
|
|
1372
1846
|
}
|
|
1373
1847
|
|
|
1374
1848
|
// src/composables/useKeyboard.ts
|
|
1375
|
-
import { ref as
|
|
1849
|
+
import { ref as ref4 } from "@vue/runtime-core";
|
|
1376
1850
|
function useKeyboard() {
|
|
1377
|
-
const isVisible =
|
|
1378
|
-
const height =
|
|
1851
|
+
const isVisible = ref4(false);
|
|
1852
|
+
const height = ref4(0);
|
|
1379
1853
|
function dismiss() {
|
|
1380
1854
|
return NativeBridge.invokeNativeModule("Keyboard", "dismiss", []).then(() => void 0);
|
|
1381
1855
|
}
|
|
@@ -1439,10 +1913,10 @@ function useAnimation() {
|
|
|
1439
1913
|
}
|
|
1440
1914
|
|
|
1441
1915
|
// src/composables/useNetwork.ts
|
|
1442
|
-
import { ref as
|
|
1916
|
+
import { ref as ref5, onUnmounted } from "@vue/runtime-core";
|
|
1443
1917
|
function useNetwork() {
|
|
1444
|
-
const isConnected =
|
|
1445
|
-
const connectionType =
|
|
1918
|
+
const isConnected = ref5(true);
|
|
1919
|
+
const connectionType = ref5("unknown");
|
|
1446
1920
|
NativeBridge.invokeNativeModule("Network", "getStatus").then((status) => {
|
|
1447
1921
|
isConnected.value = status.isConnected;
|
|
1448
1922
|
connectionType.value = status.connectionType;
|
|
@@ -1457,9 +1931,9 @@ function useNetwork() {
|
|
|
1457
1931
|
}
|
|
1458
1932
|
|
|
1459
1933
|
// src/composables/useAppState.ts
|
|
1460
|
-
import { ref as
|
|
1934
|
+
import { ref as ref6, onUnmounted as onUnmounted2 } from "@vue/runtime-core";
|
|
1461
1935
|
function useAppState() {
|
|
1462
|
-
const state =
|
|
1936
|
+
const state = ref6("active");
|
|
1463
1937
|
NativeBridge.invokeNativeModule("AppState", "getState").then((s) => {
|
|
1464
1938
|
state.value = s;
|
|
1465
1939
|
}).catch(() => {
|
|
@@ -1502,10 +1976,10 @@ function usePermissions() {
|
|
|
1502
1976
|
}
|
|
1503
1977
|
|
|
1504
1978
|
// src/composables/useGeolocation.ts
|
|
1505
|
-
import { ref as
|
|
1979
|
+
import { ref as ref7, onUnmounted as onUnmounted3 } from "@vue/runtime-core";
|
|
1506
1980
|
function useGeolocation() {
|
|
1507
|
-
const coords =
|
|
1508
|
-
const error =
|
|
1981
|
+
const coords = ref7(null);
|
|
1982
|
+
const error = ref7(null);
|
|
1509
1983
|
let watchId = null;
|
|
1510
1984
|
async function getCurrentPosition() {
|
|
1511
1985
|
const result = await NativeBridge.invokeNativeModule("Geolocation", "getCurrentPosition");
|
|
@@ -1532,20 +2006,43 @@ function useGeolocation() {
|
|
|
1532
2006
|
}
|
|
1533
2007
|
|
|
1534
2008
|
// src/composables/useCamera.ts
|
|
2009
|
+
import { onUnmounted as onUnmounted4 } from "@vue/runtime-core";
|
|
1535
2010
|
function useCamera() {
|
|
2011
|
+
const qrCleanups = [];
|
|
1536
2012
|
async function launchCamera(options = {}) {
|
|
1537
2013
|
return NativeBridge.invokeNativeModule("Camera", "launchCamera", [options]);
|
|
1538
2014
|
}
|
|
1539
2015
|
async function launchImageLibrary(options = {}) {
|
|
1540
2016
|
return NativeBridge.invokeNativeModule("Camera", "launchImageLibrary", [options]);
|
|
1541
2017
|
}
|
|
1542
|
-
|
|
2018
|
+
async function captureVideo(options = {}) {
|
|
2019
|
+
return NativeBridge.invokeNativeModule("Camera", "captureVideo", [options]);
|
|
2020
|
+
}
|
|
2021
|
+
async function scanQRCode() {
|
|
2022
|
+
return NativeBridge.invokeNativeModule("Camera", "scanQRCode");
|
|
2023
|
+
}
|
|
2024
|
+
async function stopQRScan() {
|
|
2025
|
+
return NativeBridge.invokeNativeModule("Camera", "stopQRScan");
|
|
2026
|
+
}
|
|
2027
|
+
function onQRCodeDetected(callback) {
|
|
2028
|
+
const unsubscribe = NativeBridge.onGlobalEvent("camera:qrDetected", callback);
|
|
2029
|
+
qrCleanups.push(unsubscribe);
|
|
2030
|
+
return unsubscribe;
|
|
2031
|
+
}
|
|
2032
|
+
onUnmounted4(() => {
|
|
2033
|
+
NativeBridge.invokeNativeModule("Camera", "stopQRScan").catch(() => {
|
|
2034
|
+
});
|
|
2035
|
+
qrCleanups.forEach((fn) => fn());
|
|
2036
|
+
qrCleanups.length = 0;
|
|
2037
|
+
});
|
|
2038
|
+
return { launchCamera, launchImageLibrary, captureVideo, scanQRCode, stopQRScan, onQRCodeDetected };
|
|
1543
2039
|
}
|
|
1544
2040
|
|
|
1545
2041
|
// src/composables/useNotifications.ts
|
|
1546
|
-
import { ref as
|
|
2042
|
+
import { ref as ref8, onUnmounted as onUnmounted5 } from "@vue/runtime-core";
|
|
1547
2043
|
function useNotifications() {
|
|
1548
|
-
const isGranted =
|
|
2044
|
+
const isGranted = ref8(false);
|
|
2045
|
+
const pushToken = ref8(null);
|
|
1549
2046
|
async function requestPermission() {
|
|
1550
2047
|
const granted = await NativeBridge.invokeNativeModule("Notifications", "requestPermission");
|
|
1551
2048
|
isGranted.value = granted;
|
|
@@ -1565,10 +2062,44 @@ function useNotifications() {
|
|
|
1565
2062
|
}
|
|
1566
2063
|
function onNotification(handler) {
|
|
1567
2064
|
const unsubscribe = NativeBridge.onGlobalEvent("notification:received", handler);
|
|
1568
|
-
|
|
2065
|
+
onUnmounted5(unsubscribe);
|
|
2066
|
+
return unsubscribe;
|
|
2067
|
+
}
|
|
2068
|
+
async function registerForPush() {
|
|
2069
|
+
await NativeBridge.invokeNativeModule("Notifications", "registerForPush");
|
|
2070
|
+
}
|
|
2071
|
+
async function getToken() {
|
|
2072
|
+
return NativeBridge.invokeNativeModule("Notifications", "getToken");
|
|
2073
|
+
}
|
|
2074
|
+
function onPushToken(handler) {
|
|
2075
|
+
const unsubscribe = NativeBridge.onGlobalEvent("push:token", (payload) => {
|
|
2076
|
+
pushToken.value = payload.token;
|
|
2077
|
+
handler(payload.token);
|
|
2078
|
+
});
|
|
2079
|
+
onUnmounted5(unsubscribe);
|
|
2080
|
+
return unsubscribe;
|
|
2081
|
+
}
|
|
2082
|
+
function onPushReceived(handler) {
|
|
2083
|
+
const unsubscribe = NativeBridge.onGlobalEvent("push:received", handler);
|
|
2084
|
+
onUnmounted5(unsubscribe);
|
|
1569
2085
|
return unsubscribe;
|
|
1570
2086
|
}
|
|
1571
|
-
return {
|
|
2087
|
+
return {
|
|
2088
|
+
// Local
|
|
2089
|
+
isGranted,
|
|
2090
|
+
requestPermission,
|
|
2091
|
+
getPermissionStatus,
|
|
2092
|
+
scheduleLocal,
|
|
2093
|
+
cancel,
|
|
2094
|
+
cancelAll,
|
|
2095
|
+
onNotification,
|
|
2096
|
+
// Push
|
|
2097
|
+
pushToken,
|
|
2098
|
+
registerForPush,
|
|
2099
|
+
getToken,
|
|
2100
|
+
onPushToken,
|
|
2101
|
+
onPushReceived
|
|
2102
|
+
};
|
|
1572
2103
|
}
|
|
1573
2104
|
|
|
1574
2105
|
// src/composables/useBiometry.ts
|
|
@@ -1586,10 +2117,18 @@ function useBiometry() {
|
|
|
1586
2117
|
}
|
|
1587
2118
|
|
|
1588
2119
|
// src/composables/useHttp.ts
|
|
1589
|
-
import { ref as
|
|
2120
|
+
import { ref as ref9 } from "@vue/runtime-core";
|
|
1590
2121
|
function useHttp(config = {}) {
|
|
1591
|
-
|
|
1592
|
-
|
|
2122
|
+
if (config.pins && Object.keys(config.pins).length > 0) {
|
|
2123
|
+
const configurePins = globalThis.__VN_configurePins;
|
|
2124
|
+
if (typeof configurePins === "function") {
|
|
2125
|
+
configurePins(JSON.stringify(config.pins));
|
|
2126
|
+
} else {
|
|
2127
|
+
NativeBridge.invokeNativeModule("Http", "configurePins", [config.pins]);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
const loading = ref9(false);
|
|
2131
|
+
const error = ref9(null);
|
|
1593
2132
|
async function request(method, url, options = {}) {
|
|
1594
2133
|
const fullUrl = config.baseURL ? `${config.baseURL}${url}` : url;
|
|
1595
2134
|
loading.value = true;
|
|
@@ -1635,10 +2174,10 @@ function useHttp(config = {}) {
|
|
|
1635
2174
|
}
|
|
1636
2175
|
|
|
1637
2176
|
// src/composables/useColorScheme.ts
|
|
1638
|
-
import { ref as
|
|
2177
|
+
import { ref as ref10, onUnmounted as onUnmounted6 } from "@vue/runtime-core";
|
|
1639
2178
|
function useColorScheme() {
|
|
1640
|
-
const colorScheme =
|
|
1641
|
-
const isDark =
|
|
2179
|
+
const colorScheme = ref10("light");
|
|
2180
|
+
const isDark = ref10(false);
|
|
1642
2181
|
const unsubscribe = NativeBridge.onGlobalEvent(
|
|
1643
2182
|
"colorScheme:change",
|
|
1644
2183
|
(payload) => {
|
|
@@ -1646,12 +2185,12 @@ function useColorScheme() {
|
|
|
1646
2185
|
isDark.value = payload.colorScheme === "dark";
|
|
1647
2186
|
}
|
|
1648
2187
|
);
|
|
1649
|
-
|
|
2188
|
+
onUnmounted6(unsubscribe);
|
|
1650
2189
|
return { colorScheme, isDark };
|
|
1651
2190
|
}
|
|
1652
2191
|
|
|
1653
2192
|
// src/composables/useBackHandler.ts
|
|
1654
|
-
import { onMounted as onMounted2, onUnmounted as
|
|
2193
|
+
import { onMounted as onMounted2, onUnmounted as onUnmounted7 } from "@vue/runtime-core";
|
|
1655
2194
|
function useBackHandler(handler) {
|
|
1656
2195
|
let unsubscribe = null;
|
|
1657
2196
|
onMounted2(() => {
|
|
@@ -1659,10 +2198,1054 @@ function useBackHandler(handler) {
|
|
|
1659
2198
|
handler();
|
|
1660
2199
|
});
|
|
1661
2200
|
});
|
|
1662
|
-
|
|
2201
|
+
onUnmounted7(() => {
|
|
2202
|
+
unsubscribe?.();
|
|
2203
|
+
unsubscribe = null;
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
// src/composables/useSecureStorage.ts
|
|
2208
|
+
function useSecureStorage() {
|
|
2209
|
+
function getItem(key) {
|
|
2210
|
+
return NativeBridge.invokeNativeModule("SecureStorage", "get", [key]);
|
|
2211
|
+
}
|
|
2212
|
+
function setItem(key, value) {
|
|
2213
|
+
return NativeBridge.invokeNativeModule("SecureStorage", "set", [key, value]).then(() => void 0);
|
|
2214
|
+
}
|
|
2215
|
+
function removeItem(key) {
|
|
2216
|
+
return NativeBridge.invokeNativeModule("SecureStorage", "remove", [key]).then(() => void 0);
|
|
2217
|
+
}
|
|
2218
|
+
function clear() {
|
|
2219
|
+
return NativeBridge.invokeNativeModule("SecureStorage", "clear", []).then(() => void 0);
|
|
2220
|
+
}
|
|
2221
|
+
return { getItem, setItem, removeItem, clear };
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
// src/composables/useI18n.ts
|
|
2225
|
+
import { ref as ref11, onMounted as onMounted3 } from "@vue/runtime-core";
|
|
2226
|
+
function useI18n() {
|
|
2227
|
+
const isRTL = ref11(false);
|
|
2228
|
+
const locale = ref11("en");
|
|
2229
|
+
onMounted3(async () => {
|
|
2230
|
+
try {
|
|
2231
|
+
const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getDeviceInfo", []);
|
|
2232
|
+
locale.value = info?.locale || "en";
|
|
2233
|
+
isRTL.value = ["ar", "he", "fa", "ur"].some((l) => locale.value.startsWith(l));
|
|
2234
|
+
} catch {
|
|
2235
|
+
}
|
|
2236
|
+
});
|
|
2237
|
+
return { isRTL, locale };
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
// src/composables/usePlatform.ts
|
|
2241
|
+
function usePlatform() {
|
|
2242
|
+
const platform = typeof __PLATFORM__ !== "undefined" ? __PLATFORM__ : "ios";
|
|
2243
|
+
const isIOS = platform === "ios";
|
|
2244
|
+
const isAndroid = platform === "android";
|
|
2245
|
+
return { platform, isIOS, isAndroid };
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
// src/composables/useDimensions.ts
|
|
2249
|
+
import { ref as ref12, onMounted as onMounted4, onUnmounted as onUnmounted8 } from "@vue/runtime-core";
|
|
2250
|
+
function useDimensions() {
|
|
2251
|
+
const width = ref12(0);
|
|
2252
|
+
const height = ref12(0);
|
|
2253
|
+
const scale = ref12(1);
|
|
2254
|
+
onMounted4(async () => {
|
|
2255
|
+
try {
|
|
2256
|
+
const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
|
|
2257
|
+
width.value = info?.screenWidth || 0;
|
|
2258
|
+
height.value = info?.screenHeight || 0;
|
|
2259
|
+
scale.value = info?.scale || 1;
|
|
2260
|
+
} catch {
|
|
2261
|
+
}
|
|
2262
|
+
});
|
|
2263
|
+
const cleanup = NativeBridge.onGlobalEvent("dimensionsChange", (payload) => {
|
|
2264
|
+
if (payload.width != null) width.value = payload.width;
|
|
2265
|
+
if (payload.height != null) height.value = payload.height;
|
|
2266
|
+
if (payload.scale != null) scale.value = payload.scale;
|
|
2267
|
+
});
|
|
2268
|
+
onUnmounted8(cleanup);
|
|
2269
|
+
return { width, height, scale };
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// src/composables/useWebSocket.ts
|
|
2273
|
+
import { ref as ref13, onUnmounted as onUnmounted9 } from "@vue/runtime-core";
|
|
2274
|
+
var connectionCounter = 0;
|
|
2275
|
+
function useWebSocket(url, options = {}) {
|
|
2276
|
+
const {
|
|
2277
|
+
autoConnect = true,
|
|
2278
|
+
autoReconnect = false,
|
|
2279
|
+
maxReconnectAttempts = 3,
|
|
2280
|
+
reconnectInterval = 1e3
|
|
2281
|
+
} = options;
|
|
2282
|
+
const connectionId = `ws_${++connectionCounter}_${Date.now()}`;
|
|
2283
|
+
const status = ref13("CLOSED");
|
|
2284
|
+
const lastMessage = ref13(null);
|
|
2285
|
+
const error = ref13(null);
|
|
2286
|
+
let reconnectAttempts = 0;
|
|
2287
|
+
let reconnectTimer = null;
|
|
2288
|
+
const unsubscribers = [];
|
|
2289
|
+
unsubscribers.push(
|
|
2290
|
+
NativeBridge.onGlobalEvent("websocket:open", (payload) => {
|
|
2291
|
+
if (payload.connectionId !== connectionId) return;
|
|
2292
|
+
status.value = "OPEN";
|
|
2293
|
+
error.value = null;
|
|
2294
|
+
reconnectAttempts = 0;
|
|
2295
|
+
})
|
|
2296
|
+
);
|
|
2297
|
+
unsubscribers.push(
|
|
2298
|
+
NativeBridge.onGlobalEvent("websocket:message", (payload) => {
|
|
2299
|
+
if (payload.connectionId !== connectionId) return;
|
|
2300
|
+
lastMessage.value = payload.data;
|
|
2301
|
+
})
|
|
2302
|
+
);
|
|
2303
|
+
unsubscribers.push(
|
|
2304
|
+
NativeBridge.onGlobalEvent("websocket:close", (payload) => {
|
|
2305
|
+
if (payload.connectionId !== connectionId) return;
|
|
2306
|
+
status.value = "CLOSED";
|
|
2307
|
+
if (autoReconnect && reconnectAttempts < maxReconnectAttempts && payload.code !== 1e3) {
|
|
2308
|
+
reconnectAttempts++;
|
|
2309
|
+
reconnectTimer = setTimeout(() => {
|
|
2310
|
+
open();
|
|
2311
|
+
}, reconnectInterval);
|
|
2312
|
+
}
|
|
2313
|
+
})
|
|
2314
|
+
);
|
|
2315
|
+
unsubscribers.push(
|
|
2316
|
+
NativeBridge.onGlobalEvent("websocket:error", (payload) => {
|
|
2317
|
+
if (payload.connectionId !== connectionId) return;
|
|
2318
|
+
error.value = payload.message;
|
|
2319
|
+
})
|
|
2320
|
+
);
|
|
2321
|
+
function open() {
|
|
2322
|
+
if (status.value === "OPEN" || status.value === "CONNECTING") return;
|
|
2323
|
+
status.value = "CONNECTING";
|
|
2324
|
+
error.value = null;
|
|
2325
|
+
NativeBridge.invokeNativeModule("WebSocket", "connect", [url, connectionId]).catch((err) => {
|
|
2326
|
+
status.value = "CLOSED";
|
|
2327
|
+
error.value = err.message;
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
function send(data) {
|
|
2331
|
+
if (status.value !== "OPEN") return;
|
|
2332
|
+
const message = typeof data === "string" ? data : JSON.stringify(data);
|
|
2333
|
+
NativeBridge.invokeNativeModule("WebSocket", "send", [connectionId, message]).catch((err) => {
|
|
2334
|
+
error.value = err.message;
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
function close(code, reason) {
|
|
2338
|
+
if (status.value === "CLOSED" || status.value === "CLOSING") return;
|
|
2339
|
+
status.value = "CLOSING";
|
|
2340
|
+
if (reconnectTimer) {
|
|
2341
|
+
clearTimeout(reconnectTimer);
|
|
2342
|
+
reconnectTimer = null;
|
|
2343
|
+
}
|
|
2344
|
+
reconnectAttempts = maxReconnectAttempts;
|
|
2345
|
+
NativeBridge.invokeNativeModule("WebSocket", "close", [connectionId, code ?? 1e3, reason ?? ""]).catch(() => {
|
|
2346
|
+
status.value = "CLOSED";
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
if (autoConnect) {
|
|
2350
|
+
open();
|
|
2351
|
+
}
|
|
2352
|
+
onUnmounted9(() => {
|
|
2353
|
+
if (reconnectTimer) {
|
|
2354
|
+
clearTimeout(reconnectTimer);
|
|
2355
|
+
}
|
|
2356
|
+
if (status.value === "OPEN" || status.value === "CONNECTING") {
|
|
2357
|
+
reconnectAttempts = maxReconnectAttempts;
|
|
2358
|
+
NativeBridge.invokeNativeModule("WebSocket", "close", [connectionId, 1e3, ""]).catch(() => {
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
unsubscribers.forEach((unsub) => unsub());
|
|
2362
|
+
});
|
|
2363
|
+
return { status, lastMessage, error, send, close, open };
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// src/composables/useFileSystem.ts
|
|
2367
|
+
function useFileSystem() {
|
|
2368
|
+
function readFile(path, encoding) {
|
|
2369
|
+
return NativeBridge.invokeNativeModule("FileSystem", "readFile", [path, encoding ?? "utf8"]);
|
|
2370
|
+
}
|
|
2371
|
+
function writeFile(path, content, encoding) {
|
|
2372
|
+
return NativeBridge.invokeNativeModule("FileSystem", "writeFile", [path, content, encoding ?? "utf8"]).then(() => void 0);
|
|
2373
|
+
}
|
|
2374
|
+
function deleteFile(path) {
|
|
2375
|
+
return NativeBridge.invokeNativeModule("FileSystem", "deleteFile", [path]).then(() => void 0);
|
|
2376
|
+
}
|
|
2377
|
+
function exists(path) {
|
|
2378
|
+
return NativeBridge.invokeNativeModule("FileSystem", "exists", [path]);
|
|
2379
|
+
}
|
|
2380
|
+
function listDirectory(path) {
|
|
2381
|
+
return NativeBridge.invokeNativeModule("FileSystem", "listDirectory", [path]);
|
|
2382
|
+
}
|
|
2383
|
+
function downloadFile(url, destPath) {
|
|
2384
|
+
return NativeBridge.invokeNativeModule("FileSystem", "downloadFile", [url, destPath]);
|
|
2385
|
+
}
|
|
2386
|
+
function getDocumentsPath() {
|
|
2387
|
+
return NativeBridge.invokeNativeModule("FileSystem", "getDocumentsPath", []);
|
|
2388
|
+
}
|
|
2389
|
+
function getCachesPath() {
|
|
2390
|
+
return NativeBridge.invokeNativeModule("FileSystem", "getCachesPath", []);
|
|
2391
|
+
}
|
|
2392
|
+
function stat(path) {
|
|
2393
|
+
return NativeBridge.invokeNativeModule("FileSystem", "stat", [path]);
|
|
2394
|
+
}
|
|
2395
|
+
function mkdir(path) {
|
|
2396
|
+
return NativeBridge.invokeNativeModule("FileSystem", "mkdir", [path]).then(() => void 0);
|
|
2397
|
+
}
|
|
2398
|
+
function copyFile(srcPath, destPath) {
|
|
2399
|
+
return NativeBridge.invokeNativeModule("FileSystem", "copyFile", [srcPath, destPath]).then(() => void 0);
|
|
2400
|
+
}
|
|
2401
|
+
function moveFile(srcPath, destPath) {
|
|
2402
|
+
return NativeBridge.invokeNativeModule("FileSystem", "moveFile", [srcPath, destPath]).then(() => void 0);
|
|
2403
|
+
}
|
|
2404
|
+
return {
|
|
2405
|
+
readFile,
|
|
2406
|
+
writeFile,
|
|
2407
|
+
deleteFile,
|
|
2408
|
+
exists,
|
|
2409
|
+
listDirectory,
|
|
2410
|
+
downloadFile,
|
|
2411
|
+
getDocumentsPath,
|
|
2412
|
+
getCachesPath,
|
|
2413
|
+
stat,
|
|
2414
|
+
mkdir,
|
|
2415
|
+
copyFile,
|
|
2416
|
+
moveFile
|
|
2417
|
+
};
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
// src/composables/useSensors.ts
|
|
2421
|
+
import { ref as ref14, onUnmounted as onUnmounted10 } from "@vue/runtime-core";
|
|
2422
|
+
function useAccelerometer(options = {}) {
|
|
2423
|
+
const x = ref14(0);
|
|
2424
|
+
const y = ref14(0);
|
|
2425
|
+
const z = ref14(0);
|
|
2426
|
+
const isAvailable = ref14(false);
|
|
2427
|
+
let running = false;
|
|
2428
|
+
let unsubscribe = null;
|
|
2429
|
+
NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["accelerometer"]).then((result) => {
|
|
2430
|
+
isAvailable.value = result.available;
|
|
2431
|
+
}).catch(() => {
|
|
2432
|
+
});
|
|
2433
|
+
function start() {
|
|
2434
|
+
if (running) return;
|
|
2435
|
+
running = true;
|
|
2436
|
+
unsubscribe = NativeBridge.onGlobalEvent("sensor:accelerometer", (payload) => {
|
|
2437
|
+
x.value = payload.x;
|
|
2438
|
+
y.value = payload.y;
|
|
2439
|
+
z.value = payload.z;
|
|
2440
|
+
});
|
|
2441
|
+
NativeBridge.invokeNativeModule("Sensors", "startAccelerometer", [
|
|
2442
|
+
options.interval ?? 100
|
|
2443
|
+
]).catch(() => {
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
function stop() {
|
|
2447
|
+
if (!running) return;
|
|
2448
|
+
running = false;
|
|
1663
2449
|
unsubscribe?.();
|
|
1664
2450
|
unsubscribe = null;
|
|
2451
|
+
NativeBridge.invokeNativeModule("Sensors", "stopAccelerometer").catch(() => {
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
onUnmounted10(() => {
|
|
2455
|
+
stop();
|
|
2456
|
+
});
|
|
2457
|
+
return { x, y, z, isAvailable, start, stop };
|
|
2458
|
+
}
|
|
2459
|
+
function useGyroscope(options = {}) {
|
|
2460
|
+
const x = ref14(0);
|
|
2461
|
+
const y = ref14(0);
|
|
2462
|
+
const z = ref14(0);
|
|
2463
|
+
const isAvailable = ref14(false);
|
|
2464
|
+
let running = false;
|
|
2465
|
+
let unsubscribe = null;
|
|
2466
|
+
NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["gyroscope"]).then((result) => {
|
|
2467
|
+
isAvailable.value = result.available;
|
|
2468
|
+
}).catch(() => {
|
|
1665
2469
|
});
|
|
2470
|
+
function start() {
|
|
2471
|
+
if (running) return;
|
|
2472
|
+
running = true;
|
|
2473
|
+
unsubscribe = NativeBridge.onGlobalEvent("sensor:gyroscope", (payload) => {
|
|
2474
|
+
x.value = payload.x;
|
|
2475
|
+
y.value = payload.y;
|
|
2476
|
+
z.value = payload.z;
|
|
2477
|
+
});
|
|
2478
|
+
NativeBridge.invokeNativeModule("Sensors", "startGyroscope", [
|
|
2479
|
+
options.interval ?? 100
|
|
2480
|
+
]).catch(() => {
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
function stop() {
|
|
2484
|
+
if (!running) return;
|
|
2485
|
+
running = false;
|
|
2486
|
+
unsubscribe?.();
|
|
2487
|
+
unsubscribe = null;
|
|
2488
|
+
NativeBridge.invokeNativeModule("Sensors", "stopGyroscope").catch(() => {
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
onUnmounted10(() => {
|
|
2492
|
+
stop();
|
|
2493
|
+
});
|
|
2494
|
+
return { x, y, z, isAvailable, start, stop };
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
// src/composables/useAudio.ts
|
|
2498
|
+
import { ref as ref15, onUnmounted as onUnmounted11 } from "@vue/runtime-core";
|
|
2499
|
+
function useAudio() {
|
|
2500
|
+
const duration = ref15(0);
|
|
2501
|
+
const position = ref15(0);
|
|
2502
|
+
const isPlaying = ref15(false);
|
|
2503
|
+
const isRecording = ref15(false);
|
|
2504
|
+
const error = ref15(null);
|
|
2505
|
+
const unsubProgress = NativeBridge.onGlobalEvent("audio:progress", (payload) => {
|
|
2506
|
+
position.value = payload.currentTime ?? 0;
|
|
2507
|
+
duration.value = payload.duration ?? 0;
|
|
2508
|
+
});
|
|
2509
|
+
const unsubComplete = NativeBridge.onGlobalEvent("audio:complete", () => {
|
|
2510
|
+
isPlaying.value = false;
|
|
2511
|
+
position.value = 0;
|
|
2512
|
+
});
|
|
2513
|
+
const unsubError = NativeBridge.onGlobalEvent("audio:error", (payload) => {
|
|
2514
|
+
error.value = payload.message ?? "Unknown audio error";
|
|
2515
|
+
isPlaying.value = false;
|
|
2516
|
+
});
|
|
2517
|
+
onUnmounted11(() => {
|
|
2518
|
+
unsubProgress();
|
|
2519
|
+
unsubComplete();
|
|
2520
|
+
unsubError();
|
|
2521
|
+
NativeBridge.invokeNativeModule("Audio", "stop", []).catch(() => {
|
|
2522
|
+
});
|
|
2523
|
+
if (isRecording.value) {
|
|
2524
|
+
NativeBridge.invokeNativeModule("Audio", "stopRecording", []).catch(() => {
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2527
|
+
});
|
|
2528
|
+
async function play(uri, options = {}) {
|
|
2529
|
+
error.value = null;
|
|
2530
|
+
const result = await NativeBridge.invokeNativeModule("Audio", "play", [uri, options]);
|
|
2531
|
+
if (result?.duration != null) {
|
|
2532
|
+
duration.value = result.duration;
|
|
2533
|
+
}
|
|
2534
|
+
isPlaying.value = true;
|
|
2535
|
+
}
|
|
2536
|
+
async function pause() {
|
|
2537
|
+
await NativeBridge.invokeNativeModule("Audio", "pause", []);
|
|
2538
|
+
isPlaying.value = false;
|
|
2539
|
+
}
|
|
2540
|
+
async function resume() {
|
|
2541
|
+
await NativeBridge.invokeNativeModule("Audio", "resume", []);
|
|
2542
|
+
isPlaying.value = true;
|
|
2543
|
+
}
|
|
2544
|
+
async function stop() {
|
|
2545
|
+
await NativeBridge.invokeNativeModule("Audio", "stop", []);
|
|
2546
|
+
isPlaying.value = false;
|
|
2547
|
+
position.value = 0;
|
|
2548
|
+
duration.value = 0;
|
|
2549
|
+
}
|
|
2550
|
+
async function seek(positionSec) {
|
|
2551
|
+
await NativeBridge.invokeNativeModule("Audio", "seek", [positionSec]);
|
|
2552
|
+
}
|
|
2553
|
+
async function setVolume(volume) {
|
|
2554
|
+
await NativeBridge.invokeNativeModule("Audio", "setVolume", [volume]);
|
|
2555
|
+
}
|
|
2556
|
+
async function startRecording(options = {}) {
|
|
2557
|
+
error.value = null;
|
|
2558
|
+
const result = await NativeBridge.invokeNativeModule("Audio", "startRecording", [options]);
|
|
2559
|
+
isRecording.value = true;
|
|
2560
|
+
return result?.uri ?? "";
|
|
2561
|
+
}
|
|
2562
|
+
async function stopRecording() {
|
|
2563
|
+
const result = await NativeBridge.invokeNativeModule("Audio", "stopRecording", []);
|
|
2564
|
+
isRecording.value = false;
|
|
2565
|
+
return { uri: result?.uri ?? "", duration: result?.duration ?? 0 };
|
|
2566
|
+
}
|
|
2567
|
+
async function pauseRecording() {
|
|
2568
|
+
await NativeBridge.invokeNativeModule("Audio", "pauseRecording", []);
|
|
2569
|
+
}
|
|
2570
|
+
async function resumeRecording() {
|
|
2571
|
+
await NativeBridge.invokeNativeModule("Audio", "resumeRecording", []);
|
|
2572
|
+
}
|
|
2573
|
+
return {
|
|
2574
|
+
// Playback
|
|
2575
|
+
play,
|
|
2576
|
+
pause,
|
|
2577
|
+
resume,
|
|
2578
|
+
stop,
|
|
2579
|
+
seek,
|
|
2580
|
+
setVolume,
|
|
2581
|
+
// Recording
|
|
2582
|
+
startRecording,
|
|
2583
|
+
stopRecording,
|
|
2584
|
+
pauseRecording,
|
|
2585
|
+
resumeRecording,
|
|
2586
|
+
// Reactive state
|
|
2587
|
+
duration,
|
|
2588
|
+
position,
|
|
2589
|
+
isPlaying,
|
|
2590
|
+
isRecording,
|
|
2591
|
+
error
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
// src/composables/useDatabase.ts
|
|
2596
|
+
import { ref as ref16, onUnmounted as onUnmounted12 } from "@vue/runtime-core";
|
|
2597
|
+
function useDatabase(name = "default") {
|
|
2598
|
+
const isOpen = ref16(false);
|
|
2599
|
+
let opened = false;
|
|
2600
|
+
async function ensureOpen() {
|
|
2601
|
+
if (opened) return;
|
|
2602
|
+
await NativeBridge.invokeNativeModule("Database", "open", [name]);
|
|
2603
|
+
opened = true;
|
|
2604
|
+
isOpen.value = true;
|
|
2605
|
+
}
|
|
2606
|
+
async function execute(sql, params) {
|
|
2607
|
+
await ensureOpen();
|
|
2608
|
+
return NativeBridge.invokeNativeModule("Database", "execute", [name, sql, params ?? []]);
|
|
2609
|
+
}
|
|
2610
|
+
async function query(sql, params) {
|
|
2611
|
+
await ensureOpen();
|
|
2612
|
+
return NativeBridge.invokeNativeModule("Database", "query", [name, sql, params ?? []]);
|
|
2613
|
+
}
|
|
2614
|
+
async function transaction(callback) {
|
|
2615
|
+
await ensureOpen();
|
|
2616
|
+
const statements = [];
|
|
2617
|
+
const ctx = {
|
|
2618
|
+
execute: async (sql, params) => {
|
|
2619
|
+
statements.push({ sql, params: params ?? [] });
|
|
2620
|
+
return { rowsAffected: 0 };
|
|
2621
|
+
},
|
|
2622
|
+
query: async (sql, params) => {
|
|
2623
|
+
if (statements.length > 0) {
|
|
2624
|
+
await NativeBridge.invokeNativeModule("Database", "executeTransaction", [name, statements.splice(0)]);
|
|
2625
|
+
}
|
|
2626
|
+
return NativeBridge.invokeNativeModule("Database", "query", [name, sql, params ?? []]);
|
|
2627
|
+
}
|
|
2628
|
+
};
|
|
2629
|
+
await callback(ctx);
|
|
2630
|
+
if (statements.length > 0) {
|
|
2631
|
+
await NativeBridge.invokeNativeModule("Database", "executeTransaction", [name, statements]);
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
async function close() {
|
|
2635
|
+
if (!opened) return;
|
|
2636
|
+
await NativeBridge.invokeNativeModule("Database", "close", [name]);
|
|
2637
|
+
opened = false;
|
|
2638
|
+
isOpen.value = false;
|
|
2639
|
+
}
|
|
2640
|
+
onUnmounted12(() => {
|
|
2641
|
+
if (opened) {
|
|
2642
|
+
NativeBridge.invokeNativeModule("Database", "close", [name]).catch(() => {
|
|
2643
|
+
});
|
|
2644
|
+
opened = false;
|
|
2645
|
+
isOpen.value = false;
|
|
2646
|
+
}
|
|
2647
|
+
});
|
|
2648
|
+
return { execute, query, transaction, close, isOpen };
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
// src/composables/usePerformance.ts
|
|
2652
|
+
import { ref as ref17, onUnmounted as onUnmounted13 } from "@vue/runtime-core";
|
|
2653
|
+
function usePerformance() {
|
|
2654
|
+
const isProfiling = ref17(false);
|
|
2655
|
+
const fps = ref17(0);
|
|
2656
|
+
const memoryMB = ref17(0);
|
|
2657
|
+
const bridgeOps = ref17(0);
|
|
2658
|
+
let unsubscribe = null;
|
|
2659
|
+
function handleMetrics(payload) {
|
|
2660
|
+
fps.value = payload.fps ?? 0;
|
|
2661
|
+
memoryMB.value = payload.memoryMB ?? 0;
|
|
2662
|
+
bridgeOps.value = payload.bridgeOps ?? 0;
|
|
2663
|
+
}
|
|
2664
|
+
async function startProfiling() {
|
|
2665
|
+
if (isProfiling.value) return;
|
|
2666
|
+
unsubscribe = NativeBridge.onGlobalEvent("perf:metrics", handleMetrics);
|
|
2667
|
+
await NativeBridge.invokeNativeModule("Performance", "startProfiling", []);
|
|
2668
|
+
isProfiling.value = true;
|
|
2669
|
+
}
|
|
2670
|
+
async function stopProfiling() {
|
|
2671
|
+
if (!isProfiling.value) return;
|
|
2672
|
+
await NativeBridge.invokeNativeModule("Performance", "stopProfiling", []);
|
|
2673
|
+
isProfiling.value = false;
|
|
2674
|
+
if (unsubscribe) {
|
|
2675
|
+
unsubscribe();
|
|
2676
|
+
unsubscribe = null;
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
async function getMetrics() {
|
|
2680
|
+
return NativeBridge.invokeNativeModule("Performance", "getMetrics", []);
|
|
2681
|
+
}
|
|
2682
|
+
onUnmounted13(() => {
|
|
2683
|
+
if (isProfiling.value) {
|
|
2684
|
+
NativeBridge.invokeNativeModule("Performance", "stopProfiling", []).catch(() => {
|
|
2685
|
+
});
|
|
2686
|
+
isProfiling.value = false;
|
|
2687
|
+
}
|
|
2688
|
+
if (unsubscribe) {
|
|
2689
|
+
unsubscribe();
|
|
2690
|
+
unsubscribe = null;
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
return {
|
|
2694
|
+
startProfiling,
|
|
2695
|
+
stopProfiling,
|
|
2696
|
+
getMetrics,
|
|
2697
|
+
isProfiling,
|
|
2698
|
+
fps,
|
|
2699
|
+
memoryMB,
|
|
2700
|
+
bridgeOps
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
// src/composables/useSharedElementTransition.ts
|
|
2705
|
+
import { ref as ref18, onUnmounted as onUnmounted14 } from "@vue/runtime-core";
|
|
2706
|
+
var sharedElementRegistry = /* @__PURE__ */ new Map();
|
|
2707
|
+
function useSharedElementTransition(elementId) {
|
|
2708
|
+
const viewId = ref18(null);
|
|
2709
|
+
function register(nativeViewId) {
|
|
2710
|
+
viewId.value = nativeViewId;
|
|
2711
|
+
sharedElementRegistry.set(elementId, nativeViewId);
|
|
2712
|
+
}
|
|
2713
|
+
function unregister() {
|
|
2714
|
+
viewId.value = null;
|
|
2715
|
+
sharedElementRegistry.delete(elementId);
|
|
2716
|
+
}
|
|
2717
|
+
onUnmounted14(() => {
|
|
2718
|
+
unregister();
|
|
2719
|
+
});
|
|
2720
|
+
return {
|
|
2721
|
+
id: elementId,
|
|
2722
|
+
viewId,
|
|
2723
|
+
register,
|
|
2724
|
+
unregister
|
|
2725
|
+
};
|
|
2726
|
+
}
|
|
2727
|
+
async function measureViewFrame(nativeViewId) {
|
|
2728
|
+
return NativeBridge.invokeNativeModule("Animation", "measureView", [nativeViewId]);
|
|
2729
|
+
}
|
|
2730
|
+
function getSharedElementViewId(elementId) {
|
|
2731
|
+
return sharedElementRegistry.get(elementId);
|
|
2732
|
+
}
|
|
2733
|
+
function getRegisteredSharedElements() {
|
|
2734
|
+
return Array.from(sharedElementRegistry.keys());
|
|
2735
|
+
}
|
|
2736
|
+
function clearSharedElementRegistry() {
|
|
2737
|
+
sharedElementRegistry.clear();
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
// src/composables/useIAP.ts
|
|
2741
|
+
import { ref as ref19, onUnmounted as onUnmounted15 } from "@vue/runtime-core";
|
|
2742
|
+
function useIAP() {
|
|
2743
|
+
const products = ref19([]);
|
|
2744
|
+
const isReady = ref19(false);
|
|
2745
|
+
const error = ref19(null);
|
|
2746
|
+
const cleanups = [];
|
|
2747
|
+
const unsubscribe = NativeBridge.onGlobalEvent("iap:transactionUpdate", (payload) => {
|
|
2748
|
+
if (payload.state === "failed" && payload.error) {
|
|
2749
|
+
error.value = payload.error;
|
|
2750
|
+
}
|
|
2751
|
+
});
|
|
2752
|
+
cleanups.push(unsubscribe);
|
|
2753
|
+
NativeBridge.invokeNativeModule("IAP", "initialize").then(() => {
|
|
2754
|
+
isReady.value = true;
|
|
2755
|
+
}).catch((err) => {
|
|
2756
|
+
error.value = String(err);
|
|
2757
|
+
});
|
|
2758
|
+
async function getProducts(skus) {
|
|
2759
|
+
error.value = null;
|
|
2760
|
+
try {
|
|
2761
|
+
const result = await NativeBridge.invokeNativeModule("IAP", "getProducts", [skus]);
|
|
2762
|
+
const productList = result;
|
|
2763
|
+
products.value = productList;
|
|
2764
|
+
return productList;
|
|
2765
|
+
} catch (err) {
|
|
2766
|
+
error.value = String(err);
|
|
2767
|
+
return [];
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
async function purchase(sku) {
|
|
2771
|
+
error.value = null;
|
|
2772
|
+
try {
|
|
2773
|
+
return await NativeBridge.invokeNativeModule("IAP", "purchase", [sku]);
|
|
2774
|
+
} catch (err) {
|
|
2775
|
+
error.value = String(err);
|
|
2776
|
+
return null;
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
async function restorePurchases() {
|
|
2780
|
+
error.value = null;
|
|
2781
|
+
try {
|
|
2782
|
+
return await NativeBridge.invokeNativeModule("IAP", "restorePurchases");
|
|
2783
|
+
} catch (err) {
|
|
2784
|
+
error.value = String(err);
|
|
2785
|
+
return [];
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
async function getActiveSubscriptions() {
|
|
2789
|
+
error.value = null;
|
|
2790
|
+
try {
|
|
2791
|
+
return await NativeBridge.invokeNativeModule("IAP", "getActiveSubscriptions");
|
|
2792
|
+
} catch (err) {
|
|
2793
|
+
error.value = String(err);
|
|
2794
|
+
return [];
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
function onTransactionUpdate(callback) {
|
|
2798
|
+
const unsub = NativeBridge.onGlobalEvent("iap:transactionUpdate", callback);
|
|
2799
|
+
cleanups.push(unsub);
|
|
2800
|
+
return unsub;
|
|
2801
|
+
}
|
|
2802
|
+
onUnmounted15(() => {
|
|
2803
|
+
cleanups.forEach((fn) => fn());
|
|
2804
|
+
cleanups.length = 0;
|
|
2805
|
+
});
|
|
2806
|
+
return {
|
|
2807
|
+
products,
|
|
2808
|
+
isReady,
|
|
2809
|
+
error,
|
|
2810
|
+
getProducts,
|
|
2811
|
+
purchase,
|
|
2812
|
+
restorePurchases,
|
|
2813
|
+
getActiveSubscriptions,
|
|
2814
|
+
onTransactionUpdate
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
// src/composables/useAppleSignIn.ts
|
|
2819
|
+
import { ref as ref20, onUnmounted as onUnmounted16 } from "@vue/runtime-core";
|
|
2820
|
+
function useAppleSignIn() {
|
|
2821
|
+
const user = ref20(null);
|
|
2822
|
+
const isAuthenticated = ref20(false);
|
|
2823
|
+
const error = ref20(null);
|
|
2824
|
+
const cleanups = [];
|
|
2825
|
+
const unsubscribe = NativeBridge.onGlobalEvent("auth:appleCredentialRevoked", () => {
|
|
2826
|
+
user.value = null;
|
|
2827
|
+
isAuthenticated.value = false;
|
|
2828
|
+
});
|
|
2829
|
+
cleanups.push(unsubscribe);
|
|
2830
|
+
NativeBridge.invokeNativeModule("SocialAuth", "getCurrentUser", ["apple"]).then((result) => {
|
|
2831
|
+
if (result && result.userId) {
|
|
2832
|
+
user.value = { ...result, provider: "apple" };
|
|
2833
|
+
isAuthenticated.value = true;
|
|
2834
|
+
}
|
|
2835
|
+
}).catch(() => {
|
|
2836
|
+
});
|
|
2837
|
+
async function signIn() {
|
|
2838
|
+
error.value = null;
|
|
2839
|
+
try {
|
|
2840
|
+
const result = await NativeBridge.invokeNativeModule("SocialAuth", "signInWithApple");
|
|
2841
|
+
const socialUser = { ...result, provider: "apple" };
|
|
2842
|
+
user.value = socialUser;
|
|
2843
|
+
isAuthenticated.value = true;
|
|
2844
|
+
return { success: true, user: socialUser };
|
|
2845
|
+
} catch (err) {
|
|
2846
|
+
const message = String(err);
|
|
2847
|
+
error.value = message;
|
|
2848
|
+
return { success: false, error: message };
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
async function signOut() {
|
|
2852
|
+
error.value = null;
|
|
2853
|
+
try {
|
|
2854
|
+
await NativeBridge.invokeNativeModule("SocialAuth", "signOut", ["apple"]);
|
|
2855
|
+
user.value = null;
|
|
2856
|
+
isAuthenticated.value = false;
|
|
2857
|
+
} catch (err) {
|
|
2858
|
+
error.value = String(err);
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
onUnmounted16(() => {
|
|
2862
|
+
cleanups.forEach((fn) => fn());
|
|
2863
|
+
cleanups.length = 0;
|
|
2864
|
+
});
|
|
2865
|
+
return { signIn, signOut, user, isAuthenticated, error };
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
// src/composables/useGoogleSignIn.ts
|
|
2869
|
+
import { ref as ref21, onUnmounted as onUnmounted17 } from "@vue/runtime-core";
|
|
2870
|
+
function useGoogleSignIn(clientId) {
|
|
2871
|
+
const user = ref21(null);
|
|
2872
|
+
const isAuthenticated = ref21(false);
|
|
2873
|
+
const error = ref21(null);
|
|
2874
|
+
const cleanups = [];
|
|
2875
|
+
NativeBridge.invokeNativeModule("SocialAuth", "getCurrentUser", ["google"]).then((result) => {
|
|
2876
|
+
if (result && result.userId) {
|
|
2877
|
+
user.value = { ...result, provider: "google" };
|
|
2878
|
+
isAuthenticated.value = true;
|
|
2879
|
+
}
|
|
2880
|
+
}).catch(() => {
|
|
2881
|
+
});
|
|
2882
|
+
async function signIn() {
|
|
2883
|
+
error.value = null;
|
|
2884
|
+
try {
|
|
2885
|
+
const result = await NativeBridge.invokeNativeModule("SocialAuth", "signInWithGoogle", [clientId]);
|
|
2886
|
+
const socialUser = { ...result, provider: "google" };
|
|
2887
|
+
user.value = socialUser;
|
|
2888
|
+
isAuthenticated.value = true;
|
|
2889
|
+
return { success: true, user: socialUser };
|
|
2890
|
+
} catch (err) {
|
|
2891
|
+
const message = String(err);
|
|
2892
|
+
error.value = message;
|
|
2893
|
+
return { success: false, error: message };
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
async function signOut() {
|
|
2897
|
+
error.value = null;
|
|
2898
|
+
try {
|
|
2899
|
+
await NativeBridge.invokeNativeModule("SocialAuth", "signOut", ["google"]);
|
|
2900
|
+
user.value = null;
|
|
2901
|
+
isAuthenticated.value = false;
|
|
2902
|
+
} catch (err) {
|
|
2903
|
+
error.value = String(err);
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
onUnmounted17(() => {
|
|
2907
|
+
cleanups.forEach((fn) => fn());
|
|
2908
|
+
cleanups.length = 0;
|
|
2909
|
+
});
|
|
2910
|
+
return { signIn, signOut, user, isAuthenticated, error };
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
// src/composables/useBackgroundTask.ts
|
|
2914
|
+
import { ref as ref22, onUnmounted as onUnmounted18 } from "@vue/runtime-core";
|
|
2915
|
+
function useBackgroundTask() {
|
|
2916
|
+
const taskHandlers = /* @__PURE__ */ new Map();
|
|
2917
|
+
const defaultHandler = ref22(null);
|
|
2918
|
+
const unsubscribe = NativeBridge.onGlobalEvent("background:taskExecute", (payload) => {
|
|
2919
|
+
const handler = taskHandlers.get(payload.taskId) || defaultHandler.value;
|
|
2920
|
+
if (handler) {
|
|
2921
|
+
handler(payload.taskId);
|
|
2922
|
+
}
|
|
2923
|
+
});
|
|
2924
|
+
onUnmounted18(unsubscribe);
|
|
2925
|
+
function registerTask(taskId) {
|
|
2926
|
+
return NativeBridge.invokeNativeModule("BackgroundTask", "registerTask", [taskId]).then(() => void 0);
|
|
2927
|
+
}
|
|
2928
|
+
function scheduleTask(taskId, options = {}) {
|
|
2929
|
+
const type = options.type ?? "refresh";
|
|
2930
|
+
return NativeBridge.invokeNativeModule("BackgroundTask", "scheduleTask", [taskId, type, {
|
|
2931
|
+
earliestBeginDate: options.earliestBeginDate,
|
|
2932
|
+
requiresNetworkConnectivity: options.requiresNetworkConnectivity,
|
|
2933
|
+
requiresExternalPower: options.requiresExternalPower,
|
|
2934
|
+
interval: options.interval
|
|
2935
|
+
}]).then(() => void 0);
|
|
2936
|
+
}
|
|
2937
|
+
function cancelTask(taskId) {
|
|
2938
|
+
return NativeBridge.invokeNativeModule("BackgroundTask", "cancelTask", [taskId]).then(() => void 0);
|
|
2939
|
+
}
|
|
2940
|
+
function cancelAllTasks() {
|
|
2941
|
+
return NativeBridge.invokeNativeModule("BackgroundTask", "cancelAllTasks", []).then(() => void 0);
|
|
2942
|
+
}
|
|
2943
|
+
function completeTask(taskId, success = true) {
|
|
2944
|
+
return NativeBridge.invokeNativeModule("BackgroundTask", "completeTask", [taskId, success]).then(() => void 0);
|
|
2945
|
+
}
|
|
2946
|
+
function onTaskExecute(handler, taskId) {
|
|
2947
|
+
if (taskId) {
|
|
2948
|
+
taskHandlers.set(taskId, handler);
|
|
2949
|
+
return () => {
|
|
2950
|
+
taskHandlers.delete(taskId);
|
|
2951
|
+
};
|
|
2952
|
+
} else {
|
|
2953
|
+
defaultHandler.value = handler;
|
|
2954
|
+
return () => {
|
|
2955
|
+
defaultHandler.value = null;
|
|
2956
|
+
};
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
return { registerTask, scheduleTask, cancelTask, cancelAllTasks, completeTask, onTaskExecute };
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
// src/composables/useOTAUpdate.ts
|
|
2963
|
+
import { ref as ref23, onUnmounted as onUnmounted19 } from "@vue/runtime-core";
|
|
2964
|
+
function useOTAUpdate(serverUrl) {
|
|
2965
|
+
const currentVersion = ref23("embedded");
|
|
2966
|
+
const availableVersion = ref23(null);
|
|
2967
|
+
const downloadProgress = ref23(0);
|
|
2968
|
+
const isChecking = ref23(false);
|
|
2969
|
+
const isDownloading = ref23(false);
|
|
2970
|
+
const status = ref23("idle");
|
|
2971
|
+
const error = ref23(null);
|
|
2972
|
+
let lastUpdateInfo = null;
|
|
2973
|
+
const unsubscribe = NativeBridge.onGlobalEvent("ota:downloadProgress", (payload) => {
|
|
2974
|
+
downloadProgress.value = payload.progress;
|
|
2975
|
+
});
|
|
2976
|
+
onUnmounted19(unsubscribe);
|
|
2977
|
+
NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []).then((info) => {
|
|
2978
|
+
currentVersion.value = info.version;
|
|
2979
|
+
}).catch(() => {
|
|
2980
|
+
});
|
|
2981
|
+
async function checkForUpdate() {
|
|
2982
|
+
isChecking.value = true;
|
|
2983
|
+
status.value = "checking";
|
|
2984
|
+
error.value = null;
|
|
2985
|
+
try {
|
|
2986
|
+
const info = await NativeBridge.invokeNativeModule("OTA", "checkForUpdate", [serverUrl]);
|
|
2987
|
+
lastUpdateInfo = info;
|
|
2988
|
+
if (info.updateAvailable) {
|
|
2989
|
+
availableVersion.value = info.version;
|
|
2990
|
+
} else {
|
|
2991
|
+
availableVersion.value = null;
|
|
2992
|
+
}
|
|
2993
|
+
status.value = info.updateAvailable ? "idle" : "idle";
|
|
2994
|
+
return info;
|
|
2995
|
+
} catch (err) {
|
|
2996
|
+
error.value = err?.message || String(err);
|
|
2997
|
+
status.value = "error";
|
|
2998
|
+
throw err;
|
|
2999
|
+
} finally {
|
|
3000
|
+
isChecking.value = false;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
async function downloadUpdate(url, hash) {
|
|
3004
|
+
const downloadUrl = url || lastUpdateInfo?.downloadUrl;
|
|
3005
|
+
const expectedHash = hash || lastUpdateInfo?.hash;
|
|
3006
|
+
if (!downloadUrl) {
|
|
3007
|
+
const msg = "No download URL. Call checkForUpdate() first or provide a URL.";
|
|
3008
|
+
error.value = msg;
|
|
3009
|
+
status.value = "error";
|
|
3010
|
+
throw new Error(msg);
|
|
3011
|
+
}
|
|
3012
|
+
isDownloading.value = true;
|
|
3013
|
+
downloadProgress.value = 0;
|
|
3014
|
+
status.value = "downloading";
|
|
3015
|
+
error.value = null;
|
|
3016
|
+
try {
|
|
3017
|
+
await NativeBridge.invokeNativeModule("OTA", "downloadUpdate", [downloadUrl, expectedHash || ""]);
|
|
3018
|
+
status.value = "ready";
|
|
3019
|
+
} catch (err) {
|
|
3020
|
+
error.value = err?.message || String(err);
|
|
3021
|
+
status.value = "error";
|
|
3022
|
+
throw err;
|
|
3023
|
+
} finally {
|
|
3024
|
+
isDownloading.value = false;
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
async function applyUpdate() {
|
|
3028
|
+
error.value = null;
|
|
3029
|
+
try {
|
|
3030
|
+
await NativeBridge.invokeNativeModule("OTA", "applyUpdate", []);
|
|
3031
|
+
const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
|
|
3032
|
+
currentVersion.value = info.version;
|
|
3033
|
+
availableVersion.value = null;
|
|
3034
|
+
status.value = "idle";
|
|
3035
|
+
} catch (err) {
|
|
3036
|
+
error.value = err?.message || String(err);
|
|
3037
|
+
status.value = "error";
|
|
3038
|
+
throw err;
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
async function rollback() {
|
|
3042
|
+
error.value = null;
|
|
3043
|
+
try {
|
|
3044
|
+
await NativeBridge.invokeNativeModule("OTA", "rollback", []);
|
|
3045
|
+
const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
|
|
3046
|
+
currentVersion.value = info.version;
|
|
3047
|
+
status.value = "idle";
|
|
3048
|
+
} catch (err) {
|
|
3049
|
+
error.value = err?.message || String(err);
|
|
3050
|
+
status.value = "error";
|
|
3051
|
+
throw err;
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
async function getCurrentVersion() {
|
|
3055
|
+
const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
|
|
3056
|
+
currentVersion.value = info.version;
|
|
3057
|
+
return info;
|
|
3058
|
+
}
|
|
3059
|
+
return {
|
|
3060
|
+
checkForUpdate,
|
|
3061
|
+
downloadUpdate,
|
|
3062
|
+
applyUpdate,
|
|
3063
|
+
rollback,
|
|
3064
|
+
getCurrentVersion,
|
|
3065
|
+
currentVersion,
|
|
3066
|
+
availableVersion,
|
|
3067
|
+
downloadProgress,
|
|
3068
|
+
isChecking,
|
|
3069
|
+
isDownloading,
|
|
3070
|
+
status,
|
|
3071
|
+
error
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
// src/composables/useBluetooth.ts
|
|
3076
|
+
import { ref as ref24, onUnmounted as onUnmounted20 } from "@vue/runtime-core";
|
|
3077
|
+
function useBluetooth() {
|
|
3078
|
+
const devices = ref24([]);
|
|
3079
|
+
const connectedDevice = ref24(null);
|
|
3080
|
+
const isScanning = ref24(false);
|
|
3081
|
+
const isAvailable = ref24(false);
|
|
3082
|
+
const error = ref24(null);
|
|
3083
|
+
const cleanups = [];
|
|
3084
|
+
NativeBridge.invokeNativeModule("Bluetooth", "getState").then((state) => {
|
|
3085
|
+
isAvailable.value = state === "poweredOn";
|
|
3086
|
+
}).catch(() => {
|
|
3087
|
+
isAvailable.value = false;
|
|
3088
|
+
});
|
|
3089
|
+
const unsubState = NativeBridge.onGlobalEvent("ble:stateChanged", (payload) => {
|
|
3090
|
+
isAvailable.value = payload.state === "poweredOn";
|
|
3091
|
+
});
|
|
3092
|
+
cleanups.push(unsubState);
|
|
3093
|
+
const unsubFound = NativeBridge.onGlobalEvent("ble:deviceFound", (payload) => {
|
|
3094
|
+
const existing = devices.value.findIndex((d) => d.id === payload.id);
|
|
3095
|
+
if (existing >= 0) {
|
|
3096
|
+
devices.value[existing] = payload;
|
|
3097
|
+
} else {
|
|
3098
|
+
devices.value = [...devices.value, payload];
|
|
3099
|
+
}
|
|
3100
|
+
});
|
|
3101
|
+
cleanups.push(unsubFound);
|
|
3102
|
+
const unsubConnected = NativeBridge.onGlobalEvent("ble:connected", (payload) => {
|
|
3103
|
+
connectedDevice.value = payload;
|
|
3104
|
+
});
|
|
3105
|
+
cleanups.push(unsubConnected);
|
|
3106
|
+
const unsubDisconnected = NativeBridge.onGlobalEvent("ble:disconnected", () => {
|
|
3107
|
+
connectedDevice.value = null;
|
|
3108
|
+
});
|
|
3109
|
+
cleanups.push(unsubDisconnected);
|
|
3110
|
+
const unsubError = NativeBridge.onGlobalEvent("ble:error", (payload) => {
|
|
3111
|
+
error.value = payload.message;
|
|
3112
|
+
});
|
|
3113
|
+
cleanups.push(unsubError);
|
|
3114
|
+
async function scan(serviceUUIDs) {
|
|
3115
|
+
devices.value = [];
|
|
3116
|
+
isScanning.value = true;
|
|
3117
|
+
error.value = null;
|
|
3118
|
+
try {
|
|
3119
|
+
await NativeBridge.invokeNativeModule("Bluetooth", "startScan", [serviceUUIDs]);
|
|
3120
|
+
} catch (e) {
|
|
3121
|
+
error.value = e?.message || String(e);
|
|
3122
|
+
isScanning.value = false;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
async function stopScan() {
|
|
3126
|
+
await NativeBridge.invokeNativeModule("Bluetooth", "stopScan");
|
|
3127
|
+
isScanning.value = false;
|
|
3128
|
+
}
|
|
3129
|
+
async function connect(deviceId) {
|
|
3130
|
+
error.value = null;
|
|
3131
|
+
const result = await NativeBridge.invokeNativeModule("Bluetooth", "connect", [deviceId]);
|
|
3132
|
+
return result;
|
|
3133
|
+
}
|
|
3134
|
+
async function disconnect(deviceId) {
|
|
3135
|
+
await NativeBridge.invokeNativeModule("Bluetooth", "disconnect", [deviceId]);
|
|
3136
|
+
connectedDevice.value = null;
|
|
3137
|
+
}
|
|
3138
|
+
async function read(deviceId, serviceUUID, charUUID) {
|
|
3139
|
+
return NativeBridge.invokeNativeModule("Bluetooth", "readCharacteristic", [deviceId, serviceUUID, charUUID]);
|
|
3140
|
+
}
|
|
3141
|
+
async function write(deviceId, serviceUUID, charUUID, data) {
|
|
3142
|
+
return NativeBridge.invokeNativeModule("Bluetooth", "writeCharacteristic", [deviceId, serviceUUID, charUUID, data]);
|
|
3143
|
+
}
|
|
3144
|
+
async function subscribe(deviceId, serviceUUID, charUUID, callback) {
|
|
3145
|
+
await NativeBridge.invokeNativeModule("Bluetooth", "subscribeToCharacteristic", [deviceId, serviceUUID, charUUID]);
|
|
3146
|
+
const unsubscribe = NativeBridge.onGlobalEvent("ble:characteristicChanged", (payload) => {
|
|
3147
|
+
if (payload.deviceId === deviceId && payload.serviceUUID === serviceUUID && payload.characteristicUUID === charUUID) {
|
|
3148
|
+
callback(payload);
|
|
3149
|
+
}
|
|
3150
|
+
});
|
|
3151
|
+
cleanups.push(unsubscribe);
|
|
3152
|
+
return async () => {
|
|
3153
|
+
unsubscribe();
|
|
3154
|
+
await NativeBridge.invokeNativeModule("Bluetooth", "unsubscribeFromCharacteristic", [
|
|
3155
|
+
deviceId,
|
|
3156
|
+
serviceUUID,
|
|
3157
|
+
charUUID
|
|
3158
|
+
]);
|
|
3159
|
+
};
|
|
3160
|
+
}
|
|
3161
|
+
onUnmounted20(() => {
|
|
3162
|
+
if (isScanning.value) {
|
|
3163
|
+
NativeBridge.invokeNativeModule("Bluetooth", "stopScan").catch(() => {
|
|
3164
|
+
});
|
|
3165
|
+
}
|
|
3166
|
+
cleanups.forEach((fn) => fn());
|
|
3167
|
+
cleanups.length = 0;
|
|
3168
|
+
});
|
|
3169
|
+
return {
|
|
3170
|
+
scan,
|
|
3171
|
+
stopScan,
|
|
3172
|
+
connect,
|
|
3173
|
+
disconnect,
|
|
3174
|
+
read,
|
|
3175
|
+
write,
|
|
3176
|
+
subscribe,
|
|
3177
|
+
devices,
|
|
3178
|
+
connectedDevice,
|
|
3179
|
+
isScanning,
|
|
3180
|
+
isAvailable,
|
|
3181
|
+
error
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
// src/composables/useCalendar.ts
|
|
3186
|
+
import { ref as ref25 } from "@vue/runtime-core";
|
|
3187
|
+
function useCalendar() {
|
|
3188
|
+
const hasAccess = ref25(false);
|
|
3189
|
+
const error = ref25(null);
|
|
3190
|
+
async function requestAccess() {
|
|
3191
|
+
try {
|
|
3192
|
+
const result = await NativeBridge.invokeNativeModule("Calendar", "requestAccess");
|
|
3193
|
+
hasAccess.value = result.granted;
|
|
3194
|
+
return result.granted;
|
|
3195
|
+
} catch (e) {
|
|
3196
|
+
error.value = e?.message || String(e);
|
|
3197
|
+
return false;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
async function getEvents(startDate, endDate) {
|
|
3201
|
+
return NativeBridge.invokeNativeModule("Calendar", "getEvents", [startDate, endDate]);
|
|
3202
|
+
}
|
|
3203
|
+
async function createEvent(options) {
|
|
3204
|
+
return NativeBridge.invokeNativeModule("Calendar", "createEvent", [
|
|
3205
|
+
options.title,
|
|
3206
|
+
options.startDate,
|
|
3207
|
+
options.endDate,
|
|
3208
|
+
options.notes,
|
|
3209
|
+
options.calendarId
|
|
3210
|
+
]);
|
|
3211
|
+
}
|
|
3212
|
+
async function deleteEvent(eventId) {
|
|
3213
|
+
return NativeBridge.invokeNativeModule("Calendar", "deleteEvent", [eventId]);
|
|
3214
|
+
}
|
|
3215
|
+
async function getCalendars() {
|
|
3216
|
+
return NativeBridge.invokeNativeModule("Calendar", "getCalendars");
|
|
3217
|
+
}
|
|
3218
|
+
return { requestAccess, getEvents, createEvent, deleteEvent, getCalendars, hasAccess, error };
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
// src/composables/useContacts.ts
|
|
3222
|
+
import { ref as ref26 } from "@vue/runtime-core";
|
|
3223
|
+
function useContacts() {
|
|
3224
|
+
const hasAccess = ref26(false);
|
|
3225
|
+
const error = ref26(null);
|
|
3226
|
+
async function requestAccess() {
|
|
3227
|
+
try {
|
|
3228
|
+
const result = await NativeBridge.invokeNativeModule("Contacts", "requestAccess");
|
|
3229
|
+
hasAccess.value = result.granted;
|
|
3230
|
+
return result.granted;
|
|
3231
|
+
} catch (e) {
|
|
3232
|
+
error.value = e?.message || String(e);
|
|
3233
|
+
return false;
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
async function getContacts(query) {
|
|
3237
|
+
return NativeBridge.invokeNativeModule("Contacts", "getContacts", [query]);
|
|
3238
|
+
}
|
|
3239
|
+
async function getContact(id) {
|
|
3240
|
+
return NativeBridge.invokeNativeModule("Contacts", "getContact", [id]);
|
|
3241
|
+
}
|
|
3242
|
+
async function createContact(data) {
|
|
3243
|
+
return NativeBridge.invokeNativeModule("Contacts", "createContact", [data]);
|
|
3244
|
+
}
|
|
3245
|
+
async function deleteContact(id) {
|
|
3246
|
+
return NativeBridge.invokeNativeModule("Contacts", "deleteContact", [id]);
|
|
3247
|
+
}
|
|
3248
|
+
return { requestAccess, getContacts, getContact, createContact, deleteContact, hasAccess, error };
|
|
1666
3249
|
}
|
|
1667
3250
|
|
|
1668
3251
|
// src/index.ts
|
|
@@ -1688,6 +3271,15 @@ function createApp(rootComponent, rootProps) {
|
|
|
1688
3271
|
app.component("VPicker", VPicker);
|
|
1689
3272
|
app.component("VSegmentedControl", VSegmentedControl);
|
|
1690
3273
|
app.component("VActionSheet", VActionSheet);
|
|
3274
|
+
app.component("VRefreshControl", VRefreshControl);
|
|
3275
|
+
app.component("VPressable", VPressable);
|
|
3276
|
+
app.component("VSectionList", VSectionList);
|
|
3277
|
+
app.component("VCheckbox", VCheckbox);
|
|
3278
|
+
app.component("VRadio", VRadio);
|
|
3279
|
+
app.component("VDropdown", VDropdown);
|
|
3280
|
+
app.component("VVideo", VVideo);
|
|
3281
|
+
app.component("ErrorBoundary", ErrorBoundary);
|
|
3282
|
+
app.component("VErrorBoundary", ErrorBoundary);
|
|
1691
3283
|
app.directive("show", vShow);
|
|
1692
3284
|
app.config.errorHandler = (err, instance, info) => {
|
|
1693
3285
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -1705,7 +3297,7 @@ function createApp(rootComponent, rootProps) {
|
|
|
1705
3297
|
}
|
|
1706
3298
|
};
|
|
1707
3299
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
1708
|
-
app.config.warnHandler = (msg, instance,
|
|
3300
|
+
app.config.warnHandler = (msg, instance, _trace) => {
|
|
1709
3301
|
const componentName = instance?.$options?.name || instance?.$.type?.name || "Anonymous";
|
|
1710
3302
|
console.warn(`[VueNative] Warning in ${componentName}: ${msg}`);
|
|
1711
3303
|
};
|
|
@@ -1722,52 +3314,84 @@ function createApp(rootComponent, rootProps) {
|
|
|
1722
3314
|
return app;
|
|
1723
3315
|
}
|
|
1724
3316
|
export {
|
|
3317
|
+
ErrorBoundary,
|
|
1725
3318
|
NativeBridge,
|
|
1726
3319
|
VActionSheet,
|
|
1727
3320
|
VActivityIndicator,
|
|
1728
3321
|
VAlertDialog,
|
|
1729
3322
|
VButton,
|
|
3323
|
+
VCheckbox,
|
|
3324
|
+
VDropdown,
|
|
1730
3325
|
VImage,
|
|
1731
3326
|
VInput,
|
|
1732
3327
|
VKeyboardAvoiding,
|
|
1733
3328
|
VList,
|
|
1734
3329
|
VModal,
|
|
1735
3330
|
VPicker,
|
|
3331
|
+
VPressable,
|
|
1736
3332
|
VProgressBar,
|
|
3333
|
+
VRadio,
|
|
3334
|
+
VRefreshControl,
|
|
1737
3335
|
VSafeArea,
|
|
1738
3336
|
VScrollView,
|
|
3337
|
+
VSectionList,
|
|
1739
3338
|
VSegmentedControl,
|
|
1740
3339
|
VSlider,
|
|
1741
3340
|
VStatusBar,
|
|
1742
3341
|
VSwitch,
|
|
1743
3342
|
VText,
|
|
3343
|
+
VVideo,
|
|
1744
3344
|
VView,
|
|
1745
3345
|
VWebView,
|
|
3346
|
+
clearSharedElementRegistry,
|
|
1746
3347
|
createApp,
|
|
1747
3348
|
createCommentNode,
|
|
1748
3349
|
createNativeNode,
|
|
1749
3350
|
createStyleSheet,
|
|
1750
3351
|
createTextNode,
|
|
3352
|
+
getRegisteredSharedElements,
|
|
3353
|
+
getSharedElementViewId,
|
|
3354
|
+
measureViewFrame,
|
|
1751
3355
|
render,
|
|
1752
3356
|
resetNodeId,
|
|
3357
|
+
useAccelerometer,
|
|
1753
3358
|
useAnimation,
|
|
1754
3359
|
useAppState,
|
|
3360
|
+
useAppleSignIn,
|
|
1755
3361
|
useAsyncStorage,
|
|
3362
|
+
useAudio,
|
|
1756
3363
|
useBackHandler,
|
|
3364
|
+
useBackgroundTask,
|
|
1757
3365
|
useBiometry,
|
|
3366
|
+
useBluetooth,
|
|
3367
|
+
useCalendar,
|
|
1758
3368
|
useCamera,
|
|
1759
3369
|
useClipboard,
|
|
1760
3370
|
useColorScheme,
|
|
3371
|
+
useContacts,
|
|
3372
|
+
useDatabase,
|
|
1761
3373
|
useDeviceInfo,
|
|
3374
|
+
useDimensions,
|
|
3375
|
+
useFileSystem,
|
|
1762
3376
|
useGeolocation,
|
|
3377
|
+
useGoogleSignIn,
|
|
3378
|
+
useGyroscope,
|
|
1763
3379
|
useHaptics,
|
|
1764
3380
|
useHttp,
|
|
3381
|
+
useI18n,
|
|
3382
|
+
useIAP,
|
|
1765
3383
|
useKeyboard,
|
|
1766
3384
|
useLinking,
|
|
1767
3385
|
useNetwork,
|
|
1768
3386
|
useNotifications,
|
|
3387
|
+
useOTAUpdate,
|
|
3388
|
+
usePerformance,
|
|
1769
3389
|
usePermissions,
|
|
3390
|
+
usePlatform,
|
|
3391
|
+
useSecureStorage,
|
|
1770
3392
|
useShare,
|
|
3393
|
+
useSharedElementTransition,
|
|
3394
|
+
useWebSocket,
|
|
1771
3395
|
vShow,
|
|
1772
3396
|
validStyleProperties
|
|
1773
3397
|
};
|