image fixes

This commit is contained in:
2026-05-14 21:15:33 +03:00
parent ef29e4d261
commit 8cd80c016f
14 changed files with 180 additions and 38 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
<script>
import Icon from "../common/Icon.svelte";
import { imgurl } from "./imageserver.js";
import { fileurl, imgurl } from "./imageserver.js";
import { getContext } from "svelte";
export let file;
@@ -11,7 +11,6 @@
let fileSide;
let fontSize;
console.log({ channel });
if (size == "large") {
imageSide = 256;
fileSide = 32;
@@ -36,7 +35,8 @@
{#if file.mime.startsWith("image")}
<!-- href={imgurl(record)} -->
<a
href="{channel.lucentUrl}/files/{file.id}"
target="_blank"
href={fileurl(channel, file)}
title={file.filename}
style="width:{imageSide}px;height:{imageSide}px"
>
+4 -2
View File
@@ -2,7 +2,8 @@ export function imgurl(channel, file) {
if (file.mime === "image/svg+xml") {
return fileurl(channel, file);
}
return channel.filesUrl + `/thumbs/${file.path}`;
const webpPath = file.path.slice(0, file.path.lastIndexOf(".")) + ".webp";
return channel.filesUrl + `/thumbs/${webpPath}`;
}
export function fileurl(channel, file) {
@@ -16,7 +17,8 @@ export function htmlurl(channel, file, preset) {
if (file.width > 0) {
let presetUrl = url;
if (preset) {
presetUrl = channel.filesUrl + `/templates/${preset}/${file.path}`;
const webpPath = file.path.slice(0, file.path.lastIndexOf(".")) + ".webp";
presetUrl = channel.filesUrl + `/templates/${preset}/${webpPath}`;
}
html = `<img src="${presetUrl}" alt="${file.path}" />`;
} else if (file.mime === "image/svg+xml") {
+13
View File
@@ -3,6 +3,7 @@
namespace Lucent\Channel;
use Lucent\Channel\Data\UserCommand;
use Lucent\Data\ImagePreset;
use Lucent\Primitive\Collection;
use Lucent\Data\Schema;
use Lucent\Data\ChannelAuth;
@@ -12,6 +13,10 @@ final class Channel
public string $lucentUrl;
public string $filesUrl;
public string $previewTargetUrl;
/**
* @param array<ImagePreset> $imagePresets
*/
public array $imagePresets;
/**
* @param Collection<Schema> $schemas
@@ -30,6 +35,14 @@ final class Channel
$this->lucentUrl = $url . "/lucent";
$this->filesUrl = $this->makeFilesUrl();
$this->previewTargetUrl = $url . "/" . $previewTarget;
$this->imagePresets = array_map(function ($i) {
$preset = new $i();
return new ImagePreset(
id: $i,
name: $preset->getName(),
path: $preset->getPath(),
);
}, $this->imageFilters);
}
private function makeFilesUrl(): string
+23 -1
View File
@@ -45,7 +45,7 @@ final class ChannelService
previewTarget: rtrim(config("lucent.previewTarget") ?? "", "/"),
commands: Collection::make($userCommands),
schemas: $schemasCollection,
imageFilters: config("lucent.imageFilters") ?? [],
imageFilters: self::loadImageFilters(),
roles: $schemasArray["roles"] ?? [],
);
@@ -54,6 +54,28 @@ final class ChannelService
return $channelService;
}
private static function loadImageFilters(): array
{
$relativePath = config("lucent.image_filter_path");
if (!$relativePath) {
return [];
}
$dir = base_path($relativePath);
if (!is_dir($dir)) {
return [];
}
$namespace = str_replace("/", "\\", ucwords($relativePath, "/"));
return array_values(
array_map(
fn(string $file) => $namespace . "\\" . basename($file, ".php"),
glob("{$dir}/*.php") ?: [],
),
);
}
/**
* @param string $name
* @return Option<Schema>
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace Lucent\Commands;
use Illuminate\Console\Command;
class GenerateImageFilter extends Command
{
protected $signature = "lucent:generate:image_filter {name}";
protected $description = "Generate an image filter";
public function handle()
{
$name = $this->argument("name");
$relativePath = config("lucent.image_filter_path");
$dir = base_path($relativePath);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
$filePath = "{$dir}/{$name}.php";
if (file_exists($filePath)) {
$this->error("Filter {$name} already exists at {$filePath}");
return Command::FAILURE;
}
$namespace = str_replace("/", "\\", ucwords($relativePath, "/"));
$stub = <<<PHP
<?php namespace {$namespace};
use Lucent\ImageFilterInterface;
use Intervention\Image\Interfaces\ImageInterface;
class {$name} implements ImageFilterInterface
{
public function apply(ImageInterface \$image): ImageInterface
{
return \$image;
}
public function getName(): string {
return "{$name}";
}
public function getPath(): string {
return "{$name}";
}
}
PHP;
file_put_contents($filePath, $stub);
$this->info("Created {$filePath}");
return Command::SUCCESS;
}
}
+4 -2
View File
@@ -27,10 +27,12 @@ class RebuildThumbnails extends Command
$files = FileRepo::query()->get();
$disk = $this->fileService->loadPublicDisk();
foreach ($files as $file) {
$this->fileService->createTemplates($disk, $file->path);
try {
$this->fileService->createTemplates($disk, $file->path);
} catch (Exception $e) {
echo "File " . $file->filename . " could not be rebuilt \n";
$this->error(
"File " . $file->filename . " could not be rebuilt \n",
);
}
}
}
+1 -11
View File
@@ -7,6 +7,7 @@ return [
"private_disk" => env("LUCENT_PRIVATE_DISK", "local"),
"public_disk" => env("LUCENT_PUBLIC_DISK", "public"),
"schemas_path" => env("LUCENT_SCHEMAS_PATH", "resources/lucent/schemas"),
"image_filter_path" => "app/Lucent/ImageFilters",
"database" => env("LUCENT_DB_CONNECTION", env("DB_CONNECTION", "sqlite")),
"name" => env("LUCENT_NAME", "Lucent"),
"url" => env("LUCENT_URL", env("APP_URL")),
@@ -21,17 +22,6 @@ return [
*
* */
"commands" => [],
/*
* Image filter will be available both for rich editor fields
* and throughout your application
*
* example:
* [
* "filterName" => Filter::class
* ]
*
* */
"imageFilters" => [],
"canInvite" => ["admin"],
"canBuild" => ["admin"],
"systemUserId" => "",
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace Lucent\Data;
class ImagePreset
{
function __construct(
public string $id,
public string $name,
public string $path,
) {}
}
+31 -8
View File
@@ -6,6 +6,7 @@ use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Format;
use Intervention\Image\ImageManager;
use Lucent\Channel\ChannelService;
use Lucent\Id\Id;
@@ -125,21 +126,43 @@ class FileService
public function createTemplates(Filesystem $disk, string $path): void
{
$originalImage = $this->imageManager->make(
$originalImage = $this->imageManager->decode(
$this->loadPublicDisk()->get("lucent/" . $path),
);
foreach (config("lucent.imageFilters") as $filterClass) {
foreach ($this->channelService->channel->imageFilters as $filterClass) {
$imageClone = clone $originalImage;
$image = $imageClone->filter(new $filterClass());
$filterClassInstance = new $filterClass();
$image = $imageClone->modify($filterClassInstance);
$templateUri =
"lucent/templates/" . $filterClass->name() . "/" . $path;
$disk->put($templateUri, $image->encode("webp", 75));
"lucent/templates/" .
$filterClassInstance->getPath() .
"/" .
substr($path, 0, strrpos($path, ".")) .
".webp";
$disk->put(
$templateUri,
$image->encodeUsingFormat(
Format::WEBP,
progressive: true,
quality: 80,
),
);
}
$thumbDir = "lucent/thumbs/" . $path;
$thumbDir =
"lucent/thumbs/" . substr($path, 0, strrpos($path, ".")) . ".webp";
$image = $originalImage->fit(300, 300);
$disk->put($thumbDir, $image->encode("webp", 75));
$image = $originalImage->cover(300, 300);
$disk->put(
$thumbDir,
$image->encodeUsingFormat(
Format::WEBP,
progressive: true,
quality: 80,
),
);
}
/**
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace Lucent;
use Intervention\Image\Interfaces\ModifierInterface;
interface ImageFilterInterface extends ModifierInterface
{
public function getName(): string;
public function getPath(): string;
}
+4 -1
View File
@@ -16,6 +16,7 @@ use Lucent\Account\UserRepoLunar;
use Lucent\Channel\ChannelService;
use Lucent\Commands\CompileSchemas;
use Lucent\Commands\GenerateCollectionSchema;
use Lucent\Commands\GenerateImageFilter;
use Lucent\Commands\LiveLink;
use Lucent\Commands\RebuildThumbnails;
use Lucent\Commands\RemoveOrphanEdges;
@@ -27,6 +28,7 @@ use Lucent\Data\ChannelAuth;
use Lucent\File\FileService;
use Lucent\Query\DatabaseGraph\DatabaseGraph;
use Lucent\Query\DatabaseGraph\PgsqlDatabaseGraph;
use Intervention\Image\Drivers\Imagick\Driver;
class LucentServiceProvider extends ServiceProvider
{
@@ -40,7 +42,7 @@ class LucentServiceProvider extends ServiceProvider
});
$this->app->bind(ImageManager::class, function () {
return new ImageManager(["driver" => "imagick"]);
return ImageManager::usingDriver(new Driver());
});
$this->app->bind(DatabaseGraph::class, function () {
@@ -99,6 +101,7 @@ class LucentServiceProvider extends ServiceProvider
RemoveOrphanEdges::class,
SetupDatabase::class,
GenerateCollectionSchema::class,
GenerateImageFilter::class,
Export::class,
Import::class,
Setup::class,
+5
View File
@@ -0,0 +1,5 @@
<?php
namespace Lucent\Modules;
class ImageModule {}
+1 -5
View File
@@ -6,12 +6,10 @@ use Lucent\ArrayContainer;
class RecordData extends ArrayContainer
{
public function merge(RecordData $data): RecordData
{
$this->data = array_merge($this->data, $data->toArray());
return $this;
}
@@ -19,6 +17,4 @@ class RecordData extends ArrayContainer
{
return $this->data;
}
}
+8 -5
View File
@@ -44,9 +44,9 @@ if (!function_exists("schemas_path")) {
}
if (!function_exists("lucent_file")) {
function lucent_file(\Lucent\Data\File $file): string
function lucent_file(array $file): string
{
$path = $file->path;
$path = $file["path"];
return app()->make(\Lucent\Channel\ChannelService::class)->channel
->filesUrl .
"/" .
@@ -55,10 +55,13 @@ if (!function_exists("lucent_file")) {
}
if (!function_exists("lucent_image")) {
function lucent_image(\Lucent\Data\File $file, string $template): string
function lucent_image(array $file, string $template): string
{
$path = $file->path;
$path = $file["path"];
return app()->make(\Lucent\Channel\ChannelService::class)->channel
->filesUrl . "/templates/$template/$path";
->filesUrl .
"/templates/$template/" .
substr($path, 0, strrpos($path, ".")) .
".webp";
}
}