@innspel/react-native 0.5.1 → 0.6.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/README.md +42 -1
- package/dist/index.cjs +83 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -3
- package/dist/index.d.ts +60 -3
- package/dist/index.js +83 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Innspels. Innsenderen skal se hvem som svarte.
|
|
|
98
98
|
| Kjente feil | I feilsporet **før** feltet, i ønskesporet etter. Tre svar per kort: «Ja, jeg også» (teller deg uten ny sak), «Ligner, men ikke helt» (ditt eget innspill med lenke), «Nei, det er noe annet». Tom liste hopper skjermen over — treffene er et tilbud, aldri en sperre. |
|
|
99
99
|
| Feltet | Ett tekstfelt. Send er aktiv fra N tegn, og **ingenting annet er obligatorisk**. Konteksten som legges ved er synlig og kan fjernes linje for linje. |
|
|
100
100
|
| Mønstervarsel | Ser teksten ut til å inneholde e-post, telefonnummer, kortnummer, IP eller en tilgangsnøkkel, spør widgeten om det skal fjernes. Den fjerner **aldri** noe selv. |
|
|
101
|
-
| Skjermbilde | Valgfritt
|
|
101
|
+
| Skjermbilde | Valgfritt, én eller to veier: «Legg ved skjermbilde» (skjermen bak arket, tatt ved trykk) og «Velg bilde» (fra galleriet, med din velger). Forhåndsvises og maskeres på enheten — private views automatisk på en fangst, resten med felt, pensel eller «Masker all tekst». Se under. |
|
|
102
102
|
| Kvittering | Lover noe konkret, per spor, med saksnummer. Ber aldri om en vurdering av appen. Feilet bildet, sier den det — saken er sendt uansett. |
|
|
103
103
|
| Mine innspill | Status, løftet som hører til, og svaret fra deg under saken. Det som venter på nett står øverst. |
|
|
104
104
|
|
|
@@ -132,6 +132,47 @@ import { createScreenshotAdapter, InnspelPrivate } from '@innspel/react-native';
|
|
|
132
132
|
<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
**Bilde fra galleriet.** Et innspill handler sjelden om skjermen widgeten åpnes fra — åpnes
|
|
136
|
+
den fra en profilside, viser fangsten profilen, ikke feilen. Gi adapteren din egen
|
|
137
|
+
bildevelger, så får innsenderen «Velg bilde» og kan legge ved et systemskjermbilde tatt
|
|
138
|
+
der feilen er. Pakken tar ingen avhengighet på velgeren:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import * as ImagePicker from 'expo-image-picker';
|
|
142
|
+
import { createScreenshotAdapter, type PickImageFn } from '@innspel/react-native';
|
|
143
|
+
|
|
144
|
+
const pickImage: PickImageFn = async () => {
|
|
145
|
+
const r = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], exif: false });
|
|
146
|
+
return r.canceled ? null : { uri: r.assets[0]!.uri, width: r.assets[0]!.width, height: r.assets[0]!.height };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Begge veiene:
|
|
150
|
+
<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage })}>
|
|
151
|
+
// Bare «Velg bilde» — skjermen bak arket fanges aldri:
|
|
152
|
+
<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage, captureScreen: false })}>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`captureRef` trengs fortsatt: forhåndsvisningen med maskene fanges på nytt, og det er
|
|
156
|
+
komposittet som lastes opp — aldri fila fra galleriet. Systemets bildevelger trenger ingen
|
|
157
|
+
tillatelse til biblioteket på Android 13+ og iOS. `<InnspelPrivate>` kan ikke gjelde et
|
|
158
|
+
bilde fra et annet sted, og forhåndsvisningen sier det til innsenderen.
|
|
159
|
+
|
|
160
|
+
**Din egen setning ved bildesteget.** Du kjenner brukerne dine og hva som er greit å legge
|
|
161
|
+
ved; plattformen eier ikke den setningen. Den står ved knappene og i forhåndsvisningen:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<InnspelProvider
|
|
165
|
+
client={innspel}
|
|
166
|
+
screenshot={adapter}
|
|
167
|
+
imageStepNote={{
|
|
168
|
+
feil: 'Legg ved et skjermbilde av feilen. Ikke send bilder av andre personer.',
|
|
169
|
+
onske: 'Vis gjerne hvor i appen du savner det.',
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
En streng gjelder begge spor. Et spor uten setning viser ingen.
|
|
175
|
+
|
|
135
176
|
Uten `screenshot` finnes ikke steget — ikke som en grå knapp, det finnes ikke.
|
|
136
177
|
Det samme gjelder når leietakeren har skjermbilde av (`screenshotsEnabled: false`,
|
|
137
178
|
tvunget ved mindreårige).
|
package/dist/index.cjs
CHANGED
|
@@ -46,15 +46,25 @@ var import_react_native10 = require("react-native");
|
|
|
46
46
|
// src/skjermbilde.ts
|
|
47
47
|
var import_react = require("react");
|
|
48
48
|
var import_react_native = require("react-native");
|
|
49
|
-
function
|
|
49
|
+
function storrelse(uri) {
|
|
50
|
+
return new Promise((resolve, reject) => import_react_native.Image.getSize(uri, (w, h) => resolve({ width: w, height: h }), reject));
|
|
51
|
+
}
|
|
52
|
+
function createScreenshotAdapter(captureRef, options = {}) {
|
|
53
|
+
const { pickImage, captureScreen } = options;
|
|
50
54
|
return {
|
|
51
|
-
async capture(ref,
|
|
52
|
-
const uri = await captureRef(ref, { format:
|
|
53
|
-
|
|
54
|
-
(resolve, reject) => import_react_native.Image.getSize(uri, (w, h) => resolve({ width: w, height: h }), reject)
|
|
55
|
-
);
|
|
56
|
-
return { uri, width, height };
|
|
55
|
+
async capture(ref, opts) {
|
|
56
|
+
const uri = await captureRef(ref, { format: opts.format, quality: opts.quality, result: "tmpfile" });
|
|
57
|
+
return { uri, ...await storrelse(uri) };
|
|
57
58
|
},
|
|
59
|
+
...pickImage ? {
|
|
60
|
+
async pick() {
|
|
61
|
+
const valgt = await pickImage();
|
|
62
|
+
if (!valgt) return null;
|
|
63
|
+
const { width, height } = valgt.width && valgt.height ? { width: valgt.width, height: valgt.height } : await storrelse(valgt.uri);
|
|
64
|
+
return { uri: valgt.uri, width, height };
|
|
65
|
+
}
|
|
66
|
+
} : {},
|
|
67
|
+
...captureScreen === false ? { captureScreen: false } : {},
|
|
58
68
|
measure(ref) {
|
|
59
69
|
return new Promise((resolve) => {
|
|
60
70
|
const view = ref.current;
|
|
@@ -538,6 +548,10 @@ var tekst = {
|
|
|
538
548
|
// 2f — skjermbilde (K4, DD-39, DD-40, DD-42)
|
|
539
549
|
leggVedSkjermbilde: "Legg ved skjermbilde",
|
|
540
550
|
leggVedHint: "Bildet tas f\xF8rst n\xE5r du trykker \u2014 du ser det f\xF8r det sendes.",
|
|
551
|
+
velgBilde: "Velg bilde",
|
|
552
|
+
velgBildeHint: "Fra bildene dine. Du ser det og kan maskere det f\xF8r det sendes.",
|
|
553
|
+
skjermbildeUnderGalleri: "Bildet er fra galleriet. Appen maskerer ingenting i det for deg \u2014 mal over det som ikke skal med.",
|
|
554
|
+
bildeFeilet: "kunne ikke hente bildet. Du kan sende uten.",
|
|
541
555
|
skjermbildeTittel: "Se over bildet",
|
|
542
556
|
skjermbildeUnder: "Bildet ble tatt da du trykket. Det du maskerer, ser vi aldri.",
|
|
543
557
|
maskering: "Maskering",
|
|
@@ -693,6 +707,8 @@ function Felt({
|
|
|
693
707
|
onSend,
|
|
694
708
|
sender,
|
|
695
709
|
onSkjermbilde,
|
|
710
|
+
onVelgBilde,
|
|
711
|
+
bildeNotat,
|
|
696
712
|
harVedlegg,
|
|
697
713
|
onFjernVedlegg
|
|
698
714
|
}) {
|
|
@@ -883,17 +899,31 @@ function Felt({
|
|
|
883
899
|
)
|
|
884
900
|
]
|
|
885
901
|
}
|
|
886
|
-
) : onSkjermbilde ? /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
902
|
+
) : onSkjermbilde || onVelgBilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: { gap: tema.space.sm }, children: [
|
|
903
|
+
onSkjermbilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
904
|
+
Btn,
|
|
905
|
+
{
|
|
906
|
+
variant: "secondary",
|
|
907
|
+
testID: "legg-ved-skjermbilde",
|
|
908
|
+
ikon: "\u{1F4F7}",
|
|
909
|
+
label: tekst.leggVedSkjermbilde,
|
|
910
|
+
hint: tekst.leggVedHint,
|
|
911
|
+
onPress: onSkjermbilde
|
|
912
|
+
}
|
|
913
|
+
) : null,
|
|
914
|
+
onVelgBilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
915
|
+
Btn,
|
|
916
|
+
{
|
|
917
|
+
variant: "secondary",
|
|
918
|
+
testID: "velg-bilde",
|
|
919
|
+
ikon: "\u{1F5BC}",
|
|
920
|
+
label: tekst.velgBilde,
|
|
921
|
+
hint: tekst.velgBildeHint,
|
|
922
|
+
onPress: onVelgBilde
|
|
923
|
+
}
|
|
924
|
+
) : null,
|
|
925
|
+
bildeNotat ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { testID: "bilde-notat", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Hint, { children: bildeNotat }) }) : null
|
|
926
|
+
] }) : null,
|
|
897
927
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: { borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.sm }, children: [
|
|
898
928
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
899
929
|
import_react_native3.Pressable,
|
|
@@ -1308,6 +1338,8 @@ function Skjermbilde({
|
|
|
1308
1338
|
rotStorrelse,
|
|
1309
1339
|
previewRef,
|
|
1310
1340
|
komponerer,
|
|
1341
|
+
kilde = "skjerm",
|
|
1342
|
+
notat,
|
|
1311
1343
|
onFjern,
|
|
1312
1344
|
onLeggVed
|
|
1313
1345
|
}) {
|
|
@@ -1400,7 +1432,8 @@ function Skjermbilde({
|
|
|
1400
1432
|
};
|
|
1401
1433
|
const a11y = tekst.skjermbildeA11y(automasker.length, egne.length, allTekst);
|
|
1402
1434
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { style: { flex: 1, gap: tema.space.md }, children: [
|
|
1403
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(H, { sub: tekst.skjermbildeUnder, children: tekst.skjermbildeTittel }),
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(H, { sub: kilde === "galleri" ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder, children: tekst.skjermbildeTittel }),
|
|
1436
|
+
notat ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native8.View, { testID: "bilde-notat", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: notat }) }) : null,
|
|
1404
1437
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { accessibilityRole: "toolbar", accessibilityLabel: tekst.maskering, style: { flexDirection: "row", gap: tema.space.sm }, children: [
|
|
1405
1438
|
knapp("felt", "\u25A3", tekst.maskerFelt),
|
|
1406
1439
|
knapp("pensel", "\u270E", tekst.tegnOver),
|
|
@@ -1505,7 +1538,8 @@ function Widget({
|
|
|
1505
1538
|
synlig,
|
|
1506
1539
|
apneOpsjoner,
|
|
1507
1540
|
onLukk,
|
|
1508
|
-
tenantName
|
|
1541
|
+
tenantName,
|
|
1542
|
+
imageStepNote
|
|
1509
1543
|
}) {
|
|
1510
1544
|
const tema = useTema();
|
|
1511
1545
|
const insets = (0, import_react10.useContext)(import_react_native_safe_area_context.SafeAreaInsetsContext) ?? import_react_native_safe_area_context.initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };
|
|
@@ -1528,9 +1562,13 @@ function Widget({
|
|
|
1528
1562
|
const [automasker, setAutomasker] = (0, import_react10.useState)([]);
|
|
1529
1563
|
const [rotStorrelse, setRotStorrelse] = (0, import_react10.useState)({ width: 1, height: 1 });
|
|
1530
1564
|
const [komponerer, setKomponerer] = (0, import_react10.useState)(false);
|
|
1565
|
+
const [kilde, setKilde] = (0, import_react10.useState)("skjerm");
|
|
1531
1566
|
const [vedlegg, setVedlegg] = (0, import_react10.useState)();
|
|
1532
1567
|
const [innstillinger, setInnstillinger] = (0, import_react10.useState)({ ...client.settings });
|
|
1533
1568
|
const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;
|
|
1569
|
+
const fangstMulig = skjermbildeMulig && skjermbilde?.adapter?.captureScreen !== false;
|
|
1570
|
+
const galleriMulig = skjermbildeMulig && typeof skjermbilde?.adapter?.pick === "function";
|
|
1571
|
+
const bildeNotat = typeof imageStepNote === "string" ? imageStepNote : imageStepNote?.[spor];
|
|
1534
1572
|
const nullstill = (0, import_react10.useCallback)(() => {
|
|
1535
1573
|
setSteg("valg");
|
|
1536
1574
|
setSpor("feil");
|
|
@@ -1607,11 +1645,28 @@ function Widget({
|
|
|
1607
1645
|
setAutomasker([]);
|
|
1608
1646
|
}
|
|
1609
1647
|
setBilde(fangst);
|
|
1648
|
+
setKilde("skjerm");
|
|
1610
1649
|
setSteg("skjermbilde");
|
|
1611
1650
|
} catch {
|
|
1612
1651
|
setFeil(tekst.skjermbildeFeilet);
|
|
1613
1652
|
}
|
|
1614
1653
|
}, [skjermbilde]);
|
|
1654
|
+
const velgBilde = (0, import_react10.useCallback)(async () => {
|
|
1655
|
+
const pick = skjermbilde?.adapter?.pick;
|
|
1656
|
+
if (!pick) return;
|
|
1657
|
+
setFeil(void 0);
|
|
1658
|
+
try {
|
|
1659
|
+
const valgt = await pick.call(skjermbilde.adapter);
|
|
1660
|
+
if (!valgt) return;
|
|
1661
|
+
setRotStorrelse({ width: valgt.width, height: valgt.height });
|
|
1662
|
+
setAutomasker([]);
|
|
1663
|
+
setBilde(valgt);
|
|
1664
|
+
setKilde("galleri");
|
|
1665
|
+
setSteg("skjermbilde");
|
|
1666
|
+
} catch {
|
|
1667
|
+
setFeil(tekst.bildeFeilet);
|
|
1668
|
+
}
|
|
1669
|
+
}, [skjermbilde]);
|
|
1615
1670
|
const leggVedBilde = (0, import_react10.useCallback)(async () => {
|
|
1616
1671
|
if (!skjermbilde?.adapter) return;
|
|
1617
1672
|
setKomponerer(true);
|
|
@@ -1775,7 +1830,9 @@ function Widget({
|
|
|
1775
1830
|
funn,
|
|
1776
1831
|
onSend: send,
|
|
1777
1832
|
sender,
|
|
1778
|
-
...
|
|
1833
|
+
...fangstMulig ? { onSkjermbilde: taSkjermbilde } : {},
|
|
1834
|
+
...galleriMulig ? { onVelgBilde: velgBilde } : {},
|
|
1835
|
+
...bildeNotat ? { bildeNotat } : {},
|
|
1779
1836
|
harVedlegg: vedlegg !== void 0,
|
|
1780
1837
|
onFjernVedlegg: fjernBilde
|
|
1781
1838
|
}
|
|
@@ -1788,6 +1845,8 @@ function Widget({
|
|
|
1788
1845
|
rotStorrelse,
|
|
1789
1846
|
previewRef,
|
|
1790
1847
|
komponerer,
|
|
1848
|
+
kilde,
|
|
1849
|
+
...bildeNotat ? { notat: bildeNotat } : {},
|
|
1791
1850
|
onFjern: fjernBilde,
|
|
1792
1851
|
onLeggVed: leggVedBilde
|
|
1793
1852
|
}
|
|
@@ -1835,7 +1894,8 @@ function InnspelProvider({
|
|
|
1835
1894
|
theme,
|
|
1836
1895
|
colorScheme = "dark",
|
|
1837
1896
|
tenantName,
|
|
1838
|
-
screenshot
|
|
1897
|
+
screenshot,
|
|
1898
|
+
imageStepNote
|
|
1839
1899
|
}) {
|
|
1840
1900
|
const [synlig, setSynlig] = (0, import_react11.useState)(false);
|
|
1841
1901
|
const [apneOpsjoner, setApneOpsjoner] = (0, import_react11.useState)();
|
|
@@ -1869,6 +1929,7 @@ function InnspelProvider({
|
|
|
1869
1929
|
synlig,
|
|
1870
1930
|
...apneOpsjoner ? { apneOpsjoner } : {},
|
|
1871
1931
|
...tenantName ? { tenantName } : {},
|
|
1932
|
+
...imageStepNote ? { imageStepNote } : {},
|
|
1872
1933
|
onLukk: close
|
|
1873
1934
|
}
|
|
1874
1935
|
)
|