mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr.git
synced 2026-02-15 03:23:17 +00:00
Kleine Bilder anzeigen (vibe-kanban 9bcfc693)
Die Ladezeiten der Bilder ist zu hoch, weil die Original geladen werden. Bei /association/project-support lade in der Übersicht und in der Einzel-Ansicht /association/project-support/badgebox-for-nostr-manage-your-badges nur die Conversions der Bilder, also die kleinere Versionen.
This commit is contained in:
@@ -78,14 +78,20 @@ class ProjectProposal extends Model implements HasMedia
|
|||||||
->useFallbackUrl(asset('einundzwanzig-alpha.jpg'));
|
->useFallbackUrl(asset('einundzwanzig-alpha.jpg'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSignedMediaUrl(string $collection = 'main', int $expireMinutes = 60): string
|
public function getSignedMediaUrl(string $collection = 'main', int $expireMinutes = 60, ?string $conversion = null): string
|
||||||
{
|
{
|
||||||
$media = $this->getFirstMedia($collection);
|
$media = $this->getFirstMedia($collection);
|
||||||
if (! $media) {
|
if (! $media) {
|
||||||
return asset('einundzwanzig-alpha.jpg');
|
return asset('einundzwanzig-alpha.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
|
$parameters = ['media' => $media];
|
||||||
|
|
||||||
|
if ($conversion && $media->hasGeneratedConversion($conversion)) {
|
||||||
|
$parameters['conversion'] = $conversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function einundzwanzigPleb(): BelongsTo
|
public function einundzwanzigPleb(): BelongsTo
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<a class="relative block w-full h-48 sm:w-56 sm:h-auto xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0 sm:shrink-0"
|
<a class="relative block w-full h-48 sm:w-56 sm:h-auto xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0 sm:shrink-0"
|
||||||
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
|
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
|
||||||
<img class="absolute object-cover object-center w-full h-full"
|
<img class="absolute object-cover object-center w-full h-full"
|
||||||
src="{{ $project->getSignedMediaUrl('main') }}" alt="Meetup 01">
|
src="{{ $project->getSignedMediaUrl('main', 60, 'preview') }}" alt="Meetup 01">
|
||||||
<button class="absolute top-0 right-0 mt-4 mr-4">
|
<button class="absolute top-0 right-0 mt-4 mr-4">
|
||||||
<img class="rounded-full h-8 w-8"
|
<img class="rounded-full h-8 w-8"
|
||||||
src="{{ $project->einundzwanzigPleb->profile?->picture }}"
|
src="{{ $project->einundzwanzigPleb->profile?->picture }}"
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<a class="relative block w-full h-48 sm:w-56 sm:h-auto xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0 sm:shrink-0"
|
<a class="relative block w-full h-48 sm:w-56 sm:h-auto xl:sidebar-expanded:w-40 2xl:sidebar-expanded:w-56 shrink-0 sm:shrink-0"
|
||||||
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
|
href="{{ route('association.projectSupport.item', ['projectProposal' => $project]) }}">
|
||||||
<img class="absolute object-cover object-center w-full h-full"
|
<img class="absolute object-cover object-center w-full h-full"
|
||||||
src="{{ $project->getSignedMediaUrl('main') }}" alt="Meetup 01">
|
src="{{ $project->getSignedMediaUrl('main', 60, 'preview') }}" alt="Meetup 01">
|
||||||
<button class="absolute top-0 right-0 mt-4 mr-4">
|
<button class="absolute top-0 right-0 mt-4 mr-4">
|
||||||
<img class="rounded-full h-8 w-8"
|
<img class="rounded-full h-8 w-8"
|
||||||
src="{{ $project->einundzwanzigPleb->profile?->picture }}"
|
src="{{ $project->einundzwanzigPleb->profile?->picture }}"
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ new class extends Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<figure class="mb-6">
|
<figure class="mb-6">
|
||||||
<img class="rounded-sm h-48" src="{{ $projectProposal->getSignedMediaUrl('main') }}"
|
<img class="rounded-sm h-48" src="{{ $projectProposal->getSignedMediaUrl('main', 60, 'preview') }}"
|
||||||
alt="Picture">
|
alt="Picture">
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,16 @@ Route::get('dl/{media}', function (Media $media, Request $request) {
|
|||||||
->middleware('signed');
|
->middleware('signed');
|
||||||
|
|
||||||
Route::get('media/{media}', function (Media $media, Request $request) {
|
Route::get('media/{media}', function (Media $media, Request $request) {
|
||||||
|
$conversion = $request->query('conversion');
|
||||||
|
|
||||||
|
if ($conversion && $media->hasGeneratedConversion($conversion)) {
|
||||||
|
$path = $media->getPathRelativeToRoot($conversion);
|
||||||
|
} else {
|
||||||
|
$path = $media->getPathRelativeToRoot();
|
||||||
|
}
|
||||||
|
|
||||||
return Storage::disk($media->disk)->response(
|
return Storage::disk($media->disk)->response(
|
||||||
$media->getPathRelativeToRoot(),
|
$path,
|
||||||
$media->file_name,
|
$media->file_name,
|
||||||
[
|
[
|
||||||
'Content-Type' => $media->mime_type,
|
'Content-Type' => $media->mime_type,
|
||||||
|
|||||||
95
tests/Feature/MediaSignedRouteTest.php
Normal file
95
tests/Feature/MediaSignedRouteTest.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\ProjectProposal;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
it('serves original media via signed route', function () {
|
||||||
|
Storage::fake('private');
|
||||||
|
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$project->addMedia(
|
||||||
|
\Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100)
|
||||||
|
)->toMediaCollection('main');
|
||||||
|
|
||||||
|
$media = $project->getFirstMedia('main');
|
||||||
|
|
||||||
|
$url = url()->temporarySignedRoute('media.signed', now()->addMinutes(60), ['media' => $media]);
|
||||||
|
|
||||||
|
$this->get($url)->assertSuccessful();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('serves conversion media via signed route when conversion parameter is provided', function () {
|
||||||
|
Storage::fake('private');
|
||||||
|
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$project->addMedia(
|
||||||
|
\Illuminate\Http\UploadedFile::fake()->image('test.jpg', 500, 500)
|
||||||
|
)->toMediaCollection('main');
|
||||||
|
|
||||||
|
$media = $project->getFirstMedia('main');
|
||||||
|
|
||||||
|
$url = url()->temporarySignedRoute('media.signed', now()->addMinutes(60), [
|
||||||
|
'media' => $media,
|
||||||
|
'conversion' => 'preview',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get($url)->assertSuccessful();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('falls back to original when conversion does not exist', function () {
|
||||||
|
Storage::fake('private');
|
||||||
|
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$project->addMedia(
|
||||||
|
\Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100)
|
||||||
|
)->toMediaCollection('main');
|
||||||
|
|
||||||
|
$media = $project->getFirstMedia('main');
|
||||||
|
|
||||||
|
$url = url()->temporarySignedRoute('media.signed', now()->addMinutes(60), [
|
||||||
|
'media' => $media,
|
||||||
|
'conversion' => 'nonexistent',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get($url)->assertSuccessful();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects unsigned media requests', function () {
|
||||||
|
Storage::fake('private');
|
||||||
|
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$project->addMedia(
|
||||||
|
\Illuminate\Http\UploadedFile::fake()->image('test.jpg', 100, 100)
|
||||||
|
)->toMediaCollection('main');
|
||||||
|
|
||||||
|
$media = $project->getFirstMedia('main');
|
||||||
|
|
||||||
|
$this->get("/media/{$media->id}")->assertForbidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates signed url with conversion parameter', function () {
|
||||||
|
Storage::fake('private');
|
||||||
|
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$project->addMedia(
|
||||||
|
\Illuminate\Http\UploadedFile::fake()->image('test.jpg', 500, 500)
|
||||||
|
)->toMediaCollection('main');
|
||||||
|
|
||||||
|
$urlWithoutConversion = $project->getSignedMediaUrl('main');
|
||||||
|
$urlWithConversion = $project->getSignedMediaUrl('main', 60, 'preview');
|
||||||
|
|
||||||
|
expect($urlWithoutConversion)->not->toContain('conversion=');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns fallback url when no media exists', function () {
|
||||||
|
$project = ProjectProposal::factory()->create();
|
||||||
|
|
||||||
|
$url = $project->getSignedMediaUrl('main', 60, 'preview');
|
||||||
|
|
||||||
|
expect($url)->toContain('einundzwanzig-alpha.jpg');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user