Compare commits

...

3 commits

Author SHA1 Message Date
Benjamin Nussbaum
93406b83a5 chore: update dependencies
Some checks are pending
tests / ci (push) Waiting to run
2025-09-18 10:53:38 +02:00
Benjamin Nussbaum
88e10101b8 fix: pint 2025-09-18 10:48:20 +02:00
Benjamin Nussbaum
e65473f932 fix(ci): do not add latest tag to pre-releases 2025-09-18 10:48:20 +02:00
5 changed files with 165 additions and 77 deletions

View file

@ -43,7 +43,7 @@ jobs:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=ref,event=tag type=ref,event=tag
latest type=raw,value=latest,enable=${{ github.event.release.prerelease == false }}
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6

View file

@ -27,10 +27,10 @@ final class DeviceModel extends Model
public function getColorDepthAttribute(): ?string public function getColorDepthAttribute(): ?string
{ {
if (! $this->bit_depth){ if (! $this->bit_depth) {
return null; return null;
} }
return $this->bit_depth . 'bit'; return $this->bit_depth.'bit';
} }
} }

View file

@ -7,11 +7,11 @@ use App\Models\Device;
use App\Models\DeviceModel; use App\Models\DeviceModel;
use App\Models\Plugin; use App\Models\Plugin;
use Exception; use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Imagick; use Imagick;
use ImagickException; use ImagickException;
use ImagickPixel; use ImagickPixel;
use Log;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use RuntimeException; use RuntimeException;
use Spatie\Browsershot\Browsershot; use Spatie\Browsershot\Browsershot;
@ -63,6 +63,15 @@ class ImageGenerationService
} }
} }
// Validate that the PNG file was created and is valid
if (! file_exists($pngPath)) {
throw new RuntimeException('PNG file was not created: '.$pngPath);
}
if (filesize($pngPath) === 0) {
throw new RuntimeException('PNG file is empty: '.$pngPath);
}
// Convert image based on DeviceModel settings or fallback to device settings // Convert image based on DeviceModel settings or fallback to device settings
self::convertImage($pngPath, $bmpPath, $imageSettings); self::convertImage($pngPath, $bmpPath, $imageSettings);
@ -293,14 +302,19 @@ class ImageGenerationService
*/ */
private static function convertToBmpImageMagick(string $pngPath, string $bmpPath): void private static function convertToBmpImageMagick(string $pngPath, string $bmpPath): void
{ {
$imagick = new Imagick($pngPath); try {
$imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE); $imagick = new Imagick($pngPath);
$imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false); $imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE);
$imagick->setImageDepth(1); $imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false);
$imagick->stripImage(); $imagick->setImageDepth(1);
$imagick->setFormat('BMP3'); $imagick->stripImage();
$imagick->writeImage($bmpPath); $imagick->setFormat('BMP3');
$imagick->clear(); $imagick->writeImage($bmpPath);
$imagick->clear();
} catch (ImagickException $e) {
Log::error('ImageMagick conversion failed for PNG: '.$pngPath.' - '.$e->getMessage());
throw $e;
}
} }
/** /**
@ -308,26 +322,31 @@ class ImageGenerationService
*/ */
private static function convertToPngImageMagick(string $pngPath, ?int $width, ?int $height, ?int $rotate, $quantize = true): void private static function convertToPngImageMagick(string $pngPath, ?int $width, ?int $height, ?int $rotate, $quantize = true): void
{ {
$imagick = new Imagick($pngPath); try {
if ($width !== 800 || $height !== 480) { $imagick = new Imagick($pngPath);
$imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true); if ($width !== 800 || $height !== 480) {
} $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true);
if ($rotate !== null && $rotate !== 0) { }
$imagick->rotateImage(new ImagickPixel('black'), $rotate); if ($rotate !== null && $rotate !== 0) {
} $imagick->rotateImage(new ImagickPixel('black'), $rotate);
}
$imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE); $imagick->setImageType(Imagick::IMGTYPE_GRAYSCALE);
$imagick->setOption('dither', 'FloydSteinberg'); $imagick->setOption('dither', 'FloydSteinberg');
if ($quantize) { if ($quantize) {
$imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false); $imagick->quantizeImage(2, Imagick::COLORSPACE_GRAY, 0, true, false);
}
$imagick->setImageDepth(8);
$imagick->stripImage();
$imagick->setFormat('png');
$imagick->writeImage($pngPath);
$imagick->clear();
} catch (ImagickException $e) {
Log::error('ImageMagick conversion failed for PNG: '.$pngPath.' - '.$e->getMessage());
throw $e;
} }
$imagick->setImageDepth(8);
$imagick->stripImage();
$imagick->setFormat('png');
$imagick->writeImage($pngPath);
$imagick->clear();
} }
public static function cleanupFolder(): void public static function cleanupFolder(): void

159
composer.lock generated
View file

@ -62,16 +62,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.356.17", "version": "3.356.20",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "d0357fbe2535bb7d832e594a4ff2ff8da29d229c" "reference": "7514867a6463fb68a60f5e17b4ccc56b4dc7d4f1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d0357fbe2535bb7d832e594a4ff2ff8da29d229c", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7514867a6463fb68a60f5e17b4ccc56b4dc7d4f1",
"reference": "d0357fbe2535bb7d832e594a4ff2ff8da29d229c", "reference": "7514867a6463fb68a60f5e17b4ccc56b4dc7d4f1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -153,9 +153,9 @@
"support": { "support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions", "forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.356.17" "source": "https://github.com/aws/aws-sdk-php/tree/3.356.20"
}, },
"time": "2025-09-12T18:07:37+00:00" "time": "2025-09-17T18:23:32+00:00"
}, },
{ {
"name": "bnussbau/laravel-trmnl-blade", "name": "bnussbau/laravel-trmnl-blade",
@ -1691,16 +1691,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v12.28.1", "version": "v12.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "868c1f2d3dba4df6d21e3a8d818479f094cfd942" "reference": "a9e4c73086f5ba38383e9c1d74b84fe46aac730b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/868c1f2d3dba4df6d21e3a8d818479f094cfd942", "url": "https://api.github.com/repos/laravel/framework/zipball/a9e4c73086f5ba38383e9c1d74b84fe46aac730b",
"reference": "868c1f2d3dba4df6d21e3a8d818479f094cfd942", "reference": "a9e4c73086f5ba38383e9c1d74b84fe46aac730b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1728,6 +1728,7 @@
"monolog/monolog": "^3.0", "monolog/monolog": "^3.0",
"nesbot/carbon": "^3.8.4", "nesbot/carbon": "^3.8.4",
"nunomaduro/termwind": "^2.0", "nunomaduro/termwind": "^2.0",
"phiki/phiki": "v2.0.0",
"php": "^8.2", "php": "^8.2",
"psr/container": "^1.1.1|^2.0.1", "psr/container": "^1.1.1|^2.0.1",
"psr/log": "^1.0|^2.0|^3.0", "psr/log": "^1.0|^2.0|^3.0",
@ -1837,7 +1838,7 @@
"ext-pdo": "Required to use all database features.", "ext-pdo": "Required to use all database features.",
"ext-posix": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.",
"ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).",
"filp/whoops": "Required for friendly error pages in development (^2.14.3).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).",
"laravel/tinker": "Required to use the tinker console command (^2.0).", "laravel/tinker": "Required to use the tinker console command (^2.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).",
@ -1906,7 +1907,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2025-09-04T14:58:12+00:00" "time": "2025-09-16T14:15:03+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
@ -2859,16 +2860,16 @@
}, },
{ {
"name": "livewire/flux", "name": "livewire/flux",
"version": "v2.3.2", "version": "v2.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/livewire/flux.git", "url": "https://github.com/livewire/flux.git",
"reference": "e0704b125d5f9544aa32e0cfccb11baaf44d77a0" "reference": "8d83f34d64ab0542463e8e3feab4d166e1830ed9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/livewire/flux/zipball/e0704b125d5f9544aa32e0cfccb11baaf44d77a0", "url": "https://api.github.com/repos/livewire/flux/zipball/8d83f34d64ab0542463e8e3feab4d166e1830ed9",
"reference": "e0704b125d5f9544aa32e0cfccb11baaf44d77a0", "reference": "8d83f34d64ab0542463e8e3feab4d166e1830ed9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2919,9 +2920,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/livewire/flux/issues", "issues": "https://github.com/livewire/flux/issues",
"source": "https://github.com/livewire/flux/tree/v2.3.2" "source": "https://github.com/livewire/flux/tree/v2.4.0"
}, },
"time": "2025-09-08T01:11:34+00:00" "time": "2025-09-16T00:20:10+00:00"
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
@ -3836,6 +3837,77 @@
}, },
"time": "2020-10-15T08:29:30+00:00" "time": "2020-10-15T08:29:30+00:00"
}, },
{
"name": "phiki/phiki",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/phikiphp/phiki.git",
"reference": "461f6dd7e91dc3a95463b42f549ac7d0aab4702f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phikiphp/phiki/zipball/461f6dd7e91dc3a95463b42f549ac7d0aab4702f",
"reference": "461f6dd7e91dc3a95463b42f549ac7d0aab4702f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"league/commonmark": "^2.5.3",
"php": "^8.2",
"psr/simple-cache": "^3.0"
},
"require-dev": {
"illuminate/support": "^11.45",
"laravel/pint": "^1.18.1",
"orchestra/testbench": "^9.15",
"pestphp/pest": "^3.5.1",
"phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^2.0",
"symfony/var-dumper": "^7.1.6"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Phiki\\Adapters\\Laravel\\PhikiServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Phiki\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ryan Chandler",
"email": "support@ryangjchandler.co.uk",
"homepage": "https://ryangjchandler.co.uk",
"role": "Developer"
}
],
"description": "Syntax highlighting using TextMate grammars in PHP.",
"support": {
"issues": "https://github.com/phikiphp/phiki/issues",
"source": "https://github.com/phikiphp/phiki/tree/v2.0.0"
},
"funding": [
{
"url": "https://github.com/sponsors/ryangjchandler",
"type": "github"
},
{
"url": "https://buymeacoffee.com/ryangjchandler",
"type": "other"
}
],
"time": "2025-08-28T18:20:27+00:00"
},
{ {
"name": "phpoption/phpoption", "name": "phpoption/phpoption",
"version": "1.9.4", "version": "1.9.4",
@ -8473,16 +8545,16 @@
}, },
{ {
"name": "laravel/boost", "name": "laravel/boost",
"version": "v1.1.4", "version": "v1.1.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/boost.git", "url": "https://github.com/laravel/boost.git",
"reference": "70f909465bf73dad7e791fad8b7716b3b2712076" "reference": "4bd1692c064b2135eb2f8f7bd8bcb710e5e75f86"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/boost/zipball/70f909465bf73dad7e791fad8b7716b3b2712076", "url": "https://api.github.com/repos/laravel/boost/zipball/4bd1692c064b2135eb2f8f7bd8bcb710e5e75f86",
"reference": "70f909465bf73dad7e791fad8b7716b3b2712076", "reference": "4bd1692c064b2135eb2f8f7bd8bcb710e5e75f86",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8534,7 +8606,7 @@
"issues": "https://github.com/laravel/boost/issues", "issues": "https://github.com/laravel/boost/issues",
"source": "https://github.com/laravel/boost" "source": "https://github.com/laravel/boost"
}, },
"time": "2025-09-04T12:16:09+00:00" "time": "2025-09-18T07:33:27+00:00"
}, },
{ {
"name": "laravel/mcp", "name": "laravel/mcp",
@ -8681,16 +8753,16 @@
}, },
{ {
"name": "laravel/pint", "name": "laravel/pint",
"version": "v1.24.0", "version": "v1.25.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/pint.git", "url": "https://github.com/laravel/pint.git",
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" "reference": "595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", "url": "https://api.github.com/repos/laravel/pint/zipball/595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96",
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", "reference": "595de38458c6b0ab4cae4bcc769c2e5c5d5b8e96",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8701,9 +8773,9 @@
"php": "^8.2.0" "php": "^8.2.0"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^3.82.2", "friendsofphp/php-cs-fixer": "^3.87.2",
"illuminate/view": "^11.45.1", "illuminate/view": "^11.46.0",
"larastan/larastan": "^3.5.0", "larastan/larastan": "^3.7.1",
"laravel-zero/framework": "^11.45.0", "laravel-zero/framework": "^11.45.0",
"mockery/mockery": "^1.6.12", "mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^2.3.1", "nunomaduro/termwind": "^2.3.1",
@ -8714,9 +8786,6 @@
], ],
"type": "project", "type": "project",
"autoload": { "autoload": {
"files": [
"overrides/Runner/Parallel/ProcessFactory.php"
],
"psr-4": { "psr-4": {
"App\\": "app/", "App\\": "app/",
"Database\\Seeders\\": "database/seeders/", "Database\\Seeders\\": "database/seeders/",
@ -8746,7 +8815,7 @@
"issues": "https://github.com/laravel/pint/issues", "issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint" "source": "https://github.com/laravel/pint"
}, },
"time": "2025-07-10T18:09:32+00:00" "time": "2025-09-17T01:36:44+00:00"
}, },
{ {
"name": "laravel/roster", "name": "laravel/roster",
@ -9987,16 +10056,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "2.1.25", "version": "2.1.27",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "4087d28bd252895874e174d65e26b2c202ed893a" "reference": "25da374959afa391992792691093550b3098ef1e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/4087d28bd252895874e174d65e26b2c202ed893a", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/25da374959afa391992792691093550b3098ef1e",
"reference": "4087d28bd252895874e174d65e26b2c202ed893a", "reference": "25da374959afa391992792691093550b3098ef1e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10041,20 +10110,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-09-12T14:26:42+00:00" "time": "2025-09-17T09:55:13+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "12.3.7", "version": "12.3.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9" "reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/99e692c6a84708211f7536ba322bbbaef57ac7fc",
"reference": "bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9", "reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10110,7 +10179,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.7" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.8"
}, },
"funding": [ "funding": [
{ {
@ -10130,7 +10199,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-09-10T09:59:06+00:00" "time": "2025-09-17T11:31:43+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",

View file

@ -39,9 +39,9 @@ it('loads plugins from catalog URL', function () {
'zip_url' => 'https://example.com/plugin.zip', 'zip_url' => 'https://example.com/plugin.zip',
], ],
'byos' => [ 'byos' => [
'byos_laravel' => [ 'byos_laravel' => [
'compatibility' => true, 'compatibility' => true,
] ],
], ],
'logo_url' => 'https://example.com/logo.png', 'logo_url' => 'https://example.com/logo.png',
], ],