diff --git a/.gitignore b/.gitignore index 838d9c1..9c0185e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,3 @@ yarn-error.log /.opencode /build.sh /.junie -/.agents diff --git a/Dockerfile b/Dockerfile index 5af7b33..2d761ed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ ENV TRMNL_LIQUID_ENABLED=1 # Switch to the root user so we can do root things USER root -COPY --chown=www-data:www-data --from=bnussbau/trmnl-liquid-cli:0.2.0 /usr/local/bin/trmnl-liquid-cli /usr/local/bin/ +COPY --chown=www-data:www-data --from=bnussbau/trmnl-liquid-cli:0.1.0 /usr/local/bin/trmnl-liquid-cli /usr/local/bin/ # Set the working directory WORKDIR /var/www/html diff --git a/README.md b/README.md index 670b62c..2231b24 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,6 @@ php artisan db:seed --class=ExampleRecipesSeeder | `REGISTRATION_ENABLED` | Allow user registration via Webinterface | 1 | | `SSL_MODE` | SSL Mode, if not using a Reverse Proxy ([docs](https://serversideup.net/open-source/docker-php/docs/customizing-the-image/configuring-ssl)) | `off` | | `FORCE_HTTPS` | If your server handles SSL termination, enforce HTTPS. | 0 | -| `TRUSTED_PROXIES` | If your server handles SSL termination, allow mixed mode. e.g. `"172.0.0.0/8"` or `*` | null | | `PHP_OPCACHE_ENABLE` | Enable PHP Opcache | 0 | | `TRMNL_IMAGE_URL_TIMEOUT` | How long TRMNL waits for a response on the display endpoint. (sec) | 30 | | `APP_TIMEZONE` | Default timezone, which will be used by the PHP date functions | UTC | diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 5eeeb6b..bc46559 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -60,14 +60,8 @@ class Plugin extends Model }); static::updating(function ($model): void { - // Reset image cache when any markup changes - if ($model->isDirty([ - 'render_markup', - 'render_markup_half_horizontal', - 'render_markup_half_vertical', - 'render_markup_quadrant', - 'render_markup_shared', - ])) { + // Reset image cache when markup changes + if ($model->isDirty('render_markup')) { $model->current_image = null; } }); @@ -427,9 +421,7 @@ class Plugin extends Model throw new InvalidArgumentException('Render method is only applicable for recipe plugins.'); } - $markup = $this->getMarkupForSize($size); - - if ($markup) { + if ($this->render_markup) { $renderedContent = ''; if ($this->markup_language === 'liquid') { @@ -479,7 +471,7 @@ class Plugin extends Model // Check if external renderer should be used if ($this->preferred_renderer === 'trmnl-liquid' && config('services.trmnl.liquid_enabled')) { // Use external Ruby renderer - pass raw template without preprocessing - $renderedContent = $this->renderWithExternalLiquidRenderer($markup, $context); + $renderedContent = $this->renderWithExternalLiquidRenderer($this->render_markup, $context); } else { // Use PHP keepsuit/liquid renderer // Create a custom environment with inline templates support @@ -501,14 +493,14 @@ class Plugin extends Model $environment->tagRegistry->register(TemplateTag::class); // Apply Liquid replacements (including 'with' syntax conversion) - $processedMarkup = $this->applyLiquidReplacements($markup); + $processedMarkup = $this->applyLiquidReplacements($this->render_markup); $template = $environment->parseString($processedMarkup); $liquidContext = $environment->newRenderContext(data: $context); $renderedContent = $template->render($liquidContext); } } else { - $renderedContent = Blade::render($markup, [ + $renderedContent = Blade::render($this->render_markup, [ 'size' => $size, 'data' => $this->data_payload, 'config' => $this->configuration ?? [], @@ -589,30 +581,6 @@ class Plugin extends Model return $this->configuration[$key] ?? $default; } - /** - * Get the appropriate markup for a given size, including shared prepending logic - * - * @param string $size The layout size (full, half_horizontal, half_vertical, quadrant) - * @return string|null The markup code for the given size, with shared prepended if available - */ - public function getMarkupForSize(string $size): ?string - { - $markup = match ($size) { - 'full' => $this->render_markup, - 'half_horizontal' => $this->render_markup_half_horizontal ?? $this->render_markup, - 'half_vertical' => $this->render_markup_half_vertical ?? $this->render_markup, - 'quadrant' => $this->render_markup_quadrant ?? $this->render_markup, - default => $this->render_markup, - }; - - // Prepend shared markup if it exists - if ($markup && $this->render_markup_shared) { - $markup = $this->render_markup_shared."\n".$markup; - } - - return $markup; - } - public function getPreviewMashupLayoutForSize(string $size): string { return match ($size) { diff --git a/app/Services/PluginExportService.php b/app/Services/PluginExportService.php index be98461..241764d 100644 --- a/app/Services/PluginExportService.php +++ b/app/Services/PluginExportService.php @@ -51,35 +51,17 @@ class PluginExportService $settings = $this->generateSettingsYaml($plugin); $settingsYaml = Yaml::dump($settings, 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); File::put($tempDir.'/settings.yml', $settingsYaml); - + // Generate full template content + $fullTemplate = $this->generateFullTemplate($plugin); $extension = $plugin->markup_language === 'liquid' ? 'liquid' : 'blade.php'; - - // Export full template if it exists - if ($plugin->render_markup) { - $fullTemplate = $this->generateLayoutTemplate($plugin->render_markup); - File::put($tempDir.'/full.'.$extension, $fullTemplate); - } - - // Export layout-specific templates if they exist - if ($plugin->render_markup_half_horizontal) { - $halfHorizontalTemplate = $this->generateLayoutTemplate($plugin->render_markup_half_horizontal); - File::put($tempDir.'/half_horizontal.'.$extension, $halfHorizontalTemplate); - } - - if ($plugin->render_markup_half_vertical) { - $halfVerticalTemplate = $this->generateLayoutTemplate($plugin->render_markup_half_vertical); - File::put($tempDir.'/half_vertical.'.$extension, $halfVerticalTemplate); - } - - if ($plugin->render_markup_quadrant) { - $quadrantTemplate = $this->generateLayoutTemplate($plugin->render_markup_quadrant); - File::put($tempDir.'/quadrant.'.$extension, $quadrantTemplate); - } - - // Export shared template if it exists - if ($plugin->render_markup_shared) { - $sharedTemplate = $this->generateLayoutTemplate($plugin->render_markup_shared); - File::put($tempDir.'/shared.'.$extension, $sharedTemplate); + File::put($tempDir.'/full.'.$extension, $fullTemplate); + // Generate shared.liquid if needed (for liquid templates) + if ($plugin->markup_language === 'liquid') { + $sharedTemplate = $this->generateSharedTemplate(); + /** @phpstan-ignore-next-line */ + if ($sharedTemplate) { + File::put($tempDir.'/shared.liquid', $sharedTemplate); + } } // Create ZIP file $zipPath = $tempDir.'/plugin_'.$plugin->trmnlp_id.'.zip'; @@ -142,21 +124,29 @@ class PluginExportService } /** - * Generate template content from markup, removing wrapper divs if present + * Generate the full template content */ - private function generateLayoutTemplate(?string $markup): string + private function generateFullTemplate(Plugin $plugin): string { - if (! $markup) { - return ''; - } + $markup = $plugin->render_markup; - // Remove the wrapper div if it exists (it will be added during import for liquid) + // Remove the wrapper div if it exists (it will be added during import) $markup = preg_replace('/^
\s*/', '', $markup); $markup = preg_replace('/\s*<\/div>\s*$/', '', $markup); return mb_trim($markup); } + /** + * Generate the shared template content (for liquid templates) + */ + private function generateSharedTemplate(): null + { + // For now, we don't have a way to store shared templates separately + // TODO - add support for shared templates + return null; + } + /** * Add a directory and its contents to a ZIP file */ diff --git a/app/Services/PluginImportService.php b/app/Services/PluginImportService.php index f3e7a5c..51a9aee 100644 --- a/app/Services/PluginImportService.php +++ b/app/Services/PluginImportService.php @@ -93,59 +93,37 @@ class PluginImportService $settings = Yaml::parse($settingsYaml); $this->validateYAML($settings); - // Determine markup language from the first available file + // Determine which template file to use and read its content + $templatePath = null; $markupLanguage = 'blade'; - $firstTemplatePath = $filePaths['fullLiquidPath'] - ?? ($filePaths['halfHorizontalLiquidPath'] ?? null) - ?? ($filePaths['halfVerticalLiquidPath'] ?? null) - ?? ($filePaths['quadrantLiquidPath'] ?? null) - ?? ($filePaths['sharedLiquidPath'] ?? null) - ?? ($filePaths['sharedBladePath'] ?? null); - if ($firstTemplatePath && pathinfo((string) $firstTemplatePath, PATHINFO_EXTENSION) === 'liquid') { - $markupLanguage = 'liquid'; - } + if ($filePaths['fullLiquidPath']) { + $templatePath = $filePaths['fullLiquidPath']; + $fullLiquid = File::get($templatePath); - // Read full markup (don't prepend shared - it will be prepended at render time) - $fullLiquid = null; - if (isset($filePaths['fullLiquidPath']) && $filePaths['fullLiquidPath']) { - $fullLiquid = File::get($filePaths['fullLiquidPath']); - if ($markupLanguage === 'liquid') { + // Prepend shared.liquid or shared.blade.php content if available + if ($filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { + $sharedLiquid = File::get($filePaths['sharedLiquidPath']); + $fullLiquid = $sharedLiquid."\n".$fullLiquid; + } elseif ($filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { + $sharedBlade = File::get($filePaths['sharedBladePath']); + $fullLiquid = $sharedBlade."\n".$fullLiquid; + } + + // Check if the file ends with .liquid to set markup language + if (pathinfo((string) $templatePath, PATHINFO_EXTENSION) === 'liquid') { + $markupLanguage = 'liquid'; $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; } - } - - // Read shared markup separately - $sharedMarkup = null; - if (isset($filePaths['sharedLiquidPath']) && $filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { - $sharedMarkup = File::get($filePaths['sharedLiquidPath']); - } elseif (isset($filePaths['sharedBladePath']) && $filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { - $sharedMarkup = File::get($filePaths['sharedBladePath']); - } - - // Read layout-specific markups - $halfHorizontalMarkup = null; - if (isset($filePaths['halfHorizontalLiquidPath']) && $filePaths['halfHorizontalLiquidPath'] && File::exists($filePaths['halfHorizontalLiquidPath'])) { - $halfHorizontalMarkup = File::get($filePaths['halfHorizontalLiquidPath']); - if ($markupLanguage === 'liquid') { - $halfHorizontalMarkup = '
'."\n".$halfHorizontalMarkup."\n".'
'; - } - } - - $halfVerticalMarkup = null; - if (isset($filePaths['halfVerticalLiquidPath']) && $filePaths['halfVerticalLiquidPath'] && File::exists($filePaths['halfVerticalLiquidPath'])) { - $halfVerticalMarkup = File::get($filePaths['halfVerticalLiquidPath']); - if ($markupLanguage === 'liquid') { - $halfVerticalMarkup = '
'."\n".$halfVerticalMarkup."\n".'
'; - } - } - - $quadrantMarkup = null; - if (isset($filePaths['quadrantLiquidPath']) && $filePaths['quadrantLiquidPath'] && File::exists($filePaths['quadrantLiquidPath'])) { - $quadrantMarkup = File::get($filePaths['quadrantLiquidPath']); - if ($markupLanguage === 'liquid') { - $quadrantMarkup = '
'."\n".$quadrantMarkup."\n".'
'; - } + } elseif ($filePaths['sharedLiquidPath']) { + $templatePath = $filePaths['sharedLiquidPath']; + $fullLiquid = File::get($templatePath); + $markupLanguage = 'liquid'; + $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; + } elseif ($filePaths['sharedBladePath']) { + $templatePath = $filePaths['sharedBladePath']; + $fullLiquid = File::get($templatePath); + $markupLanguage = 'blade'; } // Ensure custom_fields is properly formatted @@ -182,10 +160,6 @@ class PluginImportService 'polling_body' => $settings['polling_body'] ?? null, 'markup_language' => $markupLanguage, 'render_markup' => $fullLiquid ?? null, - 'render_markup_half_horizontal' => $halfHorizontalMarkup, - 'render_markup_half_vertical' => $halfVerticalMarkup, - 'render_markup_quadrant' => $quadrantMarkup, - 'render_markup_shared' => $sharedMarkup, 'configuration_template' => $configurationTemplate, 'data_payload' => json_decode($settings['static_data'] ?? '{}', true), ]); @@ -272,59 +246,37 @@ class PluginImportService $settings = Yaml::parse($settingsYaml); $this->validateYAML($settings); - // Determine markup language from the first available file + // Determine which template file to use and read its content + $templatePath = null; $markupLanguage = 'blade'; - $firstTemplatePath = $filePaths['fullLiquidPath'] - ?? ($filePaths['halfHorizontalLiquidPath'] ?? null) - ?? ($filePaths['halfVerticalLiquidPath'] ?? null) - ?? ($filePaths['quadrantLiquidPath'] ?? null) - ?? ($filePaths['sharedLiquidPath'] ?? null) - ?? ($filePaths['sharedBladePath'] ?? null); - if ($firstTemplatePath && pathinfo((string) $firstTemplatePath, PATHINFO_EXTENSION) === 'liquid') { - $markupLanguage = 'liquid'; - } + if ($filePaths['fullLiquidPath']) { + $templatePath = $filePaths['fullLiquidPath']; + $fullLiquid = File::get($templatePath); - // Read full markup (don't prepend shared - it will be prepended at render time) - $fullLiquid = null; - if (isset($filePaths['fullLiquidPath']) && $filePaths['fullLiquidPath']) { - $fullLiquid = File::get($filePaths['fullLiquidPath']); - if ($markupLanguage === 'liquid') { + // Prepend shared.liquid or shared.blade.php content if available + if ($filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { + $sharedLiquid = File::get($filePaths['sharedLiquidPath']); + $fullLiquid = $sharedLiquid."\n".$fullLiquid; + } elseif ($filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { + $sharedBlade = File::get($filePaths['sharedBladePath']); + $fullLiquid = $sharedBlade."\n".$fullLiquid; + } + + // Check if the file ends with .liquid to set markup language + if (pathinfo((string) $templatePath, PATHINFO_EXTENSION) === 'liquid') { + $markupLanguage = 'liquid'; $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; } - } - - // Read shared markup separately - $sharedMarkup = null; - if (isset($filePaths['sharedLiquidPath']) && $filePaths['sharedLiquidPath'] && File::exists($filePaths['sharedLiquidPath'])) { - $sharedMarkup = File::get($filePaths['sharedLiquidPath']); - } elseif (isset($filePaths['sharedBladePath']) && $filePaths['sharedBladePath'] && File::exists($filePaths['sharedBladePath'])) { - $sharedMarkup = File::get($filePaths['sharedBladePath']); - } - - // Read layout-specific markups - $halfHorizontalMarkup = null; - if (isset($filePaths['halfHorizontalLiquidPath']) && $filePaths['halfHorizontalLiquidPath'] && File::exists($filePaths['halfHorizontalLiquidPath'])) { - $halfHorizontalMarkup = File::get($filePaths['halfHorizontalLiquidPath']); - if ($markupLanguage === 'liquid') { - $halfHorizontalMarkup = '
'."\n".$halfHorizontalMarkup."\n".'
'; - } - } - - $halfVerticalMarkup = null; - if (isset($filePaths['halfVerticalLiquidPath']) && $filePaths['halfVerticalLiquidPath'] && File::exists($filePaths['halfVerticalLiquidPath'])) { - $halfVerticalMarkup = File::get($filePaths['halfVerticalLiquidPath']); - if ($markupLanguage === 'liquid') { - $halfVerticalMarkup = '
'."\n".$halfVerticalMarkup."\n".'
'; - } - } - - $quadrantMarkup = null; - if (isset($filePaths['quadrantLiquidPath']) && $filePaths['quadrantLiquidPath'] && File::exists($filePaths['quadrantLiquidPath'])) { - $quadrantMarkup = File::get($filePaths['quadrantLiquidPath']); - if ($markupLanguage === 'liquid') { - $quadrantMarkup = '
'."\n".$quadrantMarkup."\n".'
'; - } + } elseif ($filePaths['sharedLiquidPath']) { + $templatePath = $filePaths['sharedLiquidPath']; + $fullLiquid = File::get($templatePath); + $markupLanguage = 'liquid'; + $fullLiquid = '
'."\n".$fullLiquid."\n".'
'; + } elseif ($filePaths['sharedBladePath']) { + $templatePath = $filePaths['sharedBladePath']; + $fullLiquid = File::get($templatePath); + $markupLanguage = 'blade'; } // Ensure custom_fields is properly formatted @@ -370,10 +322,6 @@ class PluginImportService 'polling_body' => $settings['polling_body'] ?? null, 'markup_language' => $markupLanguage, 'render_markup' => $fullLiquid ?? null, - 'render_markup_half_horizontal' => $halfHorizontalMarkup, - 'render_markup_half_vertical' => $halfVerticalMarkup, - 'render_markup_quadrant' => $quadrantMarkup, - 'render_markup_shared' => $sharedMarkup, 'configuration_template' => $configurationTemplate, 'data_payload' => json_decode($settings['static_data'] ?? '{}', true), 'preferred_renderer' => $preferredRenderer, @@ -409,9 +357,6 @@ class PluginImportService $fullLiquidPath = null; $sharedLiquidPath = null; $sharedBladePath = null; - $halfHorizontalLiquidPath = null; - $halfVerticalLiquidPath = null; - $quadrantLiquidPath = null; // If zipEntryPath is specified, look for files in that specific directory first if ($zipEntryPath) { @@ -432,25 +377,6 @@ class PluginImportService } elseif (File::exists($targetDir.'/shared.blade.php')) { $sharedBladePath = $targetDir.'/shared.blade.php'; } - - // Check for layout-specific files - if (File::exists($targetDir.'/half_horizontal.liquid')) { - $halfHorizontalLiquidPath = $targetDir.'/half_horizontal.liquid'; - } elseif (File::exists($targetDir.'/half_horizontal.blade.php')) { - $halfHorizontalLiquidPath = $targetDir.'/half_horizontal.blade.php'; - } - - if (File::exists($targetDir.'/half_vertical.liquid')) { - $halfVerticalLiquidPath = $targetDir.'/half_vertical.liquid'; - } elseif (File::exists($targetDir.'/half_vertical.blade.php')) { - $halfVerticalLiquidPath = $targetDir.'/half_vertical.blade.php'; - } - - if (File::exists($targetDir.'/quadrant.liquid')) { - $quadrantLiquidPath = $targetDir.'/quadrant.liquid'; - } elseif (File::exists($targetDir.'/quadrant.blade.php')) { - $quadrantLiquidPath = $targetDir.'/quadrant.blade.php'; - } } // Check if files are in src subdirectory of target directory @@ -468,25 +394,6 @@ class PluginImportService } elseif (File::exists($targetDir.'/src/shared.blade.php')) { $sharedBladePath = $targetDir.'/src/shared.blade.php'; } - - // Check for layout-specific files in src - if (File::exists($targetDir.'/src/half_horizontal.liquid')) { - $halfHorizontalLiquidPath = $targetDir.'/src/half_horizontal.liquid'; - } elseif (File::exists($targetDir.'/src/half_horizontal.blade.php')) { - $halfHorizontalLiquidPath = $targetDir.'/src/half_horizontal.blade.php'; - } - - if (File::exists($targetDir.'/src/half_vertical.liquid')) { - $halfVerticalLiquidPath = $targetDir.'/src/half_vertical.liquid'; - } elseif (File::exists($targetDir.'/src/half_vertical.blade.php')) { - $halfVerticalLiquidPath = $targetDir.'/src/half_vertical.blade.php'; - } - - if (File::exists($targetDir.'/src/quadrant.liquid')) { - $quadrantLiquidPath = $targetDir.'/src/quadrant.liquid'; - } elseif (File::exists($targetDir.'/src/quadrant.blade.php')) { - $quadrantLiquidPath = $targetDir.'/src/quadrant.blade.php'; - } } // If we found the required files in the target directory, return them @@ -518,25 +425,6 @@ class PluginImportService } elseif (File::exists($tempDir.'/src/shared.blade.php')) { $sharedBladePath = $tempDir.'/src/shared.blade.php'; } - - // Check for layout-specific files - if (File::exists($tempDir.'/src/half_horizontal.liquid')) { - $halfHorizontalLiquidPath = $tempDir.'/src/half_horizontal.liquid'; - } elseif (File::exists($tempDir.'/src/half_horizontal.blade.php')) { - $halfHorizontalLiquidPath = $tempDir.'/src/half_horizontal.blade.php'; - } - - if (File::exists($tempDir.'/src/half_vertical.liquid')) { - $halfVerticalLiquidPath = $tempDir.'/src/half_vertical.liquid'; - } elseif (File::exists($tempDir.'/src/half_vertical.blade.php')) { - $halfVerticalLiquidPath = $tempDir.'/src/half_vertical.blade.php'; - } - - if (File::exists($tempDir.'/src/quadrant.liquid')) { - $quadrantLiquidPath = $tempDir.'/src/quadrant.liquid'; - } elseif (File::exists($tempDir.'/src/quadrant.blade.php')) { - $quadrantLiquidPath = $tempDir.'/src/quadrant.blade.php'; - } } else { // Search for the files in the extracted directory structure $directories = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS); @@ -554,12 +442,6 @@ class PluginImportService $sharedLiquidPath = $filepath; } elseif ($filename === 'shared.blade.php') { $sharedBladePath = $filepath; - } elseif ($filename === 'half_horizontal.liquid' || $filename === 'half_horizontal.blade.php') { - $halfHorizontalLiquidPath = $filepath; - } elseif ($filename === 'half_vertical.liquid' || $filename === 'half_vertical.blade.php') { - $halfVerticalLiquidPath = $filepath; - } elseif ($filename === 'quadrant.liquid' || $filename === 'quadrant.blade.php') { - $quadrantLiquidPath = $filepath; } } @@ -603,25 +485,6 @@ class PluginImportService $sharedBladePath = $newSrcDir.'/shared.blade.php'; } - // Copy layout-specific files if they exist - if ($halfHorizontalLiquidPath) { - $extension = pathinfo((string) $halfHorizontalLiquidPath, PATHINFO_EXTENSION); - File::copy($halfHorizontalLiquidPath, $newSrcDir.'/half_horizontal.'.$extension); - $halfHorizontalLiquidPath = $newSrcDir.'/half_horizontal.'.$extension; - } - - if ($halfVerticalLiquidPath) { - $extension = pathinfo((string) $halfVerticalLiquidPath, PATHINFO_EXTENSION); - File::copy($halfVerticalLiquidPath, $newSrcDir.'/half_vertical.'.$extension); - $halfVerticalLiquidPath = $newSrcDir.'/half_vertical.'.$extension; - } - - if ($quadrantLiquidPath) { - $extension = pathinfo((string) $quadrantLiquidPath, PATHINFO_EXTENSION); - File::copy($quadrantLiquidPath, $newSrcDir.'/quadrant.'.$extension); - $quadrantLiquidPath = $newSrcDir.'/quadrant.'.$extension; - } - // Update the paths $settingsYamlPath = $newSrcDir.'/settings.yml'; } @@ -633,9 +496,6 @@ class PluginImportService 'fullLiquidPath' => $fullLiquidPath, 'sharedLiquidPath' => $sharedLiquidPath, 'sharedBladePath' => $sharedBladePath, - 'halfHorizontalLiquidPath' => $halfHorizontalLiquidPath, - 'halfVerticalLiquidPath' => $halfVerticalLiquidPath, - 'quadrantLiquidPath' => $quadrantLiquidPath, ]; } diff --git a/composer.json b/composer.json index 96e0079..d856e75 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "ext-imagick": "*", "ext-simplexml": "*", "ext-zip": "*", - "bnussbau/laravel-trmnl-blade": "2.1.1", + "bnussbau/laravel-trmnl-blade": "2.2.*", "bnussbau/trmnl-pipeline-php": "^0.6.0", "keepsuit/laravel-liquid": "^0.5.2", "laravel/fortify": "^1.30", diff --git a/composer.lock b/composer.lock index a61b132..ec617d3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "60a7e51edd8408cffdb901e4a1c1684a", + "content-hash": "581bacf794841fc11c540e152c704d16", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.29", + "version": "3.369.27", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "068195b2980cf5cf4ade2515850d461186db3310" + "reference": "f844afab2a74eb3cf881970a9c31de460510eb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/068195b2980cf5cf4ade2515850d461186db3310", - "reference": "068195b2980cf5cf4ade2515850d461186db3310", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f844afab2a74eb3cf881970a9c31de460510eb74", + "reference": "f844afab2a74eb3cf881970a9c31de460510eb74", "shasum": "" }, "require": { @@ -153,9 +153,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.29" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.27" }, - "time": "2026-02-06T19:08:50+00:00" + "time": "2026-02-04T19:07:08+00:00" }, { "name": "bacon/bacon-qr-code", @@ -214,16 +214,16 @@ }, { "name": "bnussbau/laravel-trmnl-blade", - "version": "2.1.1", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/bnussbau/laravel-trmnl-blade.git", - "reference": "6ad96eba917ebc30ebe550e6fce4a995e94f6b35" + "reference": "6db8a82a15ccedcaaffd3b37d0d337d276a26669" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bnussbau/laravel-trmnl-blade/zipball/6ad96eba917ebc30ebe550e6fce4a995e94f6b35", - "reference": "6ad96eba917ebc30ebe550e6fce4a995e94f6b35", + "url": "https://api.github.com/repos/bnussbau/laravel-trmnl-blade/zipball/6db8a82a15ccedcaaffd3b37d0d337d276a26669", + "reference": "6db8a82a15ccedcaaffd3b37d0d337d276a26669", "shasum": "" }, "require": { @@ -278,7 +278,7 @@ ], "support": { "issues": "https://github.com/bnussbau/laravel-trmnl-blade/issues", - "source": "https://github.com/bnussbau/laravel-trmnl-blade/tree/2.1.1" + "source": "https://github.com/bnussbau/laravel-trmnl-blade/tree/2.2.1" }, "funding": [ { @@ -294,7 +294,7 @@ "type": "github" } ], - "time": "2026-01-29T20:40:42+00:00" + "time": "2026-02-05T17:57:37+00:00" }, { "name": "bnussbau/trmnl-pipeline-php", @@ -3194,16 +3194,16 @@ }, { "name": "livewire/livewire", - "version": "v4.1.3", + "version": "v4.1.2", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "69c871cb15fb95f10cda5acd1ee7e63cd3c494c8" + "reference": "8adef21f35f4ffa87fd2f3655b350236df0c39a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/69c871cb15fb95f10cda5acd1ee7e63cd3c494c8", - "reference": "69c871cb15fb95f10cda5acd1ee7e63cd3c494c8", + "url": "https://api.github.com/repos/livewire/livewire/zipball/8adef21f35f4ffa87fd2f3655b350236df0c39a8", + "reference": "8adef21f35f4ffa87fd2f3655b350236df0c39a8", "shasum": "" }, "require": { @@ -3258,7 +3258,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v4.1.3" + "source": "https://github.com/livewire/livewire/tree/v4.1.2" }, "funding": [ { @@ -3266,7 +3266,7 @@ "type": "github" } ], - "time": "2026-02-06T12:19:55+00:00" + "time": "2026-02-03T03:01:29+00:00" }, { "name": "maennchen/zipstream-php", @@ -9066,16 +9066,16 @@ }, { "name": "laravel/boost", - "version": "v2.1.1", + "version": "v2.0.6", "source": { "type": "git", "url": "https://github.com/laravel/boost.git", - "reference": "1c7d6f44c96937a961056778b9143218b1183302" + "reference": "1e1cb76e8e87ca3dd3c3d64deccbc97f4de38215" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/boost/zipball/1c7d6f44c96937a961056778b9143218b1183302", - "reference": "1c7d6f44c96937a961056778b9143218b1183302", + "url": "https://api.github.com/repos/laravel/boost/zipball/1e1cb76e8e87ca3dd3c3d64deccbc97f4de38215", + "reference": "1e1cb76e8e87ca3dd3c3d64deccbc97f4de38215", "shasum": "" }, "require": { @@ -9128,7 +9128,7 @@ "issues": "https://github.com/laravel/boost/issues", "source": "https://github.com/laravel/boost" }, - "time": "2026-02-06T10:41:29+00:00" + "time": "2026-02-04T10:10:48+00:00" }, { "name": "laravel/mcp", @@ -10484,16 +10484,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.3", + "version": "12.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d" + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b015312f28dd75b75d3422ca37dff2cd1a565e8d", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b", + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b", "shasum": "" }, "require": { @@ -10549,7 +10549,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2" }, "funding": [ { @@ -10569,7 +10569,7 @@ "type": "tidelift" } ], - "time": "2026-02-06T06:01:44+00:00" + "time": "2025-12-24T07:03:04+00:00" }, { "name": "phpunit/php-file-iterator", @@ -10935,21 +10935,21 @@ }, { "name": "rector/rector", - "version": "2.3.6", + "version": "2.3.5", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b" + "reference": "9442f4037de6a5347ae157fe8e6c7cda9d909070" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/ca9ebb81d280cd362ea39474dabd42679e32ca6b", - "reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9442f4037de6a5347ae157fe8e6c7cda9d909070", + "reference": "9442f4037de6a5347ae157fe8e6c7cda9d909070", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.38" + "phpstan/phpstan": "^2.1.36" }, "conflict": { "rector/rector-doctrine": "*", @@ -10983,7 +10983,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.3.6" + "source": "https://github.com/rectorphp/rector/tree/2.3.5" }, "funding": [ { @@ -10991,7 +10991,7 @@ "type": "github" } ], - "time": "2026-02-06T14:25:06+00:00" + "time": "2026-01-28T15:22:48+00:00" }, { "name": "sebastian/cli-parser", diff --git a/database/migrations/2026_01_28_143142_add_layout_markup_columns_to_plugins_table.php b/database/migrations/2026_01_28_143142_add_layout_markup_columns_to_plugins_table.php deleted file mode 100644 index e56751c..0000000 --- a/database/migrations/2026_01_28_143142_add_layout_markup_columns_to_plugins_table.php +++ /dev/null @@ -1,38 +0,0 @@ -text('render_markup_half_horizontal')->nullable()->after('render_markup'); - $table->text('render_markup_half_vertical')->nullable()->after('render_markup_half_horizontal'); - $table->text('render_markup_quadrant')->nullable()->after('render_markup_half_vertical'); - $table->text('render_markup_shared')->nullable()->after('render_markup_quadrant'); - $table->text('transform_code')->nullable()->after('render_markup_shared'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('plugins', function (Blueprint $table) { - $table->dropColumn([ - 'render_markup_half_horizontal', - 'render_markup_half_vertical', - 'render_markup_quadrant', - 'render_markup_shared', - 'transform_code', - ]); - }); - } -}; diff --git a/resources/views/livewire/device-models/index.blade.php b/resources/views/livewire/device-models/index.blade.php index 1aebeb1..6ec4014 100644 --- a/resources/views/livewire/device-models/index.blade.php +++ b/resources/views/livewire/device-models/index.blade.php @@ -1,6 +1,5 @@ deviceModels = DeviceModel::all(); - $this->devicePalettes = DevicePalette::all(); - session()->flash('message', 'Device models updated from API.'); - } - public function openDeviceModelModal(?string $deviceModelId = null, bool $viewOnly = false): void { if ($deviceModelId) { @@ -238,17 +229,9 @@ new class extends Component
- - - Add Device Model - - - - - Update from Models API - - - + + Add Device Model + @if (session()->has('message'))
diff --git a/resources/views/livewire/device-palettes/index.blade.php b/resources/views/livewire/device-palettes/index.blade.php index 4e96c31..6640545 100644 --- a/resources/views/livewire/device-palettes/index.blade.php +++ b/resources/views/livewire/device-palettes/index.blade.php @@ -1,6 +1,5 @@ devicePalettes = DevicePalette::all(); - session()->flash('message', 'Device palettes updated from API.'); - } - public function openDevicePaletteModal(?string $devicePaletteId = null, bool $viewOnly = false): void { if ($devicePaletteId) { @@ -210,17 +202,9 @@ new class extends Component
- - - Add Device Palette - - - - - Update from API - - - + + Add Device Palette + @if (session()->has('message'))
diff --git a/resources/views/livewire/devices/configure.blade.php b/resources/views/livewire/devices/configure.blade.php index 4c9b4c5..93183cf 100644 --- a/resources/views/livewire/devices/configure.blade.php +++ b/resources/views/livewire/devices/configure.blade.php @@ -31,10 +31,6 @@ new class extends Component public $device_model_id; - public $is_mirror = false; - - public $mirror_device_id = null; - // Signal to device to use high compatibility approaches when redrawing content public $maximum_compatibility = false; @@ -102,8 +98,6 @@ new class extends Component $this->sleep_mode_from = optional($device->sleep_mode_from)->format('H:i'); $this->sleep_mode_to = optional($device->sleep_mode_to)->format('H:i'); $this->special_function = $device->special_function; - $this->is_mirror = $device->mirror_device_id !== null; - $this->mirror_device_id = $device->mirror_device_id; return view('livewire.devices.configure', [ 'image' => ($current_image_uuid) ? url($current_image_path) : null, @@ -151,7 +145,6 @@ new class extends Component 'rotate' => 'required|integer|min:0|max:359', 'image_format' => 'required|string', 'device_model_id' => 'nullable|exists:device_models,id', - 'mirror_device_id' => 'required_if:is_mirror,true', 'maximum_compatibility' => 'boolean', 'sleep_mode_enabled' => 'boolean', 'sleep_mode_from' => 'nullable|date_format:H:i', @@ -159,13 +152,6 @@ new class extends Component 'special_function' => 'nullable|string', ]); - if ($this->is_mirror) { - $mirrorDevice = auth()->user()->devices()->find($this->mirror_device_id); - abort_unless($mirrorDevice, 403, 'Invalid mirror device selected'); - abort_if($mirrorDevice->mirror_device_id !== null, 403, 'Cannot mirror a device that is already a mirror device'); - abort_if((int) $this->mirror_device_id === (int) $this->device->id, 403, 'Device cannot mirror itself'); - } - // Convert empty string to null for custom selection $deviceModelId = empty($this->device_model_id) ? null : $this->device_model_id; @@ -179,7 +165,6 @@ new class extends Component 'rotate' => $this->rotate, 'image_format' => $this->image_format, 'device_model_id' => $deviceModelId, - 'mirror_device_id' => $this->is_mirror ? $this->mirror_device_id : null, 'maximum_compatibility' => $this->maximum_compatibility, 'sleep_mode_enabled' => $this->sleep_mode_enabled, 'sleep_mode_from' => $this->sleep_mode_from, @@ -448,18 +433,6 @@ new class extends Component @endforeach - - @if($is_mirror) - - Select a device - @foreach(auth()->user()->devices->where('mirror_device_id', null)->where('id', '!=', $device->id) as $mirrorOption) - - {{ $mirrorOption->name }} ({{ $mirrorOption->friendly_id }}) - - @endforeach - - @endif - @if(empty($device_model_id)) diff --git a/resources/views/livewire/plugins/index.blade.php b/resources/views/livewire/plugins/index.blade.php index 848fc67..90f8aa0 100644 --- a/resources/views/livewire/plugins/index.blade.php +++ b/resources/views/livewire/plugins/index.blade.php @@ -258,6 +258,7 @@ new class extends Component
Limitations
    +
  • Only full view will be imported; shared markup will be prepended
  • Some Liquid filters may be not supported or behave differently
  • API responses in formats other than JSON are not yet supported
  • {{--
      --}} @@ -311,6 +312,7 @@ new class extends Component Limitations
        +
      • Only full view will be imported; shared markup will be prepended
      • Requires trmnl-liquid-cli executable.
      • API responses in formats other than JSON are not yet fully supported.
      • There are limitations in payload size (Data Payload, Template).
      • diff --git a/resources/views/livewire/plugins/recipe.blade.php b/resources/views/livewire/plugins/recipe.blade.php index a7b3918..cda019e 100644 --- a/resources/views/livewire/plugins/recipe.blade.php +++ b/resources/views/livewire/plugins/recipe.blade.php @@ -65,12 +65,6 @@ new class extends Component public string $preview_size = 'full'; - public array $markup_layouts = []; - - public array $active_tabs = []; - - public string $active_tab = 'full'; - public function mount(): void { abort_unless(auth()->user()->plugins->contains($this->plugin), 403); @@ -97,24 +91,7 @@ new class extends Component $this->view_content = null; } } else { - // Initialize layout markups from plugin columns - $this->markup_layouts = [ - 'full' => $this->plugin->render_markup ?? '', - 'half_horizontal' => $this->plugin->render_markup_half_horizontal ?? '', - 'half_vertical' => $this->plugin->render_markup_half_vertical ?? '', - 'quadrant' => $this->plugin->render_markup_quadrant ?? '', - 'shared' => $this->plugin->render_markup_shared ?? '', - ]; - - // Set active tabs based on which layouts have content - $this->active_tabs = ['full']; // Full is always active - foreach (['half_horizontal', 'half_vertical', 'quadrant', 'shared'] as $layout) { - if (! empty($this->markup_layouts[$layout])) { - $this->active_tabs[] = $layout; - } - } - - $this->markup_code = $this->markup_layouts['full']; + $this->markup_code = $this->plugin->render_markup; $this->markup_language = $this->plugin->markup_language ?? 'blade'; } @@ -148,108 +125,12 @@ new class extends Component { abort_unless(auth()->user()->plugins->contains($this->plugin), 403); $this->validate(); - - // Update markup_code for the active tab - if (isset($this->markup_layouts[$this->active_tab])) { - $this->markup_layouts[$this->active_tab] = $this->markup_code ?? ''; - } - - // Save all layout markups to respective columns $this->plugin->update([ - 'render_markup' => $this->markup_layouts['full'] ?? null, - 'render_markup_half_horizontal' => ! empty($this->markup_layouts['half_horizontal']) ? $this->markup_layouts['half_horizontal'] : null, - 'render_markup_half_vertical' => ! empty($this->markup_layouts['half_vertical']) ? $this->markup_layouts['half_vertical'] : null, - 'render_markup_quadrant' => ! empty($this->markup_layouts['quadrant']) ? $this->markup_layouts['quadrant'] : null, - 'render_markup_shared' => ! empty($this->markup_layouts['shared']) ? $this->markup_layouts['shared'] : null, + 'render_markup' => $this->markup_code ?? null, 'markup_language' => $this->markup_language ?? null, ]); } - public function addLayoutTab(string $layout): void - { - if (! in_array($layout, $this->active_tabs, true)) { - $this->active_tabs[] = $layout; - if (! isset($this->markup_layouts[$layout])) { - $this->markup_layouts[$layout] = ''; - } - $this->switchTab($layout); - } - } - - public function removeLayoutTab(string $layout): void - { - if ($layout !== 'full') { - $this->active_tabs = array_values(array_filter($this->active_tabs, fn ($tab) => $tab !== $layout)); - if (isset($this->markup_layouts[$layout])) { - $this->markup_layouts[$layout] = ''; - } - if ($this->active_tab === $layout) { - $this->active_tab = 'full'; - $this->markup_code = $this->markup_layouts['full'] ?? ''; - } - } - } - - public function switchTab(string $layout): void - { - if (in_array($layout, $this->active_tabs, true)) { - // Save current tab's content before switching - if (isset($this->markup_layouts[$this->active_tab])) { - $this->markup_layouts[$this->active_tab] = $this->markup_code ?? ''; - } - - $this->active_tab = $layout; - $this->markup_code = $this->markup_layouts[$layout] ?? ''; - } - } - - public function toggleLayoutTab(string $layout): void - { - if ($layout === 'full') { - return; - } - - if (in_array($layout, $this->active_tabs, true)) { - $this->removeLayoutTab($layout); - } else { - $this->addLayoutTab($layout); - } - } - - public function getAvailableLayouts(): array - { - return [ - 'half_horizontal' => 'Half Horizontal', - 'half_vertical' => 'Half Vertical', - 'quadrant' => 'Quadrant', - 'shared' => 'Shared', - ]; - } - - public function getLayoutLabel(string $layout): string - { - return match ($layout) { - 'full' => $this->getFullTabLabel(), - 'half_horizontal' => 'Half Horizontal', - 'half_vertical' => 'Half Vertical', - 'quadrant' => 'Quadrant', - 'shared' => 'Shared', - default => ucfirst($layout), - }; - } - - public function getFullTabLabel(): string - { - // Return "Full" if any layout-specific markup exists, otherwise "Responsive" - if (! empty($this->markup_layouts['half_horizontal']) - || ! empty($this->markup_layouts['half_vertical']) - || ! empty($this->markup_layouts['quadrant'])) { - return 'Full'; - } - - return 'Responsive'; - } - protected array $rules = [ 'name' => 'required|string|max:255', 'data_stale_minutes' => 'required|integer|min:1', @@ -1137,75 +1018,41 @@ HTML; @if(!$plugin->render_markup_view)
        -
        -
        - @foreach($active_tabs as $tab) - - @endforeach - - - - - @foreach($this->getAvailableLayouts() as $layout => $label) - -
        - @if(in_array($layout, $active_tabs, true)) - - @else - - @endif - {{ $label }} -
        -
        - @endforeach -
        -
        -
        - -
        - - @php - $textareaId = 'code-' . $plugin->id; - @endphp - {{ $markup_language === 'liquid' ? 'Liquid Code' : 'Blade Code' }} - +
        diff --git a/resources/views/livewire/plugins/recipes/settings.blade.php b/resources/views/livewire/plugins/recipes/settings.blade.php index 540af89..c83f52c 100644 --- a/resources/views/livewire/plugins/recipes/settings.blade.php +++ b/resources/views/livewire/plugins/recipes/settings.blade.php @@ -17,8 +17,6 @@ new class extends Component public bool $alias = false; - public bool $use_trmnl_liquid_renderer = false; - public int $resetIndex = 0; public function mount(): void @@ -29,7 +27,6 @@ new class extends Component $this->trmnlp_id = $this->plugin->trmnlp_id; $this->uuid = $this->plugin->uuid; $this->alias = $this->plugin->alias ?? false; - $this->use_trmnl_liquid_renderer = $this->plugin->preferred_renderer === 'trmnl-liquid'; } public function saveTrmnlpId(): void @@ -46,13 +43,11 @@ new class extends Component ->ignore($this->plugin->id), ], 'alias' => 'boolean', - 'use_trmnl_liquid_renderer' => 'boolean', ]); $this->plugin->update([ 'trmnlp_id' => empty($this->trmnlp_id) ? null : $this->trmnlp_id, 'alias' => $this->alias, - 'preferred_renderer' => $this->use_trmnl_liquid_renderer ? 'trmnl-liquid' : null, ]); Flux::modal('trmnlp-settings')->close(); @@ -88,16 +83,6 @@ new class extends Component Enable an Alias URL for this recipe. Your server does not need to be exposed to the internet, but your device must be able to reach the URL. Docs - @if(config('services.trmnl.liquid_enabled') && $plugin->markup_language === 'liquid') - - - trmnl-liquid is a Ruby-based renderer that matches the Core service’s Liquid behavior for better compatibility. - - @endif - @if($alias) Alias URL diff --git a/tests/Feature/DeviceModelsTest.php b/tests/Feature/DeviceModelsTest.php index ac00af3..14a374d 100644 --- a/tests/Feature/DeviceModelsTest.php +++ b/tests/Feature/DeviceModelsTest.php @@ -4,8 +4,6 @@ declare(strict_types=1); use App\Models\DeviceModel; use App\Models\User; -use Illuminate\Support\Facades\Http; -use Livewire\Livewire; it('allows a user to view the device models page', function (): void { $user = User::factory()->create(); @@ -89,38 +87,3 @@ it('redirects unauthenticated users from the device models page', function (): v $response->assertRedirect('/login'); }); - -it('update from API runs job and refreshes device models', function (): void { - $user = User::factory()->create(); - $this->actingAs($user); - - Http::fake([ - 'usetrmnl.com/api/palettes' => Http::response(['data' => []], 200), - config('services.trmnl.base_url').'/api/models' => Http::response([ - 'data' => [ - [ - 'name' => 'api-model', - 'label' => 'API Model', - 'description' => 'From API', - 'width' => 800, - 'height' => 480, - 'colors' => 4, - 'bit_depth' => 2, - 'scale_factor' => 1.0, - 'rotation' => 0, - 'mime_type' => 'image/png', - 'offset_x' => 0, - 'offset_y' => 0, - 'kind' => 'trmnl', - 'published_at' => '2023-01-01T00:00:00Z', - ], - ], - ], 200), - ]); - - $component = Livewire::test('device-models.index') - ->call('updateFromApi'); - - $deviceModels = $component->get('deviceModels'); - expect($deviceModels->pluck('name')->toArray())->toContain('api-model'); -}); diff --git a/tests/Feature/Devices/DeviceConfigureTest.php b/tests/Feature/Devices/DeviceConfigureTest.php index bf4e19e..dff0954 100644 --- a/tests/Feature/Devices/DeviceConfigureTest.php +++ b/tests/Feature/Devices/DeviceConfigureTest.php @@ -5,7 +5,6 @@ namespace Tests\Feature; use App\Models\Device; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; -use Livewire\Livewire; use function Pest\Laravel\actingAs; @@ -24,35 +23,3 @@ test('configure view displays last_refreshed_at timestamp', function (): void { $response->assertOk() ->assertSee('5 minutes ago'); }); - -test('configure edit modal shows mirror checkbox and allows unchecking mirror', function (): void { - $user = User::factory()->create(); - actingAs($user); - - $deviceAttributes = [ - 'user_id' => $user->id, - 'width' => 800, - 'height' => 480, - 'rotate' => 0, - 'image_format' => 'png', - 'maximum_compatibility' => false, - ]; - $sourceDevice = Device::factory()->create($deviceAttributes); - $mirrorDevice = Device::factory()->create([ - ...$deviceAttributes, - 'mirror_device_id' => $sourceDevice->id, - ]); - - $response = $this->get(route('devices.configure', $mirrorDevice)); - $response->assertOk() - ->assertSee('Mirrors Device') - ->assertSee('Select Device to Mirror'); - - Livewire::test('devices.configure', ['device' => $mirrorDevice]) - ->set('is_mirror', false) - ->call('updateDevice') - ->assertHasNoErrors(); - - $mirrorDevice->refresh(); - expect($mirrorDevice->mirror_device_id)->toBeNull(); -}); diff --git a/tests/Feature/Livewire/DevicePalettesTest.php b/tests/Feature/Livewire/DevicePalettesTest.php index abd4b24..3c37934 100644 --- a/tests/Feature/Livewire/DevicePalettesTest.php +++ b/tests/Feature/Livewire/DevicePalettesTest.php @@ -4,7 +4,6 @@ declare(strict_types=1); use App\Models\DevicePalette; use App\Models\User; -use Illuminate\Support\Facades\Http; uses(Illuminate\Foundation\Testing\RefreshDatabase::class); @@ -571,29 +570,3 @@ test('component refreshes palette list after deleting', function (): void { expect($palettes)->toHaveCount($initialCount + 1); expect(DevicePalette::count())->toBe($initialCount + 1); }); - -test('update from API runs job and refreshes device palettes', function (): void { - $user = User::factory()->create(); - $this->actingAs($user); - - Http::fake([ - 'usetrmnl.com/api/palettes' => Http::response([ - 'data' => [ - [ - 'id' => 'api-palette', - 'name' => 'API Palette', - 'grays' => 4, - 'colors' => null, - 'framework_class' => '', - ], - ], - ], 200), - config('services.trmnl.base_url').'/api/models' => Http::response(['data' => []], 200), - ]); - - $component = Livewire::test('device-palettes.index') - ->call('updateFromApi'); - - $devicePalettes = $component->get('devicePalettes'); - expect($devicePalettes->pluck('name')->toArray())->toContain('api-palette'); -}); diff --git a/tests/Feature/Livewire/Plugins/RecipeSettingsTest.php b/tests/Feature/Livewire/Plugins/RecipeSettingsTest.php index e15ee8b..c625262 100644 --- a/tests/Feature/Livewire/Plugins/RecipeSettingsTest.php +++ b/tests/Feature/Livewire/Plugins/RecipeSettingsTest.php @@ -109,43 +109,3 @@ test('recipe settings can clear trmnlp_id', function (): void { expect($plugin->fresh()->trmnlp_id)->toBeNull(); }); - -test('recipe settings saves preferred_renderer when liquid enabled and recipe is liquid', function (): void { - config(['services.trmnl.liquid_enabled' => true]); - - $user = User::factory()->create(); - $this->actingAs($user); - - $plugin = Plugin::factory()->create([ - 'user_id' => $user->id, - 'markup_language' => 'liquid', - 'preferred_renderer' => null, - ]); - - Livewire::test('plugins.recipes.settings', ['plugin' => $plugin]) - ->set('use_trmnl_liquid_renderer', true) - ->call('saveTrmnlpId') - ->assertHasNoErrors(); - - expect($plugin->fresh()->preferred_renderer)->toBe('trmnl-liquid'); -}); - -test('recipe settings clears preferred_renderer when checkbox unchecked', function (): void { - config(['services.trmnl.liquid_enabled' => true]); - - $user = User::factory()->create(); - $this->actingAs($user); - - $plugin = Plugin::factory()->create([ - 'user_id' => $user->id, - 'markup_language' => 'liquid', - 'preferred_renderer' => 'trmnl-liquid', - ]); - - Livewire::test('plugins.recipes.settings', ['plugin' => $plugin]) - ->set('use_trmnl_liquid_renderer', false) - ->call('saveTrmnlpId') - ->assertHasNoErrors(); - - expect($plugin->fresh()->preferred_renderer)->toBeNull(); -}); diff --git a/tests/Feature/PluginImportTest.php b/tests/Feature/PluginImportTest.php index aa1706f..cc47e67 100644 --- a/tests/Feature/PluginImportTest.php +++ b/tests/Feature/PluginImportTest.php @@ -52,10 +52,8 @@ it('imports plugin with shared.liquid file', function (): void { $pluginImportService = new PluginImportService(); $plugin = $pluginImportService->importFromZip($zipFile, $user); - expect($plugin->render_markup_shared)->toBe('{% comment %}Shared styles{% endcomment %}') - ->and($plugin->render_markup)->toContain('
        ') - ->and($plugin->getMarkupForSize('full'))->toContain('{% comment %}Shared styles{% endcomment %}') - ->and($plugin->getMarkupForSize('full'))->toContain('
        '); + expect($plugin->render_markup)->toContain('{% comment %}Shared styles{% endcomment %}') + ->and($plugin->render_markup)->toContain('
        '); }); it('imports plugin with files in root directory', function (): void { @@ -204,10 +202,8 @@ it('imports plugin from monorepo with shared.liquid in subdirectory', function ( $pluginImportService = new PluginImportService(); $plugin = $pluginImportService->importFromZip($zipFile, $user); - expect($plugin->render_markup_shared)->toBe('{% comment %}Monorepo shared styles{% endcomment %}') - ->and($plugin->render_markup)->toContain('
        ') - ->and($plugin->getMarkupForSize('full'))->toContain('{% comment %}Monorepo shared styles{% endcomment %}') - ->and($plugin->getMarkupForSize('full'))->toContain('
        '); + expect($plugin->render_markup)->toContain('{% comment %}Monorepo shared styles{% endcomment %}') + ->and($plugin->render_markup)->toContain('
        '); }); it('imports plugin from URL with zip_entry_path parameter', function (): void { @@ -356,10 +352,8 @@ it('imports specific plugin from monorepo zip with zip_entry_path parameter', fu expect($plugin)->toBeInstanceOf(Plugin::class) ->and($plugin->user_id)->toBe($user->id) ->and($plugin->name)->toBe('Example Plugin 2') // Should import example-plugin2, not example-plugin - ->and($plugin->render_markup_shared)->toBe('{% comment %}Plugin 2 shared styles{% endcomment %}') - ->and($plugin->render_markup)->toContain('
        Plugin 2 content
        ') - ->and($plugin->getMarkupForSize('full'))->toContain('{% comment %}Plugin 2 shared styles{% endcomment %}') - ->and($plugin->getMarkupForSize('full'))->toContain('
        Plugin 2 content
        '); + ->and($plugin->render_markup)->toContain('{% comment %}Plugin 2 shared styles{% endcomment %}') + ->and($plugin->render_markup)->toContain('
        Plugin 2 content
        '); }); it('sets icon_url when importing from URL with iconUrl parameter', function (): void { @@ -522,8 +516,8 @@ it('imports plugin with only shared.liquid file', function (): void { expect($plugin)->toBeInstanceOf(Plugin::class) ->and($plugin->markup_language)->toBe('liquid') - ->and($plugin->render_markup_shared)->toBe('
        {{ data.title }}
        ') - ->and($plugin->render_markup)->toBeNull(); + ->and($plugin->render_markup)->toContain('
        ') + ->and($plugin->render_markup)->toContain('
        {{ data.title }}
        '); }); it('imports plugin with only shared.blade.php file', function (): void { @@ -541,8 +535,8 @@ it('imports plugin with only shared.blade.php file', function (): void { expect($plugin)->toBeInstanceOf(Plugin::class) ->and($plugin->markup_language)->toBe('blade') - ->and($plugin->render_markup_shared)->toBe('
        {{ $data["title"] }}
        ') - ->and($plugin->render_markup)->toBeNull(); + ->and($plugin->render_markup)->toBe('
        {{ $data["title"] }}
        ') + ->and($plugin->render_markup)->not->toContain('
        '); }); // Helper methods