diff --git a/app/Jobs/ConvertToComic.php b/app/Jobs/ConvertToComic.php index 147f7a3..3dce2b9 100644 --- a/app/Jobs/ConvertToComic.php +++ b/app/Jobs/ConvertToComic.php @@ -20,12 +20,9 @@ class ConvertToComic implements ShouldQueue { $absolutePath = Storage::disk('public')->path($this->photoJob->image_path); - $gmicOps = $this->photoJob->setting?->gmic_command - ?? 'cl_comic 4,1,0,0,1,15,15,1,10,20,6,2,0,0,0,0,0,0,50,50'; - $result = Process::timeout(0)->run( 'gmic ' . escapeshellarg($absolutePath) . - ' ' . $gmicOps . + ' cl_comic 4,1,0,0,1,15,15,1,10,20,6,2,0,0,0,0,0,0,50,50' . ' -o ' . escapeshellarg($absolutePath) ); diff --git a/app/Livewire/CameraCapture.php b/app/Livewire/CameraCapture.php index 6f70e26..779202f 100644 --- a/app/Livewire/CameraCapture.php +++ b/app/Livewire/CameraCapture.php @@ -4,8 +4,6 @@ namespace App\Livewire; use App\Jobs\ConvertToComic; use App\Models\PhotoJob; -use App\Models\PhotoSession; -use App\Models\PhotoSetting; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Livewire\Component; @@ -14,6 +12,17 @@ class CameraCapture extends Component { public string $status = ''; + public function delete(int $jobId): void + { + $job = PhotoJob::find($jobId); + if (!$job) return; + + Storage::disk('public')->delete($job->image_path); + $job->delete(); + + $this->status = "Job #{$jobId} deleted"; + } + public function capture(string $imageData): void { if (!preg_match('/^data:image\/(\w+);base64,/', $imageData, $type)) { @@ -22,66 +31,31 @@ class CameraCapture extends Component } $extension = strtolower($type[1]); + $filename = 'photos/' . Str::uuid() . '.' . $extension; $raw = base64_decode(substr($imageData, strpos($imageData, ',') + 1)); - $originalPath = 'photos/' . Str::uuid() . '.' . $extension; - Storage::disk('public')->put($originalPath, $raw); + Storage::disk('public')->put($filename, $raw); - $session = PhotoSession::create(['original_image_path' => $originalPath]); + $job = PhotoJob::create([ + 'image_path' => $filename, + 'status' => 'processing', + ]); - $settings = PhotoSetting::active()->get(); + ConvertToComic::dispatch($job); - foreach ($settings as $setting) { - $variantPath = 'photos/' . Str::uuid() . '.' . $extension; - Storage::disk('public')->put($variantPath, $raw); - - $job = PhotoJob::create([ - 'image_path' => $variantPath, - 'status' => 'processing', - 'photo_session_id' => $session->id, - 'photo_setting_id' => $setting->id, - ]); - - ConvertToComic::dispatch($job); - } - - $this->status = count($settings) . ' Varianten werden erstellt…'; - } - - public function selectVariant(int $sessionId, int $jobId): void - { - PhotoSession::where('id', $sessionId)->update(['selected_job_id' => $jobId]); - } - - public function deleteSession(int $sessionId): void - { - $session = PhotoSession::with('jobs')->find($sessionId); - if (!$session) return; - - foreach ($session->jobs as $job) { - Storage::disk('public')->delete($job->image_path); - $job->delete(); - } - - Storage::disk('public')->delete($session->original_image_path); - $session->delete(); - - $this->status = "Session #{$sessionId} gelöscht"; + $this->status = "Processing photo…"; } public function render() { - $sessions = PhotoSession::latest()->take(10)->get(); + $recentPhotos = PhotoJob::latest()->take(10)->get()->map(fn($job) => [ + 'id' => $job->id, + 'url' => Storage::disk('public')->url($job->image_path) . '?v=' . $job->updated_at->timestamp, + 'status' => $job->status, + ]); - foreach ($sessions as $session) { - $session->setRelation('jobs', $session->jobs()->with('setting')->orderBy('photo_setting_id')->get()); - } + $hasProcessing = $recentPhotos->contains('status', 'processing'); - $currentSession = $sessions->first(); - $previousSessions = $sessions->skip(1); - - $hasProcessing = $currentSession && $currentSession->jobs->contains('status', 'processing'); - - return view('livewire.camera-capture', compact('currentSession', 'previousSessions', 'hasProcessing')); + return view('livewire.camera-capture', compact('recentPhotos', 'hasProcessing')); } } diff --git a/app/Livewire/PhotoSettings.php b/app/Livewire/PhotoSettings.php deleted file mode 100644 index 399de88..0000000 --- a/app/Livewire/PhotoSettings.php +++ /dev/null @@ -1,75 +0,0 @@ -update(['is_active' => !$setting->is_active]); - } - - public function startEdit(int $id, string $name, string $command): void - { - $this->editingId = [$id => true]; - $this->editName[$id] = $name; - $this->editCommand[$id] = $command; - } - - public function saveEdit(int $id): void - { - PhotoSetting::findOrFail($id)->update([ - 'name' => trim($this->editName[$id] ?? ''), - 'gmic_command' => trim($this->editCommand[$id] ?? ''), - ]); - unset($this->editingId[$id]); - } - - public function cancelEdit(int $id): void - { - unset($this->editingId[$id]); - } - - public function addSetting(): void - { - $name = trim($this->newName); - $command = trim($this->newCommand); - - if (!$name || !$command) return; - - $max = PhotoSetting::max('sort_order') ?? 0; - PhotoSetting::create([ - 'name' => $name, - 'gmic_command' => $command, - 'sort_order' => $max + 1, - 'is_active' => true, - ]); - - $this->newName = ''; - $this->newCommand = ''; - $this->showForm = false; - } - - public function delete(int $id): void - { - PhotoSetting::findOrFail($id)->delete(); - } - - public function render() - { - return view('livewire.photo-settings', [ - 'settings' => PhotoSetting::orderBy('sort_order')->get(), - ]); - } -} diff --git a/app/Models/PhotoJob.php b/app/Models/PhotoJob.php index b4687ba..7df7754 100644 --- a/app/Models/PhotoJob.php +++ b/app/Models/PhotoJob.php @@ -3,19 +3,8 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; class PhotoJob extends Model { - protected $fillable = ['image_path', 'status', 'photo_session_id', 'photo_setting_id']; - - public function session(): BelongsTo - { - return $this->belongsTo(PhotoSession::class, 'photo_session_id'); - } - - public function setting(): BelongsTo - { - return $this->belongsTo(PhotoSetting::class, 'photo_setting_id'); - } + protected $fillable = ['image_path', 'status']; } diff --git a/app/Models/PhotoSession.php b/app/Models/PhotoSession.php deleted file mode 100644 index e5cc0ba..0000000 --- a/app/Models/PhotoSession.php +++ /dev/null @@ -1,22 +0,0 @@ -hasMany(PhotoJob::class)->with('setting')->orderBy('photo_setting_id'); - } - - public function selectedJob(): BelongsTo - { - return $this->belongsTo(PhotoJob::class, 'selected_job_id'); - } -} diff --git a/app/Models/PhotoSetting.php b/app/Models/PhotoSetting.php deleted file mode 100644 index c6f6d6f..0000000 --- a/app/Models/PhotoSetting.php +++ /dev/null @@ -1,23 +0,0 @@ - 'boolean']; - - public function jobs(): HasMany - { - return $this->hasMany(PhotoJob::class); - } - - public function scopeActive($query) - { - return $query->where('is_active', true)->orderBy('sort_order'); - } -} diff --git a/database/migrations/2026_05_30_122400_add_session_setting_to_photo_jobs_table.php b/database/migrations/2026_05_30_122400_add_session_setting_to_photo_jobs_table.php deleted file mode 100644 index 9eba7cf..0000000 --- a/database/migrations/2026_05_30_122400_add_session_setting_to_photo_jobs_table.php +++ /dev/null @@ -1,31 +0,0 @@ -foreignId('photo_session_id')->nullable()->constrained('photo_sessions')->nullOnDelete(); - $table->foreignId('photo_setting_id')->nullable()->constrained('photo_settings')->nullOnDelete(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('photo_jobs', function (Blueprint $table) { - $table->dropForeign(['photo_session_id']); - $table->dropForeign(['photo_setting_id']); - $table->dropColumn(['photo_session_id', 'photo_setting_id']); - }); - } -}; diff --git a/database/migrations/2026_05_30_122400_create_photo_sessions_table.php b/database/migrations/2026_05_30_122400_create_photo_sessions_table.php deleted file mode 100644 index 5d80993..0000000 --- a/database/migrations/2026_05_30_122400_create_photo_sessions_table.php +++ /dev/null @@ -1,29 +0,0 @@ -id(); - $table->string('original_image_path'); - $table->unsignedBigInteger('selected_job_id')->nullable(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('photo_sessions'); - } -}; diff --git a/database/migrations/2026_05_30_122400_create_photo_settings_table.php b/database/migrations/2026_05_30_122400_create_photo_settings_table.php deleted file mode 100644 index e870838..0000000 --- a/database/migrations/2026_05_30_122400_create_photo_settings_table.php +++ /dev/null @@ -1,31 +0,0 @@ -id(); - $table->string('name'); - $table->text('gmic_command'); - $table->integer('sort_order')->default(0); - $table->boolean('is_active')->default(true); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('photo_settings'); - } -}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 59cb778..6b901f8 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -15,6 +15,11 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - $this->call(PhotoSettingSeeder::class); + // User::factory(10)->create(); + + User::factory()->create([ + 'name' => 'Test User', + 'email' => 'test@example.com', + ]); } } diff --git a/database/seeders/PhotoSettingSeeder.php b/database/seeders/PhotoSettingSeeder.php deleted file mode 100644 index 9730d43..0000000 --- a/database/seeders/PhotoSettingSeeder.php +++ /dev/null @@ -1,37 +0,0 @@ - 'Comic', - 'gmic_command' => 'cl_comic 4,1,0,0,1,15,15,1,10,20,6,2,0,0,0,0,0,0,50,50', - 'sort_order' => 1, - 'is_active' => true, - ], - [ - 'name' => 'Schwarzweiß', - 'gmic_command' => '-to_gray', - 'sort_order' => 2, - 'is_active' => true, - ], - [ - 'name' => 'Weichzeichner', - 'gmic_command' => '-blur 4 -sharpen 80', - 'sort_order' => 3, - 'is_active' => true, - ], - ]; - - foreach ($settings as $setting) { - PhotoSetting::firstOrCreate(['name' => $setting['name']], $setting); - } - } -} diff --git a/resources/views/camera.blade.php b/resources/views/camera.blade.php index dcfe7ea..bf05846 100644 --- a/resources/views/camera.blade.php +++ b/resources/views/camera.blade.php @@ -15,8 +15,6 @@ @livewire('camera-capture') - @livewire('photo-settings') - @livewireScripts diff --git a/resources/views/livewire/camera-capture.blade.php b/resources/views/livewire/camera-capture.blade.php index 8442920..00616c1 100644 --- a/resources/views/livewire/camera-capture.blade.php +++ b/resources/views/livewire/camera-capture.blade.php @@ -1,8 +1,7 @@
- {{-- Camera preview --}}
@@ -20,136 +19,46 @@ wire:loading.attr="disabled" @disabled($hasProcessing) class="mt-8 px-10 py-4 bg-white text-gray-950 font-semibold text-lg rounded-full shadow-lg hover:bg-gray-200 active:scale-95 transition-all duration-150 disabled:opacity-50 disabled:cursor-not-allowed"> - {{ $hasProcessing ? 'Erstelle Varianten...' : 'Foto aufnehmen' }} - Speichern… + {{ $hasProcessing ? 'Erstelle Bild...' : 'Foto aufnehmen' }} + Saving…
{{ $status }}
- {{-- Tabbed photo sessions --}} - @if ($currentSession || $previousSessions->isNotEmpty()) -
- - {{-- Tab navigation --}} -
- - @foreach ($previousSessions as $session) - + @if ($recentPhotos->isNotEmpty()) +
+

Recent Photos

+
+ @foreach ($recentPhotos as $photo) +
+ @if ($photo['status'] === 'processing') +
+ Photo #{{ $photo['id'] }} +
+ + + + +
+
+ @else + Photo #{{ $photo['id'] }} + + @endif + + {{ $photo['status'] }} + +
@endforeach
- - {{-- Current session tab --}} -
- @if ($currentSession) -
- - {{-- Original for comparison --}} -
- Original - - Original - -
- - {{-- Variants --}} - @foreach ($currentSession->jobs as $job) -
status === 'done') x-on:click="$wire.selectVariant({{ $currentSession->id }}, {{ $job->id }})" @endif> - - @if ($job->status === 'processing') -
- - - - -
- @elseif ($job->status === 'failed') -
- Fehler -
- @else - {{ $job->setting?->name }} - @if ($currentSession->selected_job_id === $job->id) -
- - - -
- @endif - @endif - - - {{ $job->setting?->name ?? 'Filter' }} - -
- @endforeach - -
- - - @else -

Noch kein Foto aufgenommen.

- @endif -
- - {{-- Previous session tabs --}} - @foreach ($previousSessions as $session) -
- @php - $displayJob = $session->selected_job_id - ? $session->jobs->firstWhere('id', $session->selected_job_id) - : $session->jobs->where('status', 'done')->first(); - @endphp - - @if ($displayJob) - Session #{{ $session->id }} - @endif - - {{-- Variant thumbnails --}} - @if ($session->jobs->count() > 1) -
- @foreach ($session->jobs->where('status', 'done') as $job) -
- {{ $job->setting?->name }} - - {{ $job->setting?->name ?? 'Filter' }} - -
- @endforeach -
- @endif - - -
- @endforeach -
@endif @@ -160,7 +69,8 @@ class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-6" style="display:none">
- Photo + Photo
diff --git a/resources/views/livewire/photo-settings.blade.php b/resources/views/livewire/photo-settings.blade.php deleted file mode 100644 index 8a69d39..0000000 --- a/resources/views/livewire/photo-settings.blade.php +++ /dev/null @@ -1,69 +0,0 @@ -
-
-

Foto-Einstellungen

- -
- - @if ($showForm) -
- - - -
- @endif - -
- @foreach ($settings as $setting) -
- - - @if (isset($editingId[$setting->id])) -
- - - - -
- @else -
-

{{ $setting->name }}

-

{{ $setting->gmic_command }}

-
-
- - -
- @endif -
- @endforeach - - @if ($settings->isEmpty()) -

Keine Einstellungen vorhanden.

- @endif -
-