Files
SealShare/resources/views/livewire/share-created.blade.php
T
Andreas Reinhold / reiniandClaude Opus 5.5 f9a7839ad3
linter / quality (push) Successful in 1m5s
tests / ci (8.5) (push) Successful in 3m24s
docker / build-and-push (push) Successful in 7m10s
docker / test (8.5) (push) Successful in 3m21s
docker / release (push) Successful in 4s
Release 2.3.0
A share can now hold a private text (a password, a key, a short note)
with its files or on its own. The upload page's new "Private text" card
takes up to 100 KB; the browser encrypts the text and sends it through
the same chunk pipeline as a file, flagged is_text on share_files, so it
gets the share's password, expiry, download limit and cleanup.

The recipient sees the text only after pressing "Show text", which
counts as their download, so a messenger link preview cannot use up a
share limited to one download. The text is left out of the file list,
the ZIP and the file counts; the admin dashboard marks shares that hold
one with "Text".

The website gains a Private text feature card and a fifth phone
screenshot; every screenshot is retaken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 07:00:17 +02:00

95 lines
4.6 KiB
PHP

<x-page :title="__('Share Created!')" :description="__('Your share is ready')">
{{-- The link is ready: a check on an Expressive shape that settles in (share-ready, app.css). --}}
<x-slot:mark>
<div class="share-check">
<x-shape name="soft-burst" class="share-check-shape" />
<x-icon name="check" size="48" class="share-check-icon" />
</div>
</x-slot:mark>
<x-stack gap="space200">
{{-- Besides the link: a QR code in a dialog, saved as a PNG in the browser, and the device's
share sheet where there is one (resources/js/share-created.js). Both carry the link only. --}}
<x-stack
gap="space100"
x-data="shareActions({
url: {{ \Illuminate\Support\Js::from($shareUrl) }},
title: {{ \Illuminate\Support\Js::from($siteTitle) }},
filename: {{ \Illuminate\Support\Js::from('share-'.$share->token.'.png') }},
messages: {{ \Illuminate\Support\Js::from(['shareFailed' => __('The share sheet could not open.'), 'downloadFailed' => __('The QR code could not be saved.')]) }},
})"
data-test="share-actions"
>
<x-input
:label="__('Share Link')"
:value="$shareUrl"
readonly
copyable
mono
icon="link"
data-test="share-link"
/>
{{-- Only on the visit the upload redirects to: the password is flashed once (FileUploader::createShare).
Masked, with the link's copy button at its end, so it is copied without reaching the screen. --}}
@if ($password)
<x-input
type="password"
:label="__('Password')"
:value="$password"
:hint="__('Available only this once. Send it separately from the link.')"
readonly
copyable
icon="key"
autocomplete="off"
data-test="share-password"
/>
@endif
<x-row gap="space100" wrap>
<x-button :label="__('Show QR code')" icon="qr_code_2" variant="tonal" x-on:click="open = true" data-test="show-qr-code" />
<span x-show="canShare" x-cloak>
<x-button :label="__('Share…')" icon="share" variant="tonal" x-on:click="share()" data-test="share-sheet" />
</span>
</x-row>
<x-modal fullscreen :title="__('Scan to open the share')" data-test="qr-code-dialog">
<x-stack gap="space200">
{{-- The quiet zone is baked into the SVG (App\Services\QrCodeService), white in
either theme so a scanner keeps its contrast; the container adds no colour. --}}
<div data-qr-code class="share-qr">{!! $qrCodeSvg !!}</div>
@if ($share->isPasswordProtected())
<x-alert color="info" icon="lock" :title="__('Recipients also need the password.')" />
@endif
</x-stack>
<x-slot:actions>
<x-button :label="__('Close')" x-on:click="close()" />
<x-button :label="__('Download')" icon="download" variant="tonal" x-on:click="downloadQrCode($el.closest('dialog').querySelector('[data-qr-code] svg'))" data-test="download-qr-code" />
</x-slot:actions>
</x-modal>
</x-stack>
<x-grid :columns="2" gap="space200">
<x-stat :title="__('Files')" :value="$share->files->where('is_text', false)->count()" icon="description" />
<x-stat :title="__('Total Size')" :value="Number::fileSize($share->total_size)" icon="hard_drive" />
<x-stat :title="__('Expires')" :value="$share->expires_at ? $share->expires_at->diffForHumans() : __('Never')" icon="schedule" />
<x-stat :title="__('Max Downloads')" :value="$share->max_downloads ?? __('Unlimited')" icon="download" />
@if ($share->hasText())
<x-stat :title="__('Private text')" :value="Number::fileSize($share->textFile->file_size)" icon="notes" />
@endif
</x-grid>
@if ($share->isPasswordProtected())
<x-alert color="info" icon="lock" :title="__('This share is password protected')" />
@endif
<x-row justify="end">
<x-button :label="__('Upload More')" :link="route('upload')" icon="add" variant="tonal" />
</x-row>
</x-stack>
</x-page>