--- /dev/null
+<?php
+
+namespace App\Console\Commands;
+
+use App\Jobs\GenerateThemePreview;
+use App\Models\FluidbookTheme;
+use Cubist\Backpack\Console\Commands\CubistCommand;
+use Cubist\Util\ArrayUtil;
+use Illuminate\Database\Query\Builder;
+
+class FluidbookThemePreview extends CubistCommand
+{
+ protected $signature = 'fluidbook:theme:preview {id?}';
+ protected $description = 'Generate a theme preview';
+
+ public function handle()
+ {
+ $themeId = $this->argument('id');
+ /** @var Builder $q */
+ $q = FluidbookTheme::where('created_ok', '1')->orderBy('id', 'desc');
+ if (null !== $themeId) {
+ $themeIds = ArrayUtil::parseRange($themeId);
+ $q->whereIn('id', $themeIds);
+ }
+ $themes = $q->get();
+ $this->progressBar = $this->output->createProgressBar(count($themes));
+ $this->progressBar->start();
+
+ foreach ($themes as $theme) {
+ dispatch_sync(new GenerateThemePreview($theme));
+ $this->progressBar->advance();
+ }
+ }
+}
+++ /dev/null
-<?php
-
-namespace App\Console\Commands;
-
-use App\Jobs\GenerateThemePreview;
-use App\Models\FluidbookTheme;
-use Cubist\Backpack\Console\Commands\CubistCommand;
-use Cubist\Util\ArrayUtil;
-use Illuminate\Database\Query\Builder;
-
-class ThemePreview extends CubistCommand
-{
- protected $signature = 'fluidbook:theme:preview {id?}';
- protected $description = 'Generate a theme preview';
-
- public function handle()
- {
- $themeId = $this->argument('id');
- /** @var Builder $q */
- $q = FluidbookTheme::where('created_ok', '1');
- if (null !== $themeId) {
- $themeIds = ArrayUtil::parseRange($themeId);
- $q->whereIn('id', $themeIds);
- }
- $themes = $q->get();
- $this->progressBar = $this->output->createProgressBar(count($themes));
- $this->progressBar->start();
-
- foreach ($themes as $theme) {
- dispatch_sync(new GenerateThemePreview($theme));
- $this->progressBar->advance();
- }
- }
-}
class FluidbookThemePreviewController extends XSendFileController
{
- public function preview($id)
+ public function preview($id, $variant = '')
{
/** @var FluidbookTheme $theme */
$theme = FluidbookTheme::find($id);
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');
}
}
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;
}
}
+++ /dev/null
-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();
-})();
--- /dev/null
+// 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};
+
--- /dev/null
+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();
+})();
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');
});