From f28ac2f8691c6d0638230bf57c8a4ece36e7c5be Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Wed, 15 Jun 2022 16:26:22 +0200 Subject: [PATCH] wip #4210 @1 --- ...ePreview.php => FluidbookThemePreview.php} | 4 +- .../Admin/FluidbookThemePreviewController.php | 9 ++- app/Jobs/GenerateThemePreview.php | 13 +++- .../js/social_screenshot/social_screenshot.js | 28 -------- .../js/theme_preview/install-mouse-helper.js | 71 +++++++++++++++++++ resources/js/theme_preview/theme_preview.js | 37 ++++++++++ routes/web.php | 1 + 7 files changed, 128 insertions(+), 35 deletions(-) rename app/Console/Commands/{ThemePreview.php => FluidbookThemePreview.php} (87%) delete mode 100644 resources/js/social_screenshot/social_screenshot.js create mode 100644 resources/js/theme_preview/install-mouse-helper.js create mode 100644 resources/js/theme_preview/theme_preview.js diff --git a/app/Console/Commands/ThemePreview.php b/app/Console/Commands/FluidbookThemePreview.php similarity index 87% rename from app/Console/Commands/ThemePreview.php rename to app/Console/Commands/FluidbookThemePreview.php index bb23b0945..62a103a51 100644 --- a/app/Console/Commands/ThemePreview.php +++ b/app/Console/Commands/FluidbookThemePreview.php @@ -8,7 +8,7 @@ use Cubist\Backpack\Console\Commands\CubistCommand; use Cubist\Util\ArrayUtil; use Illuminate\Database\Query\Builder; -class ThemePreview extends CubistCommand +class FluidbookThemePreview extends CubistCommand { protected $signature = 'fluidbook:theme:preview {id?}'; protected $description = 'Generate a theme preview'; @@ -17,7 +17,7 @@ class ThemePreview extends CubistCommand { $themeId = $this->argument('id'); /** @var Builder $q */ - $q = FluidbookTheme::where('created_ok', '1'); + $q = FluidbookTheme::where('created_ok', '1')->orderBy('id', 'desc'); if (null !== $themeId) { $themeIds = ArrayUtil::parseRange($themeId); $q->whereIn('id', $themeIds); diff --git a/app/Http/Controllers/Admin/FluidbookThemePreviewController.php b/app/Http/Controllers/Admin/FluidbookThemePreviewController.php index 879ebb043..80dd93e38 100644 --- a/app/Http/Controllers/Admin/FluidbookThemePreviewController.php +++ b/app/Http/Controllers/Admin/FluidbookThemePreviewController.php @@ -8,7 +8,7 @@ use Cubist\Backpack\Http\Controllers\Base\XSendFileController; class FluidbookThemePreviewController extends XSendFileController { - public function preview($id) + public function preview($id, $variant = '') { /** @var FluidbookTheme $theme */ $theme = FluidbookTheme::find($id); @@ -18,6 +18,11 @@ class FluidbookThemePreviewController extends XSendFileController if (!$theme->canList(backpack_user())) { return response()->setStatusCode(403); } - return $this->xSendFile(GenerateThemePreview::getPreviewPath($theme->id)); + return $this->xSendFile(GenerateThemePreview::getPreviewPath($theme->id, $variant)); + } + + public function previewMenu($id) + { + return $this->preview($id, 'menu'); } } diff --git a/app/Jobs/GenerateThemePreview.php b/app/Jobs/GenerateThemePreview.php index c49c72d72..914965475 100644 --- a/app/Jobs/GenerateThemePreview.php +++ b/app/Jobs/GenerateThemePreview.php @@ -35,22 +35,29 @@ class GenerateThemePreview extends Base public function handle() { $path = self::getPreviewPath($this->theme->getIdValue()); + $pathmenu = self::getPreviewPath($this->theme->getIdValue(), 'menu'); $cl = new CommandLine('node'); - $cl->setArg(null, resource_path('js/social_screenshot/social_screenshot.js')); + $cl->setArg(null, resource_path('js/theme_preview/theme_preview.js')); $cl->setArg('width', 1024); $cl->setArg('height', 768); $cl->setArg('delay', 2); $cl->setArg('scale', 1); $cl->setArg('dest', $path); + $cl->setArg('destmenu', $pathmenu); $cl->setArg('page', 2); $url = $this->theme->getPreviewURL(['shortLoading' => 1, 'transition' => 1]); $cl->setArg('url', $url); $cl->execute(); } - public static function getPreviewPath($themeId) + public static function getPreviewPath($themeId, $variant = '') { - return storage_path('themes') . '/' . $themeId . '.jpg'; + $res = storage_path('themes') . '/' . $themeId; + if ($variant) { + $res .= '-' . $variant; + } + $res .= '.jpg'; + return $res; } } diff --git a/resources/js/social_screenshot/social_screenshot.js b/resources/js/social_screenshot/social_screenshot.js deleted file mode 100644 index e0f909dd8..000000000 --- a/resources/js/social_screenshot/social_screenshot.js +++ /dev/null @@ -1,28 +0,0 @@ -const puppeteer = require('puppeteer'); -const commandLineArgs = require('command-line-args'); -const optionDefinitions = [ - {name: 'url', type: String}, - {name: 'dest', type: String}, - {name: 'delay', type: Number, defaultOption: 10}, - {name: 'scale', type: Number, defaultOption: 1}, - {name: 'width', type: Number, defaultOption: 1920}, - {name: 'height', type: Number, defaultOption: 1080}, - {name: 'page', type: Number, defaultOption: 2} -]; - -(async () => { - const options = commandLineArgs(optionDefinitions); - const browser = await puppeteer.launch({headless: true}); - const page = await browser.newPage(); - await page.setViewport({ - width: options.width / options.scale, - height: options.height / options.scale, - deviceScaleFactor: options.scale, - }); - await page.goto(options.url, {waitUntil: 'networkidle2'}); - await new Promise(r => setTimeout(r, 1000 * (options.delay -1))); - await page.evaluate(() => fluidbook.setCurrentPage(2)); - await new Promise(r => setTimeout(r, 1000)); - await page.screenshot({path: options.dest, type: 'jpeg', quality: 95}); - await browser.close(); -})(); diff --git a/resources/js/theme_preview/install-mouse-helper.js b/resources/js/theme_preview/install-mouse-helper.js new file mode 100644 index 000000000..c378776c9 --- /dev/null +++ b/resources/js/theme_preview/install-mouse-helper.js @@ -0,0 +1,71 @@ +// This injects a box into the page that moves with the mouse; +// Useful for debugging +async function installMouseHelper(page) { + await page.evaluateOnNewDocument(() => { + // Install mouse helper only for top-level frame. + if (window !== window.parent) return; + window.addEventListener('DOMContentLoaded', () => { + const box = document.createElement('puppeteer-mouse-pointer'); + const styleElement = document.createElement('style'); + styleElement.innerHTML = ` + puppeteer-mouse-pointer { + pointer-events: none; + position: absolute; + top: 0; + z-index: 10000; + left: 0; + width: 10px; + height: 10px; + background: rgba(0,0,0,.25); + border: 1px solid white; + border-radius: 50%; + margin: -5px 0 0 -5px; + padding: 0; + transition: background .2s, border-radius .2s, border-color .2s; + } + puppeteer-mouse-pointer.button-1 { + transition: none; + background: rgba(0,0,0,0.9); + } + puppeteer-mouse-pointer.button-2 { + transition: none; + border-color: rgba(0,0,255,0.9); + } + puppeteer-mouse-pointer.button-3 { + transition: none; + border-radius: 4px; + } + puppeteer-mouse-pointer.button-4 { + transition: none; + border-color: rgba(255,0,0,0.9); + } + puppeteer-mouse-pointer.button-5 { + transition: none; + border-color: rgba(0,255,0,0.9); + } + `; + document.head.appendChild(styleElement); + document.body.appendChild(box); + document.addEventListener('mousemove', event => { + box.style.left = event.pageX + 'px'; + box.style.top = event.pageY + 'px'; + updateButtons(event.buttons); + }, true); + document.addEventListener('mousedown', event => { + updateButtons(event.buttons); + box.classList.add('button-' + event.which); + }, true); + document.addEventListener('mouseup', event => { + updateButtons(event.buttons); + box.classList.remove('button-' + event.which); + }, true); + + function updateButtons(buttons) { + for (let i = 0; i < 5; i++) box.classList.toggle('button-' + i, buttons & (1 << i)); + } + }, false); + }); +}; + +module.exports = {installMouseHelper}; + diff --git a/resources/js/theme_preview/theme_preview.js b/resources/js/theme_preview/theme_preview.js new file mode 100644 index 000000000..3bfa4e2d4 --- /dev/null +++ b/resources/js/theme_preview/theme_preview.js @@ -0,0 +1,37 @@ +const puppeteer = require('puppeteer'); +const commandLineArgs = require('command-line-args'); +const optionDefinitions = [{name: 'url', type: String}, {name: 'dest', type: String}, { + name: 'destmenu', + type: String +}, {name: 'delay', type: Number, defaultOption: 10}, {name: 'scale', type: Number, defaultOption: 1}, { + name: 'width', + type: Number, + defaultOption: 1920 +}, {name: 'height', type: Number, defaultOption: 1080}, {name: 'page', type: Number, defaultOption: 2}]; + +(async () => { + const {installMouseHelper} = require('./install-mouse-helper'); + const options = commandLineArgs(optionDefinitions); + const browser = await puppeteer.launch({headless: true}); + const page = await browser.newPage(); + await page.setViewport({ + width: options.width / options.scale, height: options.height / options.scale, deviceScaleFactor: options.scale, + }); + await installMouseHelper(page); + await page.goto(options.url, {waitUntil: 'networkidle2'}); + await new Promise(r => setTimeout(r, 1000 * (options.delay - 1))); + + // Set page and take a screenshot + await page.evaluate(() => fluidbook.slider.hover(512)); + await page.evaluate(() => fluidbook.setCurrentPage(2)); + await page.mouse.move(150, 300); + + await new Promise(r => setTimeout(r, 1000)); + await page.screenshot({path: options.dest, type: 'jpeg', quality: 95}); + + // // Open share menu and take a screenshot + // await page.evaluate(() => fluidbook.menu.openView('share')); + // await new Promise(r => setTimeout(r, 500)); + // await page.screenshot({path: options.destmenu, type: 'jpeg', quality: 95}); + await browser.close(); +})(); diff --git a/routes/web.php b/routes/web.php index 1d2ba8678..ccba5f0d1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -10,4 +10,5 @@ Route::group([ Route::any('tools/{tool}/{args?}', 'ToolsController@index')->where(['args' => '.*']); Route::post('toolbox_setting', 'ToolboxSettingsController@set'); Route::get('fluidbookthemepreview/{id}.jpg', 'FluidbookThemePreviewController@preview'); + Route::get('fluidbookthemepreview/{id}-menu.jpg', 'FluidbookThemePreviewController@previewMenu'); }); -- 2.39.5