@innspel/react-native 0.5.1 → 0.7.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 +89 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -3
- package/dist/index.d.ts +61 -3
- package/dist/index.js +89 -22
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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",
|
|
@@ -594,6 +608,8 @@ var tekst = {
|
|
|
594
608
|
mineTom: "Du har ikke sendt noe enn\xE5.",
|
|
595
609
|
mineIkkeSendt: "Ikke sendt enn\xE5",
|
|
596
610
|
mineSak: (nr) => `Sak ${nr}`,
|
|
611
|
+
// Leietakeren fjernet vedlegget. Bare AT — aldri hvorfor, av hvem eller når.
|
|
612
|
+
bildeFjernet: "Bildet er fjernet.",
|
|
597
613
|
svarFra: (leietaker) => `Svar fra ${leietaker}`,
|
|
598
614
|
svarFraGenerisk: "Svar",
|
|
599
615
|
sendNytt: "Send nytt innspill",
|
|
@@ -693,6 +709,8 @@ function Felt({
|
|
|
693
709
|
onSend,
|
|
694
710
|
sender,
|
|
695
711
|
onSkjermbilde,
|
|
712
|
+
onVelgBilde,
|
|
713
|
+
bildeNotat,
|
|
696
714
|
harVedlegg,
|
|
697
715
|
onFjernVedlegg
|
|
698
716
|
}) {
|
|
@@ -883,17 +901,31 @@ function Felt({
|
|
|
883
901
|
)
|
|
884
902
|
]
|
|
885
903
|
}
|
|
886
|
-
) : onSkjermbilde ? /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
904
|
+
) : onSkjermbilde || onVelgBilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: { gap: tema.space.sm }, children: [
|
|
905
|
+
onSkjermbilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
906
|
+
Btn,
|
|
907
|
+
{
|
|
908
|
+
variant: "secondary",
|
|
909
|
+
testID: "legg-ved-skjermbilde",
|
|
910
|
+
ikon: "\u{1F4F7}",
|
|
911
|
+
label: tekst.leggVedSkjermbilde,
|
|
912
|
+
hint: tekst.leggVedHint,
|
|
913
|
+
onPress: onSkjermbilde
|
|
914
|
+
}
|
|
915
|
+
) : null,
|
|
916
|
+
onVelgBilde ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
917
|
+
Btn,
|
|
918
|
+
{
|
|
919
|
+
variant: "secondary",
|
|
920
|
+
testID: "velg-bilde",
|
|
921
|
+
ikon: "\u{1F5BC}",
|
|
922
|
+
label: tekst.velgBilde,
|
|
923
|
+
hint: tekst.velgBildeHint,
|
|
924
|
+
onPress: onVelgBilde
|
|
925
|
+
}
|
|
926
|
+
) : null,
|
|
927
|
+
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
|
|
928
|
+
] }) : null,
|
|
897
929
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: { borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.sm }, children: [
|
|
898
930
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
899
931
|
import_react_native3.Pressable,
|
|
@@ -1266,6 +1298,10 @@ function MineInnspill({
|
|
|
1266
1298
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatusPill, { ikon: v.ikon, etikett: v.etikett, farge: v.farge }),
|
|
1267
1299
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Hint, { children: v.lofte })
|
|
1268
1300
|
] }),
|
|
1301
|
+
!venter && rad.attachmentRemoved ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native7.View, { testID: `bilde-fjernet-${rad.id}`, style: { flexDirection: "row", gap: tema.space.xs, alignItems: "center" }, children: [
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native7.Text, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { fontSize: tema.font.small }, children: "\u{1F5D1}" }),
|
|
1303
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Hint, { children: tekst.bildeFjernet })
|
|
1304
|
+
] }) : null,
|
|
1269
1305
|
svar ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1270
1306
|
import_react_native7.View,
|
|
1271
1307
|
{
|
|
@@ -1308,6 +1344,8 @@ function Skjermbilde({
|
|
|
1308
1344
|
rotStorrelse,
|
|
1309
1345
|
previewRef,
|
|
1310
1346
|
komponerer,
|
|
1347
|
+
kilde = "skjerm",
|
|
1348
|
+
notat,
|
|
1311
1349
|
onFjern,
|
|
1312
1350
|
onLeggVed
|
|
1313
1351
|
}) {
|
|
@@ -1400,7 +1438,8 @@ function Skjermbilde({
|
|
|
1400
1438
|
};
|
|
1401
1439
|
const a11y = tekst.skjermbildeA11y(automasker.length, egne.length, allTekst);
|
|
1402
1440
|
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 }),
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(H, { sub: kilde === "galleri" ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder, children: tekst.skjermbildeTittel }),
|
|
1442
|
+
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
1443
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native8.View, { accessibilityRole: "toolbar", accessibilityLabel: tekst.maskering, style: { flexDirection: "row", gap: tema.space.sm }, children: [
|
|
1405
1444
|
knapp("felt", "\u25A3", tekst.maskerFelt),
|
|
1406
1445
|
knapp("pensel", "\u270E", tekst.tegnOver),
|
|
@@ -1505,7 +1544,8 @@ function Widget({
|
|
|
1505
1544
|
synlig,
|
|
1506
1545
|
apneOpsjoner,
|
|
1507
1546
|
onLukk,
|
|
1508
|
-
tenantName
|
|
1547
|
+
tenantName,
|
|
1548
|
+
imageStepNote
|
|
1509
1549
|
}) {
|
|
1510
1550
|
const tema = useTema();
|
|
1511
1551
|
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 +1568,13 @@ function Widget({
|
|
|
1528
1568
|
const [automasker, setAutomasker] = (0, import_react10.useState)([]);
|
|
1529
1569
|
const [rotStorrelse, setRotStorrelse] = (0, import_react10.useState)({ width: 1, height: 1 });
|
|
1530
1570
|
const [komponerer, setKomponerer] = (0, import_react10.useState)(false);
|
|
1571
|
+
const [kilde, setKilde] = (0, import_react10.useState)("skjerm");
|
|
1531
1572
|
const [vedlegg, setVedlegg] = (0, import_react10.useState)();
|
|
1532
1573
|
const [innstillinger, setInnstillinger] = (0, import_react10.useState)({ ...client.settings });
|
|
1533
1574
|
const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;
|
|
1575
|
+
const fangstMulig = skjermbildeMulig && skjermbilde?.adapter?.captureScreen !== false;
|
|
1576
|
+
const galleriMulig = skjermbildeMulig && typeof skjermbilde?.adapter?.pick === "function";
|
|
1577
|
+
const bildeNotat = typeof imageStepNote === "string" ? imageStepNote : imageStepNote?.[spor];
|
|
1534
1578
|
const nullstill = (0, import_react10.useCallback)(() => {
|
|
1535
1579
|
setSteg("valg");
|
|
1536
1580
|
setSpor("feil");
|
|
@@ -1607,11 +1651,28 @@ function Widget({
|
|
|
1607
1651
|
setAutomasker([]);
|
|
1608
1652
|
}
|
|
1609
1653
|
setBilde(fangst);
|
|
1654
|
+
setKilde("skjerm");
|
|
1610
1655
|
setSteg("skjermbilde");
|
|
1611
1656
|
} catch {
|
|
1612
1657
|
setFeil(tekst.skjermbildeFeilet);
|
|
1613
1658
|
}
|
|
1614
1659
|
}, [skjermbilde]);
|
|
1660
|
+
const velgBilde = (0, import_react10.useCallback)(async () => {
|
|
1661
|
+
const pick = skjermbilde?.adapter?.pick;
|
|
1662
|
+
if (!pick) return;
|
|
1663
|
+
setFeil(void 0);
|
|
1664
|
+
try {
|
|
1665
|
+
const valgt = await pick.call(skjermbilde.adapter);
|
|
1666
|
+
if (!valgt) return;
|
|
1667
|
+
setRotStorrelse({ width: valgt.width, height: valgt.height });
|
|
1668
|
+
setAutomasker([]);
|
|
1669
|
+
setBilde(valgt);
|
|
1670
|
+
setKilde("galleri");
|
|
1671
|
+
setSteg("skjermbilde");
|
|
1672
|
+
} catch {
|
|
1673
|
+
setFeil(tekst.bildeFeilet);
|
|
1674
|
+
}
|
|
1675
|
+
}, [skjermbilde]);
|
|
1615
1676
|
const leggVedBilde = (0, import_react10.useCallback)(async () => {
|
|
1616
1677
|
if (!skjermbilde?.adapter) return;
|
|
1617
1678
|
setKomponerer(true);
|
|
@@ -1775,7 +1836,9 @@ function Widget({
|
|
|
1775
1836
|
funn,
|
|
1776
1837
|
onSend: send,
|
|
1777
1838
|
sender,
|
|
1778
|
-
...
|
|
1839
|
+
...fangstMulig ? { onSkjermbilde: taSkjermbilde } : {},
|
|
1840
|
+
...galleriMulig ? { onVelgBilde: velgBilde } : {},
|
|
1841
|
+
...bildeNotat ? { bildeNotat } : {},
|
|
1779
1842
|
harVedlegg: vedlegg !== void 0,
|
|
1780
1843
|
onFjernVedlegg: fjernBilde
|
|
1781
1844
|
}
|
|
@@ -1788,6 +1851,8 @@ function Widget({
|
|
|
1788
1851
|
rotStorrelse,
|
|
1789
1852
|
previewRef,
|
|
1790
1853
|
komponerer,
|
|
1854
|
+
kilde,
|
|
1855
|
+
...bildeNotat ? { notat: bildeNotat } : {},
|
|
1791
1856
|
onFjern: fjernBilde,
|
|
1792
1857
|
onLeggVed: leggVedBilde
|
|
1793
1858
|
}
|
|
@@ -1835,7 +1900,8 @@ function InnspelProvider({
|
|
|
1835
1900
|
theme,
|
|
1836
1901
|
colorScheme = "dark",
|
|
1837
1902
|
tenantName,
|
|
1838
|
-
screenshot
|
|
1903
|
+
screenshot,
|
|
1904
|
+
imageStepNote
|
|
1839
1905
|
}) {
|
|
1840
1906
|
const [synlig, setSynlig] = (0, import_react11.useState)(false);
|
|
1841
1907
|
const [apneOpsjoner, setApneOpsjoner] = (0, import_react11.useState)();
|
|
@@ -1869,6 +1935,7 @@ function InnspelProvider({
|
|
|
1869
1935
|
synlig,
|
|
1870
1936
|
...apneOpsjoner ? { apneOpsjoner } : {},
|
|
1871
1937
|
...tenantName ? { tenantName } : {},
|
|
1938
|
+
...imageStepNote ? { imageStepNote } : {},
|
|
1872
1939
|
onLukk: close
|
|
1873
1940
|
}
|
|
1874
1941
|
)
|