diff --git a/src/lib/components/filesharing/Done.svelte b/src/lib/components/filesharing/Done.svelte index 765bfd9..1359594 100644 --- a/src/lib/components/filesharing/Done.svelte +++ b/src/lib/components/filesharing/Done.svelte @@ -4,7 +4,9 @@ import HelpToggle from '$lib/components/HelpToggle.svelte' import Chip from '$lib/components/Chip.svelte' import FileList from '$lib/components/filesharing/FileList.svelte' + import EmailPreviewModal from '$lib/components/filesharing/EmailPreviewModal.svelte' import airplane from '$lib/assets/images/airplane.svg' + import { STAGING } from '$lib/env' interface props { encryptState: EncryptState @@ -12,6 +14,13 @@ } let { encryptState = $bindable(), createDefaultEncryptState }: props = $props() + + // On staging, cryptify renders the notification email but does not + // dispatch via SMTP. Auto-open the preview modal so developers don't + // have to scrape cryptify logs for the /download link. The modal + // fetches the actual rendered HTML from cryptify, so this branch + // never runs in production (STAGING is false there). + let previewOpen = $state(STAGING && !!encryptState.uploadUuid)
@@ -59,12 +68,28 @@ variant="dark" /> + {#if STAGING && encryptState.uploadUuid} + (previewOpen = true)} + size="lg" + variant="default" + /> + {/if} +
+{#if STAGING && previewOpen && encryptState.uploadUuid} + (previewOpen = false)} + /> +{/if} + diff --git a/src/lib/components/filesharing/SendButton.svelte b/src/lib/components/filesharing/SendButton.svelte index 15dc88b..7bbf1d1 100644 --- a/src/lib/components/filesharing/SendButton.svelte +++ b/src/lib/components/filesharing/SendButton.svelte @@ -192,6 +192,13 @@ message: encryptState.message, language: lang as 'EN' | 'NL', }, + // Captured here (not from the upload() return value) so the + // staging email-preview modal can render even if a later + // chunk fails — the uuid is what links the preview to the + // /download?uuid=… link cryptify would have emailed. + onUploadInit: ({ uuid }) => { + encryptState.uploadUuid = uuid + }, }) const totalBytes = encryptState.files.reduce( diff --git a/src/lib/env.ts b/src/lib/env.ts index 5e4f28f..8c8230c 100644 --- a/src/lib/env.ts +++ b/src/lib/env.ts @@ -29,3 +29,10 @@ function runtimeConfig(): Record { export const FF_BUSINESS = runtimeConfig().FF_BUSINESS === true export const BUSINESS_URL = (runtimeConfig().BUSINESS_URL as string) ?? 'https://business.postguard.eu' + +/** True on staging/dev where cryptify runs with `staging_mode = true` and + * does not actually send notification emails. The website uses this to + * render an in-page preview of the email a recipient would have received, + * so developers can grab the download link without trawling the cryptify + * logs. */ +export const STAGING = runtimeConfig().STAGING === true diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index d2eca62..f33920d 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -229,6 +229,21 @@ "addRecipient": "recipient", "addRecipientButton": "Add another recipient", "emailSenderConfirm": "Send me a confirmation", + "emailPreview": { + "title": "Notification email preview", + "subtitle": "Staging only — cryptify does not actually send notification emails on staging. This is what each recipient would have received.", + "loading": "Loading preview…", + "error": "Could not load preview.", + "empty": "No recipients to preview.", + "close": "Close", + "from": "From", + "replyTo": "Reply to", + "subject": "Subject", + "to": "To", + "confirmationTag": "sender copy", + "iframeTitle": "Notification email body", + "reopen": "Show email preview" + }, "timeremaining": { "estimate": "Estimating...", "unknown": "More then one day left.", diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json index dbba7c0..da80cfe 100644 --- a/src/lib/locales/nl.json +++ b/src/lib/locales/nl.json @@ -228,6 +228,21 @@ "addRecipient": "ontvanger", "addRecipientButton": "Voeg nog een ontvanger toe", "emailSenderConfirm": "Stuur mij een bevestiging", + "emailPreview": { + "title": "Voorbeeld notificatie-e-mail", + "subtitle": "Alleen staging — cryptify verstuurt op staging geen e-mails. Dit is wat elke ontvanger zou hebben gezien.", + "loading": "Voorbeeld laden…", + "error": "Voorbeeld kon niet worden geladen.", + "empty": "Geen ontvangers om weer te geven.", + "close": "Sluiten", + "from": "Van", + "replyTo": "Antwoord aan", + "subject": "Onderwerp", + "to": "Aan", + "confirmationTag": "bevestigingskopie", + "iframeTitle": "Inhoud van de notificatie-e-mail", + "reopen": "Toon e-mailvoorbeeld" + }, "timeremaining": { "estimate": "Estimating...", "unknown": "Nog meer dan een dag", diff --git a/src/lib/types/filesharing/attributes.ts b/src/lib/types/filesharing/attributes.ts index 9a19d1d..c1f8be8 100644 --- a/src/lib/types/filesharing/attributes.ts +++ b/src/lib/types/filesharing/attributes.ts @@ -26,6 +26,9 @@ export type EncryptState = { selfAborted: boolean serverError: boolean encryptStartTime: number + /** Cryptify upload UUID, captured via `onUploadInit` as soon as the + * server allocates one. Used by the staging email-preview modal. */ + uploadUuid?: string } export type AttType = diff --git a/static/config.js b/static/config.js index 912cdd0..308552c 100644 --- a/static/config.js +++ b/static/config.js @@ -3,4 +3,8 @@ window.APP_CONFIG = { FF_BUSINESS: true, BUSINESS_URL: 'https://business.staging.postguard.eu', + // Set to true to simulate the staging/dev environment locally: instead + // of relying on cryptify to send a real notification email, the website + // pops up a preview of what the email would have looked like. + STAGING: false, };