@innspel/react-native 0.2.1 → 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/README.md +20 -2
- package/dist/index.cjs +344 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -4
- package/dist/index.d.ts +61 -4
- package/dist/index.js +343 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MaskRect, InnspelClient, OpenFeedbackOptions, InnspelStorage, SubmissionStatus, SubmissionType } from '@innspel/core';
|
|
2
|
-
export { AttachmentInput, AttachmentOutcome, CaptureInput, ContextInput, InnspelClient, InnspelOptions, InnspelStorage, MySubmission, OpenFeedbackOptions, SubmissionStatusView } from '@innspel/core';
|
|
1
|
+
import { MaskRect, InnspelClient, OpenFeedbackOptions, ParticipationView, InnspelStorage, SubmissionStatus, SubmissionType } from '@innspel/core';
|
|
2
|
+
export { AttachmentInput, AttachmentOutcome, CaptureInput, ContextInput, InnspelClient, InnspelOptions, InnspelStorage, InvitationView, MyPrograms, MySubmission, OpenFeedbackOptions, ParticipationView, ProgramTask, ProgramView, SubmissionStatusView } from '@innspel/core';
|
|
3
3
|
import React, { RefObject, ComponentRef } from 'react';
|
|
4
4
|
import { View, StyleProp, ViewStyle } from 'react-native';
|
|
5
5
|
|
|
@@ -55,7 +55,7 @@ type CaptureRefFn = (ref: RefObject<ViewRef | null> | ViewRef, options: {
|
|
|
55
55
|
declare function createScreenshotAdapter(captureRef: CaptureRefFn): ScreenshotAdapter;
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
* tokens.ts — GENERERT fra theme/theme.ts (avtrykk
|
|
58
|
+
* tokens.ts — GENERERT fra theme/theme.ts (avtrykk e9fb0cf68373).
|
|
59
59
|
* Rediger aldri denne filen. Endre temaet i kilden og kjør
|
|
60
60
|
* `node scripts/generate-tokens.ts`, som CI verifiserer med `--check`.
|
|
61
61
|
*
|
|
@@ -364,6 +364,32 @@ declare function InnspelPrivate({ children, style }: {
|
|
|
364
364
|
style?: StyleProp<ViewStyle>;
|
|
365
365
|
}): React.JSX.Element;
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Betaprogrammet i vertsappen: 3a banneret, 3b aksepten og deltakelsen med
|
|
369
|
+
* «Gå ut» (DD-36). Sett den der vertsappen vil ha invitasjonen — typisk øverst
|
|
370
|
+
* på hjemskjermen. Uten invitasjon og uten deltakelse rendrer den INGENTING;
|
|
371
|
+
* det er wireframens «tom → fanen skjules helt», ikke en tom tilstand.
|
|
372
|
+
*
|
|
373
|
+
* **Tokenet kommer fra verten** (DD-12). Plattformen sender aldri invitasjonen:
|
|
374
|
+
* leietakeren får `program.invitation_created` med tokenet, løser pseudonymet til
|
|
375
|
+
* sin egen bruker og sender lenken i sin egen kanal. Verten fanger tokenet fra
|
|
376
|
+
* dyplenken og gir det hit. Uten det viser banneret fortsatt invitasjonen — men
|
|
377
|
+
* «Bli med» er inaktiv, med lenken forklart, i stedet for å feile ved trykk.
|
|
378
|
+
*
|
|
379
|
+
* Oppgavene, «Hvordan gikk det?» og oppfølgingene er M3.2.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* <InnspelProgram invitationToken={tokenFraDyplenke} />
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
declare function InnspelProgram({ invitationToken, onEndring, }: {
|
|
387
|
+
/** Engangs-tokenet fra leietakerens egen kanal, typisk fanget fra en dyplenke. */
|
|
388
|
+
invitationToken?: string;
|
|
389
|
+
/** Kalles når testeren blir med eller går ut — for vertens egen navigasjon. */
|
|
390
|
+
onEndring?: (deltakelse: ParticipationView | null) => void;
|
|
391
|
+
}): React.JSX.Element | null;
|
|
392
|
+
|
|
367
393
|
/**
|
|
368
394
|
* Formen på lagringspakkene i React Native-økosystemet: AsyncStorage, MMKV med
|
|
369
395
|
* async-fasade, expo-secure-store. Alle tre har disse tre metodene.
|
|
@@ -525,6 +551,37 @@ declare const tekst: {
|
|
|
525
551
|
readonly svarFra: (leietaker: string) => string;
|
|
526
552
|
readonly svarFraGenerisk: "Svar";
|
|
527
553
|
readonly sendNytt: "Send nytt innspill";
|
|
554
|
+
readonly invitasjonRegion: "Invitasjon til betaprogram";
|
|
555
|
+
readonly invitasjonHva: (navn: string) => string;
|
|
556
|
+
readonly invitasjonKontakter: (maks: number) => string;
|
|
557
|
+
readonly lesMer: "Les mer og bli med";
|
|
558
|
+
readonly avvisInvitasjon: "Avvis invitasjonen";
|
|
559
|
+
readonly akseptHva: "Hva testes";
|
|
560
|
+
/** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */
|
|
561
|
+
readonly akseptTall: (oppgaver: number, minutter: number, periode: string, kontakter: number) => string;
|
|
562
|
+
readonly akseptOppgaver: "Hva vi ber om";
|
|
563
|
+
readonly akseptOppgaveTid: (minutter: number) => string;
|
|
564
|
+
readonly akseptKjenteFeil: (antall: number) => string;
|
|
565
|
+
readonly akseptKjenteFeilUnder: "Disse trenger du ikke melde — vi vet om dem.";
|
|
566
|
+
readonly akseptInnsamling: "Hva som samles inn";
|
|
567
|
+
readonly akseptInnsamlingTekst: "Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.";
|
|
568
|
+
readonly akseptVilkar: "Les vilkårene (åpnes i nettleser)";
|
|
569
|
+
readonly akseptVilkarHint: "Bare en lenke. Ingen avkryssing, ingen signatur — «Bli med» binder deg ikke til noe.";
|
|
570
|
+
readonly akseptIngenVilkar: "Ingen vilkår, ingen avtale — plattformen kjenner ikke navnet ditt og kan ikke inngå én.";
|
|
571
|
+
readonly akseptUtgang: "Du kan gå ut når som helst — herfra.";
|
|
572
|
+
readonly bliMed: "Bli med";
|
|
573
|
+
readonly bliMedHint: "Samtykket gjelder bare dette programmet.";
|
|
574
|
+
/** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */
|
|
575
|
+
readonly bliMedUtenToken: "Åpne lenken vi sendte deg for å bli med.";
|
|
576
|
+
readonly akseptFeil: (arsak: string) => string;
|
|
577
|
+
readonly deltakelseRegion: "Ditt betaprogram";
|
|
578
|
+
readonly deltakelsePeriode: (periode: string, brukt: number, maks: number) => string;
|
|
579
|
+
readonly deltakelseOppgaverKommer: "Oppgavene kan gjøres når det passer deg.";
|
|
580
|
+
readonly gaaUt: "Gå ut av programmet";
|
|
581
|
+
readonly gaaUtTittel: "Gå ut av programmet?";
|
|
582
|
+
readonly gaaUtTekst: (navn: string) => string;
|
|
583
|
+
readonly bliVaerende: "Bli værende";
|
|
584
|
+
readonly gaaUtBekreft: "Gå ut";
|
|
528
585
|
readonly tilbake: "Tilbake";
|
|
529
586
|
readonly lukk: "Lukk";
|
|
530
587
|
readonly venterPaaNett: "Venter på nett — sendes automatisk";
|
|
@@ -548,4 +605,4 @@ declare const lofte: {
|
|
|
548
605
|
readonly avvist: "Vi har svart på denne.";
|
|
549
606
|
};
|
|
550
607
|
|
|
551
|
-
export { type AsyncStorageLike, type CaptureOptions, type CaptureRefFn, type InnspelColors, InnspelPrivate, InnspelProvider, type InnspelTheme, type PartialTheme, type ScreenshotAdapter, type ScreenshotCapture, type StatusVisning, type Tema, byggTema, createMemoryStorage, createScreenshotAdapter, createStorage, t as darkTokens, light, lofte, screenRules, statusVisning, tekst, useInnspel, useTema, venterVisning };
|
|
608
|
+
export { type AsyncStorageLike, type CaptureOptions, type CaptureRefFn, type InnspelColors, InnspelPrivate, InnspelProgram, InnspelProvider, type InnspelTheme, type PartialTheme, type ScreenshotAdapter, type ScreenshotCapture, type StatusVisning, type Tema, byggTema, createMemoryStorage, createScreenshotAdapter, createStorage, t as darkTokens, light, lofte, screenRules, statusVisning, tekst, useInnspel, useTema, venterVisning };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MaskRect, InnspelClient, OpenFeedbackOptions, InnspelStorage, SubmissionStatus, SubmissionType } from '@innspel/core';
|
|
2
|
-
export { AttachmentInput, AttachmentOutcome, CaptureInput, ContextInput, InnspelClient, InnspelOptions, InnspelStorage, MySubmission, OpenFeedbackOptions, SubmissionStatusView } from '@innspel/core';
|
|
1
|
+
import { MaskRect, InnspelClient, OpenFeedbackOptions, ParticipationView, InnspelStorage, SubmissionStatus, SubmissionType } from '@innspel/core';
|
|
2
|
+
export { AttachmentInput, AttachmentOutcome, CaptureInput, ContextInput, InnspelClient, InnspelOptions, InnspelStorage, InvitationView, MyPrograms, MySubmission, OpenFeedbackOptions, ParticipationView, ProgramTask, ProgramView, SubmissionStatusView } from '@innspel/core';
|
|
3
3
|
import React, { RefObject, ComponentRef } from 'react';
|
|
4
4
|
import { View, StyleProp, ViewStyle } from 'react-native';
|
|
5
5
|
|
|
@@ -55,7 +55,7 @@ type CaptureRefFn = (ref: RefObject<ViewRef | null> | ViewRef, options: {
|
|
|
55
55
|
declare function createScreenshotAdapter(captureRef: CaptureRefFn): ScreenshotAdapter;
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
* tokens.ts — GENERERT fra theme/theme.ts (avtrykk
|
|
58
|
+
* tokens.ts — GENERERT fra theme/theme.ts (avtrykk e9fb0cf68373).
|
|
59
59
|
* Rediger aldri denne filen. Endre temaet i kilden og kjør
|
|
60
60
|
* `node scripts/generate-tokens.ts`, som CI verifiserer med `--check`.
|
|
61
61
|
*
|
|
@@ -364,6 +364,32 @@ declare function InnspelPrivate({ children, style }: {
|
|
|
364
364
|
style?: StyleProp<ViewStyle>;
|
|
365
365
|
}): React.JSX.Element;
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Betaprogrammet i vertsappen: 3a banneret, 3b aksepten og deltakelsen med
|
|
369
|
+
* «Gå ut» (DD-36). Sett den der vertsappen vil ha invitasjonen — typisk øverst
|
|
370
|
+
* på hjemskjermen. Uten invitasjon og uten deltakelse rendrer den INGENTING;
|
|
371
|
+
* det er wireframens «tom → fanen skjules helt», ikke en tom tilstand.
|
|
372
|
+
*
|
|
373
|
+
* **Tokenet kommer fra verten** (DD-12). Plattformen sender aldri invitasjonen:
|
|
374
|
+
* leietakeren får `program.invitation_created` med tokenet, løser pseudonymet til
|
|
375
|
+
* sin egen bruker og sender lenken i sin egen kanal. Verten fanger tokenet fra
|
|
376
|
+
* dyplenken og gir det hit. Uten det viser banneret fortsatt invitasjonen — men
|
|
377
|
+
* «Bli med» er inaktiv, med lenken forklart, i stedet for å feile ved trykk.
|
|
378
|
+
*
|
|
379
|
+
* Oppgavene, «Hvordan gikk det?» og oppfølgingene er M3.2.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* <InnspelProgram invitationToken={tokenFraDyplenke} />
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
declare function InnspelProgram({ invitationToken, onEndring, }: {
|
|
387
|
+
/** Engangs-tokenet fra leietakerens egen kanal, typisk fanget fra en dyplenke. */
|
|
388
|
+
invitationToken?: string;
|
|
389
|
+
/** Kalles når testeren blir med eller går ut — for vertens egen navigasjon. */
|
|
390
|
+
onEndring?: (deltakelse: ParticipationView | null) => void;
|
|
391
|
+
}): React.JSX.Element | null;
|
|
392
|
+
|
|
367
393
|
/**
|
|
368
394
|
* Formen på lagringspakkene i React Native-økosystemet: AsyncStorage, MMKV med
|
|
369
395
|
* async-fasade, expo-secure-store. Alle tre har disse tre metodene.
|
|
@@ -525,6 +551,37 @@ declare const tekst: {
|
|
|
525
551
|
readonly svarFra: (leietaker: string) => string;
|
|
526
552
|
readonly svarFraGenerisk: "Svar";
|
|
527
553
|
readonly sendNytt: "Send nytt innspill";
|
|
554
|
+
readonly invitasjonRegion: "Invitasjon til betaprogram";
|
|
555
|
+
readonly invitasjonHva: (navn: string) => string;
|
|
556
|
+
readonly invitasjonKontakter: (maks: number) => string;
|
|
557
|
+
readonly lesMer: "Les mer og bli med";
|
|
558
|
+
readonly avvisInvitasjon: "Avvis invitasjonen";
|
|
559
|
+
readonly akseptHva: "Hva testes";
|
|
560
|
+
/** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */
|
|
561
|
+
readonly akseptTall: (oppgaver: number, minutter: number, periode: string, kontakter: number) => string;
|
|
562
|
+
readonly akseptOppgaver: "Hva vi ber om";
|
|
563
|
+
readonly akseptOppgaveTid: (minutter: number) => string;
|
|
564
|
+
readonly akseptKjenteFeil: (antall: number) => string;
|
|
565
|
+
readonly akseptKjenteFeilUnder: "Disse trenger du ikke melde — vi vet om dem.";
|
|
566
|
+
readonly akseptInnsamling: "Hva som samles inn";
|
|
567
|
+
readonly akseptInnsamlingTekst: "Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.";
|
|
568
|
+
readonly akseptVilkar: "Les vilkårene (åpnes i nettleser)";
|
|
569
|
+
readonly akseptVilkarHint: "Bare en lenke. Ingen avkryssing, ingen signatur — «Bli med» binder deg ikke til noe.";
|
|
570
|
+
readonly akseptIngenVilkar: "Ingen vilkår, ingen avtale — plattformen kjenner ikke navnet ditt og kan ikke inngå én.";
|
|
571
|
+
readonly akseptUtgang: "Du kan gå ut når som helst — herfra.";
|
|
572
|
+
readonly bliMed: "Bli med";
|
|
573
|
+
readonly bliMedHint: "Samtykket gjelder bare dette programmet.";
|
|
574
|
+
/** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */
|
|
575
|
+
readonly bliMedUtenToken: "Åpne lenken vi sendte deg for å bli med.";
|
|
576
|
+
readonly akseptFeil: (arsak: string) => string;
|
|
577
|
+
readonly deltakelseRegion: "Ditt betaprogram";
|
|
578
|
+
readonly deltakelsePeriode: (periode: string, brukt: number, maks: number) => string;
|
|
579
|
+
readonly deltakelseOppgaverKommer: "Oppgavene kan gjøres når det passer deg.";
|
|
580
|
+
readonly gaaUt: "Gå ut av programmet";
|
|
581
|
+
readonly gaaUtTittel: "Gå ut av programmet?";
|
|
582
|
+
readonly gaaUtTekst: (navn: string) => string;
|
|
583
|
+
readonly bliVaerende: "Bli værende";
|
|
584
|
+
readonly gaaUtBekreft: "Gå ut";
|
|
528
585
|
readonly tilbake: "Tilbake";
|
|
529
586
|
readonly lukk: "Lukk";
|
|
530
587
|
readonly venterPaaNett: "Venter på nett — sendes automatisk";
|
|
@@ -548,4 +605,4 @@ declare const lofte: {
|
|
|
548
605
|
readonly avvist: "Vi har svart på denne.";
|
|
549
606
|
};
|
|
550
607
|
|
|
551
|
-
export { type AsyncStorageLike, type CaptureOptions, type CaptureRefFn, type InnspelColors, InnspelPrivate, InnspelProvider, type InnspelTheme, type PartialTheme, type ScreenshotAdapter, type ScreenshotCapture, type StatusVisning, type Tema, byggTema, createMemoryStorage, createScreenshotAdapter, createStorage, t as darkTokens, light, lofte, screenRules, statusVisning, tekst, useInnspel, useTema, venterVisning };
|
|
608
|
+
export { type AsyncStorageLike, type CaptureOptions, type CaptureRefFn, type InnspelColors, InnspelPrivate, InnspelProgram, InnspelProvider, type InnspelTheme, type PartialTheme, type ScreenshotAdapter, type ScreenshotCapture, type StatusVisning, type Tema, byggTema, createMemoryStorage, createScreenshotAdapter, createStorage, t as darkTokens, light, lofte, screenRules, statusVisning, tekst, useInnspel, useTema, venterVisning };
|
package/dist/index.js
CHANGED
|
@@ -546,6 +546,40 @@ var tekst = {
|
|
|
546
546
|
svarFra: (leietaker) => `Svar fra ${leietaker}`,
|
|
547
547
|
svarFraGenerisk: "Svar",
|
|
548
548
|
sendNytt: "Send nytt innspill",
|
|
549
|
+
// 3a — invitasjonsbanneret (DD-12)
|
|
550
|
+
invitasjonRegion: "Invitasjon til betaprogram",
|
|
551
|
+
invitasjonHva: (navn) => `Vil du teste \xAB${navn}\xBB?`,
|
|
552
|
+
invitasjonKontakter: (maks) => `Vi tar kontakt maks ${maks} ganger. Du kan g\xE5 ut n\xE5r som helst.`,
|
|
553
|
+
lesMer: "Les mer og bli med",
|
|
554
|
+
avvisInvitasjon: "Avvis invitasjonen",
|
|
555
|
+
// 3b — aksepten (DD-13, DD-32, DD-37)
|
|
556
|
+
akseptHva: "Hva testes",
|
|
557
|
+
/** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */
|
|
558
|
+
akseptTall: (oppgaver, minutter, periode2, kontakter) => `${oppgaver} oppgaver \xB7 ca. ${minutter} min hver \xB7 ${periode2} \xB7 maks ${kontakter} kontakter`,
|
|
559
|
+
akseptOppgaver: "Hva vi ber om",
|
|
560
|
+
akseptOppgaveTid: (minutter) => `ca. ${minutter} min`,
|
|
561
|
+
akseptKjenteFeil: (antall) => `Kjente feil (${antall})`,
|
|
562
|
+
akseptKjenteFeilUnder: "Disse trenger du ikke melde \u2014 vi vet om dem.",
|
|
563
|
+
akseptInnsamling: "Hva som samles inn",
|
|
564
|
+
akseptInnsamlingTekst: "Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.",
|
|
565
|
+
akseptVilkar: "Les vilk\xE5rene (\xE5pnes i nettleser)",
|
|
566
|
+
akseptVilkarHint: "Bare en lenke. Ingen avkryssing, ingen signatur \u2014 \xABBli med\xBB binder deg ikke til noe.",
|
|
567
|
+
akseptIngenVilkar: "Ingen vilk\xE5r, ingen avtale \u2014 plattformen kjenner ikke navnet ditt og kan ikke inng\xE5 \xE9n.",
|
|
568
|
+
akseptUtgang: "Du kan g\xE5 ut n\xE5r som helst \u2014 herfra.",
|
|
569
|
+
bliMed: "Bli med",
|
|
570
|
+
bliMedHint: "Samtykket gjelder bare dette programmet.",
|
|
571
|
+
/** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */
|
|
572
|
+
bliMedUtenToken: "\xC5pne lenken vi sendte deg for \xE5 bli med.",
|
|
573
|
+
akseptFeil: (arsak) => `Kunne ikke bli med: ${arsak}`,
|
|
574
|
+
// 3c (M3.1-delen) — deltakelsen og «Gå ut» (DD-36)
|
|
575
|
+
deltakelseRegion: "Ditt betaprogram",
|
|
576
|
+
deltakelsePeriode: (periode2, brukt, maks) => `${periode2} \xB7 ${brukt} av ${maks} kontakter brukt`,
|
|
577
|
+
deltakelseOppgaverKommer: "Oppgavene kan gj\xF8res n\xE5r det passer deg.",
|
|
578
|
+
gaaUt: "G\xE5 ut av programmet",
|
|
579
|
+
gaaUtTittel: "G\xE5 ut av programmet?",
|
|
580
|
+
gaaUtTekst: (navn) => `Du tas ut av testgruppen med en gang. \xAB${navn}\xBB sl\xE5s av for deg, og vi tar ikke kontakt igjen. Det du allerede har svart, beholdes.`,
|
|
581
|
+
bliVaerende: "Bli v\xE6rende",
|
|
582
|
+
gaaUtBekreft: "G\xE5 ut",
|
|
549
583
|
// Felles
|
|
550
584
|
tilbake: "Tilbake",
|
|
551
585
|
lukk: "Lukk",
|
|
@@ -1397,7 +1431,8 @@ function Widget({
|
|
|
1397
1431
|
const [rotStorrelse, setRotStorrelse] = useState3({ width: 1, height: 1 });
|
|
1398
1432
|
const [komponerer, setKomponerer] = useState3(false);
|
|
1399
1433
|
const [vedlegg, setVedlegg] = useState3();
|
|
1400
|
-
const
|
|
1434
|
+
const [innstillinger, setInnstillinger] = useState3({ ...client.settings });
|
|
1435
|
+
const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;
|
|
1401
1436
|
const nullstill = useCallback2(() => {
|
|
1402
1437
|
setSteg("valg");
|
|
1403
1438
|
setSpor("feil");
|
|
@@ -1421,6 +1456,7 @@ function Widget({
|
|
|
1421
1456
|
if (!synlig) return;
|
|
1422
1457
|
client.track({ name: "widget_opened" });
|
|
1423
1458
|
void client.queue.flush().catch(() => void 0);
|
|
1459
|
+
void client.loadSettings().then((s) => setInnstillinger({ ...s })).catch(() => void 0);
|
|
1424
1460
|
if (apneOpsjoner?.track) velgSpor(apneOpsjoner.track);
|
|
1425
1461
|
}, [synlig]);
|
|
1426
1462
|
const hentKort = useCallback2(async () => {
|
|
@@ -1623,8 +1659,8 @@ function Widget({
|
|
|
1623
1659
|
spor,
|
|
1624
1660
|
verdi,
|
|
1625
1661
|
onEndre: endreTekst,
|
|
1626
|
-
minTextLength:
|
|
1627
|
-
textMaxLength:
|
|
1662
|
+
minTextLength: innstillinger.minTextLength,
|
|
1663
|
+
textMaxLength: innstillinger.textMaxLength,
|
|
1628
1664
|
kontekst: client.context,
|
|
1629
1665
|
fjernedeFelter: fjernede,
|
|
1630
1666
|
onFjernKontekst: (f) => setFjernede((x) => [...x, f]),
|
|
@@ -1754,6 +1790,309 @@ function InnspelPrivate({ children, style }) {
|
|
|
1754
1790
|
return /* @__PURE__ */ jsx10(View10, { ref, collapsable: false, style, testID: "innspel-privat", children });
|
|
1755
1791
|
}
|
|
1756
1792
|
|
|
1793
|
+
// src/program/InnspelProgram.tsx
|
|
1794
|
+
import { InnspelApiError as InnspelApiError2 } from "@innspel/core";
|
|
1795
|
+
import { useCallback as useCallback4, useEffect as useEffect3, useState as useState5 } from "react";
|
|
1796
|
+
import { Modal as Modal3, Pressable as Pressable7, Text as Text10, View as View12 } from "react-native";
|
|
1797
|
+
|
|
1798
|
+
// src/program/Aksept.tsx
|
|
1799
|
+
import "react";
|
|
1800
|
+
import { Linking, Modal as Modal2, Pressable as Pressable6, ScrollView as ScrollView2, Text as Text9, View as View11 } from "react-native";
|
|
1801
|
+
|
|
1802
|
+
// src/program/periode.ts
|
|
1803
|
+
var MANEDER = [
|
|
1804
|
+
"januar",
|
|
1805
|
+
"februar",
|
|
1806
|
+
"mars",
|
|
1807
|
+
"april",
|
|
1808
|
+
"mai",
|
|
1809
|
+
"juni",
|
|
1810
|
+
"juli",
|
|
1811
|
+
"august",
|
|
1812
|
+
"september",
|
|
1813
|
+
"oktober",
|
|
1814
|
+
"november",
|
|
1815
|
+
"desember"
|
|
1816
|
+
];
|
|
1817
|
+
function periode(opensAt, closesAt) {
|
|
1818
|
+
const fra = new Date(opensAt);
|
|
1819
|
+
const til = new Date(closesAt);
|
|
1820
|
+
if (Number.isNaN(fra.getTime()) || Number.isNaN(til.getTime())) return "";
|
|
1821
|
+
const sammeManed = fra.getMonth() === til.getMonth() && fra.getFullYear() === til.getFullYear();
|
|
1822
|
+
return sammeManed ? `${fra.getDate()}.\u2013${til.getDate()}. ${MANEDER[til.getMonth()]}` : `${fra.getDate()}. ${MANEDER[fra.getMonth()]} \u2013 ${til.getDate()}. ${MANEDER[til.getMonth()]}`;
|
|
1823
|
+
}
|
|
1824
|
+
function minutterPerOppgave(tasks) {
|
|
1825
|
+
if (tasks.length === 0) return 0;
|
|
1826
|
+
return Math.round(tasks.reduce((sum, t2) => sum + t2.estimatedMinutes, 0) / tasks.length);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
// src/program/Aksept.tsx
|
|
1830
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1831
|
+
function Aksept({
|
|
1832
|
+
program,
|
|
1833
|
+
harToken,
|
|
1834
|
+
sender,
|
|
1835
|
+
feil,
|
|
1836
|
+
onBliMed,
|
|
1837
|
+
onLukk
|
|
1838
|
+
}) {
|
|
1839
|
+
const tema = useTema();
|
|
1840
|
+
const tall = tekst.akseptTall(
|
|
1841
|
+
program.tasks.length,
|
|
1842
|
+
minutterPerOppgave(program.tasks),
|
|
1843
|
+
periode(program.opensAt, program.closesAt),
|
|
1844
|
+
program.maxContacts
|
|
1845
|
+
);
|
|
1846
|
+
return /* @__PURE__ */ jsx11(Modal2, { visible: true, transparent: true, animationType: "slide", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ jsx11(View11, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ jsxs10(
|
|
1847
|
+
View11,
|
|
1848
|
+
{
|
|
1849
|
+
testID: "program-aksept",
|
|
1850
|
+
accessibilityViewIsModal: true,
|
|
1851
|
+
style: {
|
|
1852
|
+
backgroundColor: tema.color.bg,
|
|
1853
|
+
borderTopLeftRadius: tema.radius.lg * 2,
|
|
1854
|
+
borderTopRightRadius: tema.radius.lg * 2,
|
|
1855
|
+
padding: tema.screenPadding,
|
|
1856
|
+
gap: tema.space.md,
|
|
1857
|
+
maxHeight: "92%",
|
|
1858
|
+
minHeight: "60%"
|
|
1859
|
+
},
|
|
1860
|
+
children: [
|
|
1861
|
+
/* @__PURE__ */ jsxs10(View11, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
1862
|
+
/* @__PURE__ */ jsx11(Btn, { variant: "ghost", testID: "aksept-tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: onLukk }),
|
|
1863
|
+
/* @__PURE__ */ jsx11(View11, {})
|
|
1864
|
+
] }),
|
|
1865
|
+
feil ? /* @__PURE__ */ jsx11(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
|
|
1866
|
+
/* @__PURE__ */ jsxs10(ScrollView2, { contentContainerStyle: { gap: tema.space.md }, children: [
|
|
1867
|
+
/* @__PURE__ */ jsx11(H, { sub: tekst.akseptHva, children: program.name }),
|
|
1868
|
+
/* @__PURE__ */ jsx11(
|
|
1869
|
+
Text9,
|
|
1870
|
+
{
|
|
1871
|
+
accessibilityRole: "text",
|
|
1872
|
+
style: {
|
|
1873
|
+
color: tema.color.textPrimary,
|
|
1874
|
+
fontSize: tema.font.body,
|
|
1875
|
+
lineHeight: tema.lineHeight.body,
|
|
1876
|
+
fontWeight: tema.weight.semibold
|
|
1877
|
+
},
|
|
1878
|
+
children: tall
|
|
1879
|
+
}
|
|
1880
|
+
),
|
|
1881
|
+
/* @__PURE__ */ jsx11(Text9, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: program.hypothesis }),
|
|
1882
|
+
/* @__PURE__ */ jsxs10(Card, { children: [
|
|
1883
|
+
/* @__PURE__ */ jsx11(H, { children: tekst.akseptOppgaver }),
|
|
1884
|
+
program.tasks.map((o) => /* @__PURE__ */ jsxs10(View11, { style: { gap: tema.space.xs }, children: [
|
|
1885
|
+
/* @__PURE__ */ jsx11(Text9, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: o.title }),
|
|
1886
|
+
/* @__PURE__ */ jsxs10(Hint, { children: [
|
|
1887
|
+
tekst.akseptOppgaveTid(o.estimatedMinutes),
|
|
1888
|
+
o.screenHint ? ` \xB7 ${o.screenHint}` : ""
|
|
1889
|
+
] })
|
|
1890
|
+
] }, o.id))
|
|
1891
|
+
] }),
|
|
1892
|
+
program.knownIssues.length > 0 ? /* @__PURE__ */ jsxs10(Card, { children: [
|
|
1893
|
+
/* @__PURE__ */ jsx11(H, { sub: tekst.akseptKjenteFeilUnder, children: tekst.akseptKjenteFeil(program.knownIssues.length) }),
|
|
1894
|
+
program.knownIssues.map((k) => /* @__PURE__ */ jsxs10(View11, { style: { gap: tema.space.xs }, children: [
|
|
1895
|
+
/* @__PURE__ */ jsx11(Text9, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: k.title }),
|
|
1896
|
+
k.workaround ? /* @__PURE__ */ jsxs10(Text9, { style: { color: tema.color.textSecondary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: [
|
|
1897
|
+
tekst.omvei,
|
|
1898
|
+
" ",
|
|
1899
|
+
k.workaround
|
|
1900
|
+
] }) : null,
|
|
1901
|
+
k.fixedIn ? /* @__PURE__ */ jsx11(
|
|
1902
|
+
StatusPill,
|
|
1903
|
+
{
|
|
1904
|
+
ikon: k.status === "fikset" ? "\u2713" : "\u{1F527}",
|
|
1905
|
+
etikett: k.status === "fikset" ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn),
|
|
1906
|
+
farge: k.status === "fikset" ? "success" : "info"
|
|
1907
|
+
}
|
|
1908
|
+
) : null
|
|
1909
|
+
] }, k.id))
|
|
1910
|
+
] }) : null,
|
|
1911
|
+
/* @__PURE__ */ jsxs10(Card, { children: [
|
|
1912
|
+
/* @__PURE__ */ jsx11(H, { sub: tekst.akseptInnsamlingTekst, children: tekst.akseptInnsamling }),
|
|
1913
|
+
/* @__PURE__ */ jsx11(Hint, { children: tekst.kontekstAldri })
|
|
1914
|
+
] }),
|
|
1915
|
+
program.termsUrl && !program.commitmentFree ? /* @__PURE__ */ jsxs10(View11, { style: { gap: tema.space.xs }, children: [
|
|
1916
|
+
/* @__PURE__ */ jsx11(
|
|
1917
|
+
Pressable6,
|
|
1918
|
+
{
|
|
1919
|
+
testID: "vilkar-lenke",
|
|
1920
|
+
accessibilityRole: "link",
|
|
1921
|
+
accessibilityLabel: tekst.akseptVilkar,
|
|
1922
|
+
onPress: () => void Linking.openURL(String(program.termsUrl)),
|
|
1923
|
+
style: { minHeight: tema.touch, justifyContent: "center" },
|
|
1924
|
+
children: /* @__PURE__ */ jsxs10(Text9, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, textDecorationLine: "underline" }, children: [
|
|
1925
|
+
"\u{1F517} ",
|
|
1926
|
+
tekst.akseptVilkar
|
|
1927
|
+
] })
|
|
1928
|
+
}
|
|
1929
|
+
),
|
|
1930
|
+
/* @__PURE__ */ jsx11(Hint, { children: tekst.akseptVilkarHint })
|
|
1931
|
+
] }) : /* @__PURE__ */ jsx11(Hint, { children: tekst.akseptIngenVilkar }),
|
|
1932
|
+
/* @__PURE__ */ jsxs10(Text9, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: [
|
|
1933
|
+
"\u{1F6AA} ",
|
|
1934
|
+
tekst.akseptUtgang
|
|
1935
|
+
] })
|
|
1936
|
+
] }),
|
|
1937
|
+
/* @__PURE__ */ jsx11(
|
|
1938
|
+
Btn,
|
|
1939
|
+
{
|
|
1940
|
+
testID: "bli-med",
|
|
1941
|
+
label: tekst.bliMed,
|
|
1942
|
+
disabled: !harToken || sender,
|
|
1943
|
+
hint: harToken ? tekst.bliMedHint : tekst.bliMedUtenToken,
|
|
1944
|
+
onPress: onBliMed
|
|
1945
|
+
}
|
|
1946
|
+
)
|
|
1947
|
+
]
|
|
1948
|
+
}
|
|
1949
|
+
) }) });
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// src/program/InnspelProgram.tsx
|
|
1953
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1954
|
+
function InnspelProgram({
|
|
1955
|
+
invitationToken,
|
|
1956
|
+
onEndring
|
|
1957
|
+
}) {
|
|
1958
|
+
const { client } = useInnspel();
|
|
1959
|
+
const tema = useTema();
|
|
1960
|
+
const [mine, setMine] = useState5();
|
|
1961
|
+
const [deltakelse, setDeltakelse] = useState5();
|
|
1962
|
+
const [viserAksept, setViserAksept] = useState5(false);
|
|
1963
|
+
const [viserGaaUt, setViserGaaUt] = useState5(false);
|
|
1964
|
+
const [avvist, setAvvist] = useState5(false);
|
|
1965
|
+
const [sender, setSender] = useState5(false);
|
|
1966
|
+
const [feil, setFeil] = useState5();
|
|
1967
|
+
useEffect3(() => {
|
|
1968
|
+
if (client.isAnonymous) return;
|
|
1969
|
+
let levende = true;
|
|
1970
|
+
void client.programs.list().then((svar) => {
|
|
1971
|
+
if (!levende) return;
|
|
1972
|
+
setMine(svar);
|
|
1973
|
+
setDeltakelse(svar.participations.find((p) => p.status !== "trukket"));
|
|
1974
|
+
}).catch(() => void 0);
|
|
1975
|
+
return () => {
|
|
1976
|
+
levende = false;
|
|
1977
|
+
};
|
|
1978
|
+
}, [client]);
|
|
1979
|
+
const bliMed = useCallback4(async () => {
|
|
1980
|
+
if (!invitationToken) return;
|
|
1981
|
+
setSender(true);
|
|
1982
|
+
setFeil(void 0);
|
|
1983
|
+
try {
|
|
1984
|
+
const ny = await client.programs.accept(invitationToken);
|
|
1985
|
+
setDeltakelse(ny);
|
|
1986
|
+
setViserAksept(false);
|
|
1987
|
+
onEndring?.(ny);
|
|
1988
|
+
} catch (e) {
|
|
1989
|
+
setFeil(e instanceof InnspelApiError2 ? e.message : "tjeneren svarte ikke.");
|
|
1990
|
+
} finally {
|
|
1991
|
+
setSender(false);
|
|
1992
|
+
}
|
|
1993
|
+
}, [client, invitationToken, onEndring]);
|
|
1994
|
+
const gaaUt = useCallback4(async () => {
|
|
1995
|
+
if (!deltakelse) return;
|
|
1996
|
+
setSender(true);
|
|
1997
|
+
try {
|
|
1998
|
+
await client.programs.withdraw(deltakelse.id);
|
|
1999
|
+
setDeltakelse(void 0);
|
|
2000
|
+
setViserGaaUt(false);
|
|
2001
|
+
onEndring?.(null);
|
|
2002
|
+
} catch (e) {
|
|
2003
|
+
setFeil(e instanceof InnspelApiError2 ? e.message : "tjeneren svarte ikke.");
|
|
2004
|
+
} finally {
|
|
2005
|
+
setSender(false);
|
|
2006
|
+
}
|
|
2007
|
+
}, [client, deltakelse, onEndring]);
|
|
2008
|
+
const invitasjon = deltakelse ? void 0 : mine?.invitations[0];
|
|
2009
|
+
const program = deltakelse?.program ?? invitasjon?.program;
|
|
2010
|
+
if (!program) return null;
|
|
2011
|
+
if (deltakelse) {
|
|
2012
|
+
return /* @__PURE__ */ jsxs11(View12, { testID: "program-deltakelse", accessibilityLabel: tekst.deltakelseRegion, style: { gap: tema.space.sm }, children: [
|
|
2013
|
+
/* @__PURE__ */ jsxs11(Card, { children: [
|
|
2014
|
+
/* @__PURE__ */ jsx12(H, { sub: tekst.deltakelsePeriode(periode(program.opensAt, program.closesAt), deltakelse.contactsSent, program.maxContacts), children: program.name }),
|
|
2015
|
+
/* @__PURE__ */ jsx12(Hint, { children: tekst.deltakelseOppgaverKommer }),
|
|
2016
|
+
/* @__PURE__ */ jsx12(Btn, { variant: "ghost", testID: "gaa-ut", ikon: "\u{1F6AA}", label: tekst.gaaUt, onPress: () => setViserGaaUt(true) })
|
|
2017
|
+
] }),
|
|
2018
|
+
viserGaaUt ? /* @__PURE__ */ jsx12(Modal3, { visible: true, transparent: true, animationType: "fade", onRequestClose: () => setViserGaaUt(false), accessibilityViewIsModal: true, children: /* @__PURE__ */ jsx12(View12, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", padding: tema.space.md }, children: /* @__PURE__ */ jsxs11(
|
|
2019
|
+
View12,
|
|
2020
|
+
{
|
|
2021
|
+
testID: "gaa-ut-dialog",
|
|
2022
|
+
accessibilityViewIsModal: true,
|
|
2023
|
+
style: {
|
|
2024
|
+
backgroundColor: tema.color.surface,
|
|
2025
|
+
borderRadius: tema.radius.lg,
|
|
2026
|
+
borderWidth: tema.hairline,
|
|
2027
|
+
borderColor: tema.color.borderStrong,
|
|
2028
|
+
padding: tema.space.md,
|
|
2029
|
+
gap: tema.space.md
|
|
2030
|
+
},
|
|
2031
|
+
children: [
|
|
2032
|
+
/* @__PURE__ */ jsx12(H, { children: tekst.gaaUtTittel }),
|
|
2033
|
+
/* @__PURE__ */ jsx12(Text10, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.gaaUtTekst(program.name) }),
|
|
2034
|
+
/* @__PURE__ */ jsxs11(View12, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
|
|
2035
|
+
/* @__PURE__ */ jsx12(Btn, { grow: true, variant: "secondary", testID: "bli-vaerende", label: tekst.bliVaerende, onPress: () => setViserGaaUt(false) }),
|
|
2036
|
+
/* @__PURE__ */ jsx12(Btn, { grow: true, variant: "danger", testID: "bekreft-gaa-ut", ikon: "\u{1F6AA}", label: tekst.gaaUtBekreft, disabled: sender, onPress: () => void gaaUt() })
|
|
2037
|
+
] })
|
|
2038
|
+
]
|
|
2039
|
+
}
|
|
2040
|
+
) }) }) : null
|
|
2041
|
+
] });
|
|
2042
|
+
}
|
|
2043
|
+
if (!invitasjon || avvist) return null;
|
|
2044
|
+
return /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2045
|
+
/* @__PURE__ */ jsxs11(
|
|
2046
|
+
View12,
|
|
2047
|
+
{
|
|
2048
|
+
testID: "program-banner",
|
|
2049
|
+
accessibilityLabel: tekst.invitasjonRegion,
|
|
2050
|
+
style: {
|
|
2051
|
+
backgroundColor: tema.color.brandBg,
|
|
2052
|
+
borderRadius: tema.radius.lg,
|
|
2053
|
+
borderWidth: tema.hairline,
|
|
2054
|
+
borderColor: tema.color.brand,
|
|
2055
|
+
padding: tema.space.md,
|
|
2056
|
+
gap: tema.space.sm
|
|
2057
|
+
},
|
|
2058
|
+
children: [
|
|
2059
|
+
/* @__PURE__ */ jsxs11(View12, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
|
|
2060
|
+
/* @__PURE__ */ jsx12(Text10, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { fontSize: tema.font.h3 }, children: "\u{1F9EA}" }),
|
|
2061
|
+
/* @__PURE__ */ jsxs11(View12, { style: { flex: 1, gap: tema.space.xs }, children: [
|
|
2062
|
+
/* @__PURE__ */ jsx12(Text10, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.invitasjonHva(program.name) }),
|
|
2063
|
+
/* @__PURE__ */ jsx12(Hint, { children: tekst.invitasjonKontakter(program.maxContacts) })
|
|
2064
|
+
] }),
|
|
2065
|
+
/* @__PURE__ */ jsx12(
|
|
2066
|
+
Pressable7,
|
|
2067
|
+
{
|
|
2068
|
+
testID: "avvis-invitasjon",
|
|
2069
|
+
accessibilityRole: "button",
|
|
2070
|
+
accessibilityLabel: tekst.avvisInvitasjon,
|
|
2071
|
+
onPress: () => setAvvist(true),
|
|
2072
|
+
style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
|
|
2073
|
+
children: /* @__PURE__ */ jsx12(Text10, { style: { color: tema.color.textSecondary, fontSize: tema.font.body }, children: "\u2715" })
|
|
2074
|
+
}
|
|
2075
|
+
)
|
|
2076
|
+
] }),
|
|
2077
|
+
feil && !viserAksept ? /* @__PURE__ */ jsx12(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
|
|
2078
|
+
/* @__PURE__ */ jsx12(Btn, { variant: "secondary", testID: "les-mer", label: tekst.lesMer, onPress: () => setViserAksept(true) })
|
|
2079
|
+
]
|
|
2080
|
+
}
|
|
2081
|
+
),
|
|
2082
|
+
viserAksept ? /* @__PURE__ */ jsx12(
|
|
2083
|
+
Aksept,
|
|
2084
|
+
{
|
|
2085
|
+
program,
|
|
2086
|
+
harToken: !!invitationToken,
|
|
2087
|
+
sender,
|
|
2088
|
+
...feil ? { feil } : {},
|
|
2089
|
+
onBliMed: () => void bliMed(),
|
|
2090
|
+
onLukk: () => setViserAksept(false)
|
|
2091
|
+
}
|
|
2092
|
+
) : null
|
|
2093
|
+
] });
|
|
2094
|
+
}
|
|
2095
|
+
|
|
1757
2096
|
// src/lagring.ts
|
|
1758
2097
|
function createStorage(pakke) {
|
|
1759
2098
|
return {
|
|
@@ -1776,6 +2115,7 @@ function createMemoryStorage() {
|
|
|
1776
2115
|
}
|
|
1777
2116
|
export {
|
|
1778
2117
|
InnspelPrivate,
|
|
2118
|
+
InnspelProgram,
|
|
1779
2119
|
InnspelProvider,
|
|
1780
2120
|
byggTema,
|
|
1781
2121
|
createMemoryStorage,
|