Implement creator studio and upload updates

This commit is contained in:
2026-04-04 10:12:02 +02:00
parent 1da7d3bf88
commit 0b216b7ecd
15107 changed files with 31206 additions and 626514 deletions

View File

@@ -8,6 +8,7 @@ use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
use Intervention\Image\Drivers\Imagick\Driver as ImagickDriver;
use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\ImageManager;
use RuntimeException;
@@ -91,7 +92,16 @@ class AvatarService
public function removeAvatar(int $userId): void
{
$diskName = (string) config('avatars.disk', 's3');
Storage::disk($diskName)->deleteDirectory("avatars/{$userId}");
$disk = Storage::disk($diskName);
$existingHash = UserProfile::query()
->where('user_id', $userId)
->value('avatar_hash');
if (is_string($existingHash) && trim($existingHash) !== '') {
$disk->deleteDirectory($this->avatarDirectory(trim($existingHash)));
}
$disk->deleteDirectory("avatars/{$userId}");
UserProfile::query()->updateOrCreate(
['user_id' => $userId],
@@ -108,20 +118,25 @@ class AvatarService
$image = $this->readImageFromBinary($binary);
$image = $this->normalizeImage($image);
$cropPosition = $this->normalizePosition($position);
$normalizedSource = (string) $image->encode(new PngEncoder());
if ($normalizedSource === '') {
throw new RuntimeException('Avatar processing failed to prepare the source image.');
}
$diskName = (string) config('avatars.disk', 's3');
$disk = Storage::disk($diskName);
$basePath = "avatars/{$userId}";
$existingHash = UserProfile::query()
->where('user_id', $userId)
->value('avatar_hash');
$hashSeed = '';
$encodedVariants = [];
foreach ($this->sizes as $size) {
$variant = $image->cover($size, $size, $cropPosition);
$variant = $this->manager->read($normalizedSource)->cover($size, $size, $cropPosition);
$encoded = (string) $variant->encode(new WebpEncoder($this->quality));
$disk->put("{$basePath}/{$size}.webp", $encoded, [
'visibility' => 'public',
'CacheControl' => 'public, max-age=31536000, immutable',
'ContentType' => 'image/webp',
]);
$encodedVariants[(int) $size] = $encoded;
if ($size === 128) {
$hashSeed = $encoded;
@@ -133,11 +148,34 @@ class AvatarService
}
$hash = hash('sha256', $hashSeed);
$basePath = $this->avatarDirectory($hash);
foreach ($encodedVariants as $size => $encoded) {
$disk->put("{$basePath}/{$size}.webp", $encoded, [
'visibility' => 'public',
'CacheControl' => 'public, max-age=31536000, immutable',
'ContentType' => 'image/webp',
]);
}
if (is_string($existingHash) && trim($existingHash) !== '' && trim($existingHash) !== $hash) {
$disk->deleteDirectory($this->avatarDirectory(trim($existingHash)));
}
$disk->deleteDirectory("avatars/{$userId}");
$this->updateProfileMetadata($userId, $hash);
return $hash;
}
private function avatarDirectory(string $hash): string
{
$p1 = substr($hash, 0, 2);
$p2 = substr($hash, 2, 2);
return sprintf('avatars/%s/%s/%s', $p1, $p2, $hash);
}
private function normalizePosition(string $position): string
{
$normalized = strtolower(trim($position));