diff options
Diffstat (limited to 'electron/src')
| -rw-r--r-- | electron/src/index.ejs | 32 | ||||
| -rw-r--r-- | electron/src/index.html | 20 | ||||
| -rw-r--r-- | electron/src/lib/api.js | 18 | ||||
| -rw-r--r-- | electron/src/lib/i18n.js | 22 | ||||
| -rw-r--r-- | electron/src/main/index.dev.js | 32 | ||||
| -rw-r--r-- | electron/src/main/index.js | 169 | ||||
| -rw-r--r-- | electron/src/main/preload.js | 7 | ||||
| -rw-r--r-- | electron/src/renderer/App.vue | 11 | ||||
| -rw-r--r-- | electron/src/renderer/assets/js/simulator.js | 64 | ||||
| -rw-r--r-- | electron/src/renderer/assets/style/simulator.css | 41 | ||||
| -rw-r--r-- | electron/src/renderer/components/InstallPalettes.vue | 123 | ||||
| -rw-r--r-- | electron/src/renderer/components/NotFound.vue | 12 | ||||
| -rw-r--r-- | electron/src/renderer/components/Preferences.vue | 55 | ||||
| -rw-r--r-- | electron/src/renderer/components/Simulator.vue | 17 | ||||
| -rw-r--r-- | electron/src/renderer/main.js | 151 | ||||
| -rw-r--r-- | electron/src/renderer/router/index.js | 44 |
16 files changed, 323 insertions, 495 deletions
diff --git a/electron/src/index.ejs b/electron/src/index.ejs deleted file mode 100644 index 381a86c7..00000000 --- a/electron/src/index.ejs +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - - Authors: see git history - - Copyright (c) 2010 Authors - Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - ---> -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>inkstitch-gui</title> - <% if (htmlWebpackPlugin.options.nodeModules) { %> - <!-- Add `node_modules/` to global paths so `require` works properly in development --> - <script> - require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>') - </script> - <% } %> - </head> - <body> - <div id="app"></div> - <!-- Set `__static` path to static files in production --> - <% if (!process.browser) { %> - <script> - if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\') - </script> - <% } %> - - <!-- webpack builds are automatically injected --> - </body> -</html> diff --git a/electron/src/index.html b/electron/src/index.html new file mode 100644 index 00000000..1eb6fbab --- /dev/null +++ b/electron/src/index.html @@ -0,0 +1,20 @@ +<!-- + + Authors: see git history + + Copyright (c) 2010 Authors + Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +--> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + </head> + <body> + <div id="app"></div> + </body> +</html> +<script> +global = globalThis +</script> diff --git a/electron/src/lib/api.js b/electron/src/lib/api.js index b6aa74e2..63818541 100644 --- a/electron/src/lib/api.js +++ b/electron/src/lib/api.js @@ -6,11 +6,19 @@ * */ -const axios = require('axios') -const queryString = require('query-string') +import axios from 'axios'; +import flaskserverport from './flaskserverport.json' -var port = queryString.parse(global.location.search).port +if (flaskserverport.port === undefined) { + var theflaskport = window.inkstitchAPI.flaskport() + console.log("Installed mode") + console.log(theflaskport) +} else { + var theflaskport = flaskserverport.port + console.log("Dev mode") + console.log(theflaskport) +} -module.exports = axios.create({ - baseURL: `http://127.0.0.1:${port}/` +export const inkStitch = axios.create({ + baseURL: `http://127.0.0.1:${theflaskport}` }) diff --git a/electron/src/lib/i18n.js b/electron/src/lib/i18n.js index de56fc8f..2a7c4f66 100644 --- a/electron/src/lib/i18n.js +++ b/electron/src/lib/i18n.js @@ -6,22 +6,33 @@ * */ -module.exports.selectLanguage = function (translations) { +export function selectLanguage(translations, flaskport) { + var port = flaskport + // get language from flask server, process in modern electron isn't exposed to renderer + const request = new XMLHttpRequest(); + request.open('GET', `http://127.0.0.1:${port}/languages`, false) + request.send(null) + var process = undefined + + if (request.status === 200) { + process = JSON.parse(request.responseText) + } // get a list of available translations var availableTranslations = ['en_US']; - for(var k in translations) availableTranslations.push(k); + for (var k in translations) availableTranslations.push(k); var lang = undefined; // get system language / Inkscape language ['LANG', 'LC_MESSAGES', 'LC_ALL', 'LANGUAGE'].forEach(language => { - if (process.env[language]) { + if (process[language]) { // split encoding information, we don't need it - var current_lang = process.env[language].split(".")[0]; + var current_lang = process[language].split('.')[0]; + if (current_lang.length == 2) { // current language has only two letters (e.g. en), // compare with available languages and if present, set to a long locale name (e.g. en_US) - lang = availableTranslations.find(elem => elem.startsWith(current_lang)); + lang = availableTranslations.find((elem) => elem.startsWith(current_lang)); } else { lang = current_lang; } @@ -33,3 +44,4 @@ module.exports.selectLanguage = function (translations) { } return lang } + diff --git a/electron/src/main/index.dev.js b/electron/src/main/index.dev.js deleted file mode 100644 index 7fc8c159..00000000 --- a/electron/src/main/index.dev.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Authors: see git history - * - * Copyright (c) 2010 Authors - * Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - * - */ - -/** - * This file is used specifically and only for development. It installs - * `electron-debug` & `vue-devtools`. There shouldn't be any need to - * modify this file, but it can be used to extend your development - * environment. - */ - -/* eslint-disable */ - -// Install `electron-debug` with `devtron` -require('electron-debug')({ showDevTools: true }) - -// Install `vue-devtools` -require('electron').app.on('ready', () => { - let installExtension = require('electron-devtools-installer') - installExtension.default(installExtension.VUEJS_DEVTOOLS) - .then(() => {}) - .catch(err => { - console.log('Unable to install `vue-devtools`: \n', err) - }) -}) - -// Require `main` process to boot app -require('./index') diff --git a/electron/src/main/index.js b/electron/src/main/index.js index d6f259fe..546580ea 100644 --- a/electron/src/main/index.js +++ b/electron/src/main/index.js @@ -8,113 +8,104 @@ 'use strict' -import {app, BrowserWindow, ipcMain, dialog, shell} from 'electron' -var fs = require('fs'); -var path = require('path'); -var tmp = require('tmp'); - +const path = require('path') +const fs = require('fs') +const tmp = require('tmp') const url = require('url') +const { app, BrowserWindow, ipcMain, dialog, shell, Menu} = require('electron') +// url for printPDF flask server which is used in development and production mode -/** - * Set `__static` path to static files in production - * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html - */ -if (process.env.NODE_ENV === 'development') { - // we were run as electron --inspect=5858 path/to/main.js <args> - // so get rid of the first two args - console.log("args " + process.argv) - process.argv.shift() - process.argv.shift() -} else { - global.__static = path.join(__dirname, '/static').replace(/\\/g, '\\\\') -} +var port = process.env.FLASKPORT +const printPdfUrl = `http://127.0.0.1:${port}/` -let mainWindow +const isDev = process.env.BABEL_ENV === 'development' -var target = process.argv[1] || ""; +var target = null +// Finds this url in the argv array and sets to target value +if (process.argv.includes(printPdfUrl)) { + target = printPdfUrl +} else { + target = process.argv[1] || ""; +} var targetURL = url.parse(target) -var winURL = null; +var winURL = null -// Print PDF will give us a full URL to a flask server, bypassing Vue entirely. // Eventually this will be migrated to Vue. if (targetURL.protocol) { - winURL = target + winURL = target } else { - if (process.env.NODE_ENV === 'development') { - winURL = `http://localhost:9080/?${targetURL.query || ""}#${targetURL.pathname || ""}` - } else { - winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}`; - } + winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}` } function createWindow() { - /** - * Initial window options - */ - mainWindow = new BrowserWindow({ - height: 563, - useContentSize: true, - width: 1000, - webPreferences: {nodeIntegration: true} - }) - - mainWindow.loadURL(winURL) - mainWindow.maximize() - - mainWindow.on('closed', () => { - mainWindow = null - }) -} - -app.on('ready', createWindow) - -app.on('window-all-closed', () => { - app.quit() -}) - -app.on('activate', () => { - if (mainWindow === null) { - createWindow() - } -}) - -ipcMain.on('save-pdf', function (event, pageSize) { - mainWindow.webContents.printToPDF({"pageSize": pageSize}, function(error, data) { - dialog.showSaveDialog(mainWindow, {"defaultPath": "inkstitch.pdf", - "filters": [{ name: 'PDF', extensions: ['pdf'] }] - }, function(filename, bookmark) { - if (typeof filename !== 'undefined') - fs.writeFileSync(filename, data, 'utf-8'); + const mainWindow = new BrowserWindow({ + useContentSize: true, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + nodeIntegration: false, + contextIsolation: true, + }, + }) + if (isDev) { + // printPDF in development mode will have dev tools activated + // Vuejs parts of Ink/Stich will not and dev tools must be accessed though the menu of electron window + mainWindow.loadURL(winURL) + mainWindow.webContents.openDevTools() + } else { + mainWindow.loadURL(winURL) + } + // This will remove the menu from the release, in dev mode the menu is available. + if(process.platform === "darwin" && !isDev) { + Menu.setApplicationMenu(Menu.buildFromTemplate([])); + } if(process.platform === "win32" || process.platform === "linux" && !isDev) { + mainWindow.removeMenu(); + } + mainWindow.maximize() + // save to PDF + ipcMain.on('save-pdf', (event, pageSize) => { + const webContents = event.sender + const win = BrowserWindow.fromWebContents(webContents) + const saveOpt = { + title: "Save PDF", + defaultPath: "Inkstitch.pdf", + bookmark: "true", + } + win.webContents.printToPDF({}).then(pageSize => { + dialog.showSaveDialog(saveOpt).then(filename => { + const { filePath } = filename; + fs.writeFileSync(filePath, pageSize, (error) => { + if (error) { + throw error + } + console.log(`Wrote PDF successfully to ${pdfPath}`) + }) + }).catch(error => { + console.log(`Failed to write PDF to ${pdfPath}: `, error) }) + }) }) -}) - -ipcMain.on('open-pdf', function (event, pageSize) { - mainWindow.webContents.printToPDF({"pageSize": pageSize}, function(error, data) { + // openPDF + ipcMain.on('open-pdf', (event, pageSize) => { + const webContents = event.sender + const win = BrowserWindow.fromWebContents(webContents) + win.webContents.printToPDF({}).then(pageSize => { tmp.file({keep: true, discardDescriptor: true}, function(err, path, fd, cleanupCallback) { - fs.writeFileSync(path, data, 'utf-8'); - shell.openItem(path); + fs.writeFileSync(path, pageSize, 'utf-8'); + shell.openPath(path); + }) }) }) -}) - - -/** - * Auto Updater - * - * Uncomment the following code below and install `electron-updater` to - * support auto updating. Code Signing with a valid certificate is required. - * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating - */ - -/* -import { autoUpdater } from 'electron-updater' +} -autoUpdater.on('update-downloaded', () => { - autoUpdater.quitAndInstall() +app.whenReady().then(() => { + createWindow() + app.on('activate', () => { + if(BrowserWindow.getAllWindows().length === 0) { + createWindow() + } + }) }) -app.on('ready', () => { - if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates() +app.on('window-all-closed', () => { + app.quit() }) - */ diff --git a/electron/src/main/preload.js b/electron/src/main/preload.js new file mode 100644 index 00000000..b7d1c02a --- /dev/null +++ b/electron/src/main/preload.js @@ -0,0 +1,7 @@ +const { contextBridge, ipcRenderer } = require ('electron') + +contextBridge.exposeInMainWorld('inkstitchAPI', { + savepdf: (pageSize) => { ipcRenderer.send('save-pdf', pageSize) }, + openpdf: (pageSize) => { ipcRenderer.send('open-pdf', pageSize) }, + flaskport: () => process.env.FLASKPORT, +}) diff --git a/electron/src/renderer/App.vue b/electron/src/renderer/App.vue index 2e5bbb9d..b98b1399 100644 --- a/electron/src/renderer/App.vue +++ b/electron/src/renderer/App.vue @@ -9,20 +9,9 @@ <template> <div id="app"> - <v-app> - <v-main> <router-view></router-view> - </v-main> - </v-app> </div> </template> - -<script> -export default { - name: 'my-project' -} -</script> - <style> @import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'); </style> diff --git a/electron/src/renderer/assets/js/simulator.js b/electron/src/renderer/assets/js/simulator.js index 186e3e30..8a0423f3 100644 --- a/electron/src/renderer/assets/js/simulator.js +++ b/electron/src/renderer/assets/js/simulator.js @@ -5,19 +5,18 @@ * Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. * */ +import { inkStitch } from '../../../lib/api.js' -const inkStitch = require("../../../lib/api") -const Mousetrap = require("mousetrap") import { SVG } from '@svgdotjs/svg.js' -require('@svgdotjs/svg.panzoom.js/src/svg.panzoom.js') -require('@svgdotjs/svg.filter.js') -const svgpath = require('svgpath') +import '@svgdotjs/svg.panzoom.js' +import '@svgdotjs/svg.filter.js' +import svgpath from 'svgpath' import Loading from 'vue-loading-overlay'; import 'vue-loading-overlay/dist/vue-loading.css'; +import { reactive, toRefs } from 'vue' import VueSlider from 'vue-slider-component' -import 'vue-slider-component/theme/default.css' - -const throttle = require('lodash.throttle') +import 'vue-slider-component/theme/antd.css' +import throttle from 'lodash/throttle' function SliderMark(command, icon) { this.label = "" @@ -31,6 +30,10 @@ export default { Loading, VueSlider }, + setup() { + const data = reactive({ value: 0 }) + return toRefs(data) + }, data: function () { return { loading: false, @@ -511,15 +514,23 @@ export default { }, generatePage () { this.$refs.simulator.style.backgroundColor = this.page_specs.deskcolor + let page = this.svg.rect(this.page_specs.width, this.page_specs.height) .move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1]) .fill(this.page_specs.pagecolor) - .stroke({width: 1, color: 'black'}) - .filterWith(add => { - let blur = add.offset(2,2).in(add.$sourceAlpha).gaussianBlur(2) - add.blend(add.$source, blur) - }) + .stroke({width: 0.1, color: this.page_specs.bordercolor}) .back() + + if (this.page_specs.showpageshadow === "true") { + let shadow = this.svg.rect(this.page_specs.width, this.page_specs.height) + .move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1]) + .fill(this.page_specs.bordercolor) + .filterWith(add => { + let blur = add.offset(.5,.5).in(add.$source).gaussianBlur(.5) + }) + .back() + } + this.page_specs["bbox"] = page.bbox() }, zoomDesign () { @@ -606,29 +617,30 @@ export default { this.generateColorSections() this.generateScale() this.generateCursor() - + this.resizeCursor() + this.loading = false // v-on:keydown doesn't seem to work, maybe an Electron issue? - Mousetrap.bind("up", this.animationSpeedUp) - Mousetrap.bind("down", this.animationSlowDown) - Mousetrap.bind("left", this.animationReverse) - Mousetrap.bind("right", this.animationForward) - Mousetrap.bind("pagedown", this.animationPreviousCommand) - Mousetrap.bind("pageup", this.animationNextCommand) - Mousetrap.bind("space", this.toggleAnimation) - Mousetrap.bind("+", this.animationForwardOneStitch) - Mousetrap.bind("-", this.animationBackwardOneStitch) - Mousetrap.bind("]", this.zoomDesign) - Mousetrap.bind("[", this.zoomPage) + this.$mousetrap.bind("up", this.animationSpeedUp) + this.$mousetrap.bind("down", this.animationSlowDown) + this.$mousetrap.bind("left", this.animationReverse) + this.$mousetrap.bind("right", this.animationForward) + this.$mousetrap.bind("pagedown", this.animationPreviousCommand) + this.$mousetrap.bind("pageup", this.animationNextCommand) + this.$mousetrap.bind("space", this.toggleAnimation) + this.$mousetrap.bind("+", this.animationForwardOneStitch) + this.$mousetrap.bind("-", this.animationBackwardOneStitch) + this.$mousetrap.bind("]", this.zoomDesign) + this.$mousetrap.bind("[", this.zoomPage) this.svg.on('zoom', this.resizeCursor) - this.resizeCursor() inkStitch.get('page_specs').then(response => { this.page_specs = response.data this.generatePage() }) + this.start() }) } diff --git a/electron/src/renderer/assets/style/simulator.css b/electron/src/renderer/assets/style/simulator.css index 64047a7e..e938cbe3 100644 --- a/electron/src/renderer/assets/style/simulator.css +++ b/electron/src/renderer/assets/style/simulator.css @@ -5,11 +5,10 @@ * Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. * */ - -* { - box-sizing: border-box; + * { + padding: 1px; + margin: 1px; } - .loading-icon { text-align: center; margin-bottom: 1rem; @@ -32,7 +31,7 @@ button { align-items: flex-start; text-align: center; cursor: default; - background-color: buttonface; + background: linear-gradient(0deg, rgba(169,169,169,1) 0%, rgba(255,255,255,1) 68%, rgba(227,227,227,1) 100%); box-sizing: border-box; padding: 2px 6px 3px; border-width: 2px; @@ -183,7 +182,7 @@ button.pressed { } .vue-slider { - height: 25px !important; + height: 10px !important; margin-bottom: 14px; } @@ -203,7 +202,7 @@ button.pressed { margin-right: 10px; } -.slider-container::v-deep .vue-slider-mark-step { +.slider-container :deep(.vue-slider-mark-step) { width: 2px; height: 20px; border-radius: 2px; @@ -212,26 +211,26 @@ button.pressed { box-shadow: inset 1px 0 1px #ffffffbd, inset -1px 0 1px black; } -.slider-container::v-deep .vue-slider-mark:first-child .vue-slider-mark-step, -.slider-container::v-deep .vue-slider-mark:last-child .vue-slider-mark-step { +.slider-container :deep(.vue-slider-mark:first-child .vue-slider-mark-step), +.slider-container :deep(.vue-slider-mark:last-child .vue-slider-mark-step) { display: block; } -.slider-container::v-deep .vue-slider-rail { +.slider-container :deep(.vue-slider-rail) { border: 1px solid #dedede; } -.slider-container::v-deep .vue-slider-process { +.slider-container :deep(.vue-slider-process) { border-radius: 0; box-shadow: inset 0px 2px 2px #ffffff80, inset 0px -2px 2px #0000002e; } -.slider-container::v-deep .vue-slider-process:first-child { +.slider-container :deep(.vue-slider-process:first-child) { border-top-left-radius: 15px; border-bottom-left-radius: 15px; } -.slider-container::v-deep .vue-slider-process:nth-last-child(3) { +.slider-container :deep(.vue-slider-process:nth-last-child(3)) { border-top-right-radius: 15px; border-bottom-right-radius: 15px; } @@ -247,20 +246,20 @@ button.pressed { } .slider-label-trim { - transform: scale(1, 0.75) translate(-50%, -9px); + transform: scale(1, 0.75) translate(-50%, -9px) !important;; } .slider-label-stop { font-size: 1.2rem; - transform: translate(-50%, 12px); + transform: translate(-50%, 12px) !important;; } .slider-label-jump { - transform: translate(-50%, -50px); + transform: translate(-50%, -50px) !important;; } .slider-label-color-change { - transform: translate(-50%, 10px); + transform: translate(-50%, 10px) !important;; } .current-stitch-input { @@ -286,23 +285,23 @@ button.pressed { /* we need ::v-deep here because the svg tag is added by svg.js and so Vue can't add the data-v-* attribute */ -div.simulator::v-deep svg.simulation { +div.simulator :deep(svg.simulation) { flex-grow: 1; flex-shrink: 1; order: -2; margin-bottom: -48px; } -div.simulator::v-deep svg.simulation-scale { +div.simulator :deep(svg.simulation-scale) { height: 50px; order: -1; margin-left: 5px; } -div.simulator::v-deep .simulation-scale-label { +div.simulator :deep(.simulation-scale-label) { font-size: 14px; } -div.simulator::v-deep .cursor { +div.simulator :deep(.cursor) { /* not sure what to add here to make it more visible */ } diff --git a/electron/src/renderer/components/InstallPalettes.vue b/electron/src/renderer/components/InstallPalettes.vue deleted file mode 100644 index 3608f858..00000000 --- a/electron/src/renderer/components/InstallPalettes.vue +++ /dev/null @@ -1,123 +0,0 @@ -<!-- - - Authors: see git history - - Copyright (c) 2010 Authors - Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - ---> - -<template> - <v-dialog max-width="500px" value="true"> - <v-card v-if="step == 'pick'" key="pick" rounded="lg" :loading="installing" :disabled="installing"> - <v-card-title> - <translate> - Install Palettes - </translate> - </v-card-title> - <v-card-text class="text--primary"> - <translate>Ink/Stitch can install palettes for Inkscape matching the thread colors from popular machine embroidery thread manufacturers. - </translate> - </v-card-text> - <v-file-input class="mb-3 mx-3" webkitdirectory hide-details v-model="path" truncate-length="45" - :label="$gettext('Choose Inkscape directory')"> - </v-file-input> - <v-card-text> - <translate>If you are not sure which file path to choose, click on install directly. In most cases Ink/Stitch will guess the correct path. - </translate> - </v-card-text> - <v-card-actions> - <v-btn text color="primary" v-on:click="install"> - <v-icon>mdi-palette</v-icon> - <translate>Install</translate> - </v-btn> - <v-btn text color="primary" v-on:click="close"> - <translate>Cancel</translate> - </v-btn> - </v-card-actions> - </v-card> - <v-card v-if="step == 'done'" key="done"> - <v-card-title> - <translate> - Installation Completed - </translate> - </v-card-title> - <v-card-text class="text--primary"> - <translate> - Inkscape palettes have been installed. Please restart Inkscape to load the new palettes. - </translate> - </v-card-text> - <v-card-actions> - <v-btn text color="primary" v-on:click="close"> - Done - </v-btn> - </v-card-actions> - </v-card> - <v-card v-if="step == 'error'" key="error"> - <v-card-title> - <translate> - Installation Failed - </translate> - </v-card-title> - <v-card-text class="text--primary"> - <translate>Inkscape add-on installation failed</translate> - </v-card-text> - <v-card-text class="text--secondary"> - {{ error }} - </v-card-text> - <v-card-actions> - <v-btn text color="primary" v-on:click="retry"> - <translate>Try again</translate> - </v-btn> - <v-btn text color="primary" v-on:click="close"> - <translate>Cancel</translate> - </v-btn> - </v-card-actions> - </v-card> - </v-dialog> -</template> - -<script> -const inkStitch = require("../../lib/api") - -export default { - name: "InstallPalettes", - data: function () { - return { - path: null, - installing: false, - step: "pick", - error: null - } - }, - methods: { - install() { - this.installing = true - inkStitch.post('install/palettes', {path: this.path.path || this.path.name}).then(response => { - this.step = "done" - }).catch(error => { - this.step = "error" - this.error = error.response.data.error - }).then(() => { - this.installing = false - }) - }, - close() { - window.close() - }, - retry() { - this.installing = false - this.step = "pick" - } - }, - created: function () { - inkStitch.get("install/default-path").then(response => { - this.path = new File([""], response.data, {}) - }) - } -} -</script> - -<style scoped> - -</style> diff --git a/electron/src/renderer/components/NotFound.vue b/electron/src/renderer/components/NotFound.vue new file mode 100644 index 00000000..4accf901 --- /dev/null +++ b/electron/src/renderer/components/NotFound.vue @@ -0,0 +1,12 @@ +<!-- + + Authors: see git history + + Copyright (c) 2010 Authors + Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +--> + +<template> + <h1>Oops, it looks like the page you're looking for doesn't exist.</h1> +</template> diff --git a/electron/src/renderer/components/Preferences.vue b/electron/src/renderer/components/Preferences.vue index f68c942d..101f1b8a 100644 --- a/electron/src/renderer/components/Preferences.vue +++ b/electron/src/renderer/components/Preferences.vue @@ -1,13 +1,22 @@ +<!-- + + Authors: see git history + + Copyright (c) 2010 Authors + Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. + +--> + <template> - <v-card raised rounded="lg" class="preferences-card"> + <v-card elevation="8" rounded="lg" class="preferences-card"> <v-card-title class="text-center justify-center py-6"> - <h1 class="font-weight-bold text-h2 basil--text"> + <h1 class="font-weight-bold text-h2 text-basil"> Ink/Stitch Settings </h1> </v-card-title> <v-card-text> - <v-tabs v-model="tab" background-color="transparent" grow> + <v-tabs v-model="tab" bg-color="transparent" class="text-primary" grow> <v-tab key="this_svg_settings"> This SVG </v-tab> @@ -16,16 +25,16 @@ </v-tab> </v-tabs> - <v-tabs-items v-model="tab"> - <v-tab-item key="this_svg_settings"> + <v-window v-model="tab"> + <v-window-item key="this_svg_settings"> <v-card flat> <v-card-text> <table> <tr> <td class="label"> <v-tooltip bottom> - <template v-slot:activator="{on, attrs}"> - <label for="collapse_len_mm" v-on="on" v-bind="attrs"><translate>Minimum jump stitch length</translate></label> + <template v-slot:activator="{ props }"> + <label for="collapse_len_mm" v-bind="props"><translate>Minimum jump stitch length</translate></label> </template> <label for="collapse_len_mm"><translate>Jump stitches smaller than this will be treated as normal stitches.</translate></label> </v-tooltip> @@ -45,8 +54,8 @@ <tr> <td class="label"> <v-tooltip bottom> - <template v-slot:activator="{on, attrs}"> - <label for="min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Minimum stitch length</translate></label> + <template v-slot:activator="{ props }"> + <label for="min_stitch_len_mm" v-bind="props"><translate>Minimum stitch length</translate></label> </template> <label for="min_stitch_len_mm"><translate>Drop stitches smaller than this value.</translate></label> </v-tooltip> @@ -66,16 +75,16 @@ </table> </v-card-text> </v-card> - </v-tab-item> - <v-tab-item key="global_settings"> + </v-window-item> + <v-window-item key="global_settings"> <v-card flat> <v-card-text> <table> <tr> <td> <v-tooltip bottom> - <template v-slot:activator="{on, attrs}"> - <label for="default_collapse_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum jump stitch length</translate></label> + <template v-slot:activator="{ props }"> + <label for="default_collapse_len_mm" v-bind="props"><translate>Default minimum jump stitch length</translate></label> </template> <label for="default_collapse_len_mm"><translate>Used for new SVGs.</translate></label> </v-tooltip> @@ -90,8 +99,8 @@ <tr> <td> <v-tooltip bottom> - <template v-slot:activator="{on, attrs}"> - <label for="default_min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum stitch length</translate></label> + <template v-slot:activator="{ props }"> + <label for="default_min_stitch_len_mm" v-bind="props"><translate>Default minimum stitch length</translate></label> </template> <label for="default_min_stitch_len_mm"><translate>Used for new SVGs.</translate></label> </v-tooltip> @@ -106,8 +115,8 @@ <tr> <td> <v-tooltip bottom> - <template v-slot:activator="{on, attrs}"> - <label for="cache_size" v-on="on" v-bind="attrs"><translate>Stitch plan cache size</translate></label> + <template v-slot:activator="{ props }"> + <label for="cache_size" v-bind="props"><translate>Stitch plan cache size</translate></label> </template> <label for="default_min_stitch_len_mm"><translate>The greater the number, the more stitch plans can be cached, speeding up stitch plan calculation. Default: 100</translate></label> </v-tooltip> @@ -125,8 +134,8 @@ </table> </v-card-text> </v-card> - </v-tab-item> - </v-tabs-items> + </v-window-item> + </v-window> </v-card-text> <v-card-actions> <v-btn text color="primary" @click="close"><translate>done</translate></v-btn> @@ -136,8 +145,7 @@ </template> <script> -const inkStitch = require("../../lib/api") - +import { inkStitch } from '../../lib/api.js' export default { name: "Preferences", data: function () { @@ -202,10 +210,11 @@ td.label { td.preference { padding-right: 4px; padding-left: 16px; - max-width: 100px; + max-width: 15em; + min-width: 8em; } -td.preference::v-deep input { +td.preference :deep(input) { text-align: right; } diff --git a/electron/src/renderer/components/Simulator.vue b/electron/src/renderer/components/Simulator.vue index bbcb5138..6d76b133 100644 --- a/electron/src/renderer/components/Simulator.vue +++ b/electron/src/renderer/components/Simulator.vue @@ -13,7 +13,7 @@ <div class="window-controls"> <div ref="controlInfoButton" class="control-info-button" v-on:click="toggleInfo"> <font-awesome-icon icon="info"/> - <collapse-transition> + <Transition name="collapse"> <div class="control-info" v-show="infoExpanded" v-bind:style="{'max-height': infoMaxHeight + 'px'}"> <h1> <font-awesome-icon icon="info" class="info-icon"/> @@ -163,14 +163,14 @@ </p> </div> </div> - </collapse-transition> + </Transition> </div> <div class="toggle-controls" v-on:click="toggleControls"> <font-awesome-icon v-if="controlsExpanded" icon="minus"/> <font-awesome-icon v-else icon="plus"/> </div> </div> - <collapse-transition> + <Transition name="collapse"> <div class="panel" v-show="controlsExpanded"> <fieldset class="controls"> <legend> @@ -203,7 +203,7 @@ </fieldset> <fieldset class="speed"> <legend> - <translate :translate-n="speed" translate-plural="Speed: %{speed} stitches/sec">Speed: %{speed} stitch/sec</translate> + <translate :translate-params="{ speed: speed }" :translate-n="speed" translate-plural="Speed: %{speed} stitches/sec">Speed: %{speed} stitch/sec</translate> </legend> <button v-on:click="animationSlowDown" :title="$gettext('Slow down (arrow down)')"> <font-awesome-icon icon="hippo" size="2x" class="fa-button"/> @@ -248,7 +248,7 @@ <input id="stop-checkbox" type="checkbox" v-model="showStops"/> <label for="stop-checkbox"><font-awesome-icon icon="pause"/> <translate>stops</translate></label> </span> - <span> + <span class="npp"> <input id="npp-checkbox" type="checkbox" v-model="showNeedlePenetrationPoints"/> <label for="npp-checkbox"> <font-awesome-layers> @@ -270,12 +270,11 @@ </span> </fieldset> </div> - </collapse-transition> + </Transition> <div class="slider-container"> <span>1</span> <span class="slider-box"> - <vue-slider - :value="currentStitchDisplay" + <vue-slider v-model="currentStitchDisplay" @change="setCurrentStitch" :min="0" :max="numStitches" @@ -297,7 +296,7 @@ @focus="stop"/> </div> </fieldset> - <loading :active.sync="loading" :is-full-page="false"> + <loading :active="loading" :is-full-page="false"> <div class="loading"> <div class="loading-icon"> <font-awesome-icon icon="spinner" size="4x" pulse/> diff --git a/electron/src/renderer/main.js b/electron/src/renderer/main.js index ea422538..3fcd1afc 100644 --- a/electron/src/renderer/main.js +++ b/electron/src/renderer/main.js @@ -7,111 +7,68 @@ */ // ES6 -import Vue from 'vue' -import axios from 'axios' - -import App from './App' +import { createApp } from 'vue' +import App from './App.vue' import router from './router' - -import {library} from '@fortawesome/fontawesome-svg-core' -import { - faAlignRight, - faAngleDoubleLeft, - faAngleDoubleRight, - faAngleRight, - faCircle, - faCut, - faExchangeAlt, - faEye, - faFrog, - faLink, - faHippo, - faHorse, - faInfo, - faMinus, - faPalette, - faPause, - faPlay, - faPlus, - faShoePrints, - faSpinner, - faStepBackward, - faStepForward, - faStop, - faSearchPlus, - faSearchMinus -} from '@fortawesome/free-solid-svg-icons' -import {FontAwesomeIcon, FontAwesomeLayers} from '@fortawesome/vue-fontawesome' -import Transitions from 'vue2-transitions' -import GetTextPlugin from 'vue-gettext' +import { library } from '@fortawesome/fontawesome-svg-core' +import { fas } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome' +import { createGettext } from 'vue3-gettext' import translations from './assets/translations.json' -import {selectLanguage} from '../lib/i18n' -import Vuetify from 'vuetify' -import 'vuetify/dist/vuetify.min.css' -import '@mdi/font/css/materialdesignicons.css' +import { selectLanguage } from '../lib/i18n.js' -// We have to add to the library every icon we use anywhere in the UI. -// This avoids the need to bundle the entire font-awesome icon set with -// Ink/Stitch. -library.add( - faAlignRight, - faAngleDoubleLeft, - faAngleDoubleRight, - faAngleRight, - faCircle, - faCut, - faExchangeAlt, - faEye, - faFrog, - faLink, - faHippo, - faHorse, - faInfo, - faMinus, - faPalette, - faPause, - faPlay, - faPlus, - faShoePrints, - faSpinner, - faStepBackward, - faStepForward, - faStop, - faSearchPlus, - faSearchMinus -) +import flaskserverport from '../lib/flaskserverport.json' -Vue.component('font-awesome-icon', FontAwesomeIcon) -Vue.component('font-awesome-layers', FontAwesomeLayers) +import { createVuetify, ThemeDefinition } from 'vuetify' +import * as components from 'vuetify/components' +import * as directives from 'vuetify/directives' +import 'vuetify/styles' -Vue.use(Transitions) -Vue.use(GetTextPlugin, { - translations: translations, - defaultLanguage: selectLanguage(translations), - silent: true -}) +import VueMousetrapPlugin from 'vue-mousetrap' -Vue.http = Vue.prototype.$http = axios -Vue.config.productionTip = false +if (flaskserverport.port === undefined) { + var theflaskport = window.inkstitchAPI.flaskport() + console.log("Installed mode") + console.log(theflaskport) +} else { + var theflaskport = flaskserverport.port + console.log("Dev mode") + console.log(theflaskport) +} -Vue.use(Vuetify) -const vuetify = new Vuetify({ +const inkStitchTheme = { + dark: false, + colors: { + primary: '#003399', + secondary: '#000000', + accent: '#8c9eff', + error: '#b71c1c', + } +} +const vuetify = new createVuetify({ + components, + directives, + ssr: true, theme: { + defaultTheme: 'inkStitchTheme', themes: { - light: { - primary: '#003399', - secondary: '#000000', - accent: '#8c9eff', - error: '#b71c1c', - }, - }, - }, + inkStitchTheme, + } + } }) -/* eslint-disable no-new */ -new Vue({ - vuetify, - components: {App}, - router, - template: '<App/>' -}).$mount('#app') +library.add(fas) +const app = createApp(App) +app.component('font-awesome-icon', FontAwesomeIcon) +app.component('font-awesome-layers', FontAwesomeLayers) + +app.use(createGettext({ + defaultLanguage: selectLanguage(translations, theflaskport), + translations: translations, + silent: true, + setGlobalProperties: true, +})) +app.use(VueMousetrapPlugin) +app.use(vuetify) +app.use(router) +app.mount('#app') diff --git a/electron/src/renderer/router/index.js b/electron/src/renderer/router/index.js index 1200fa0e..e90a8fd5 100644 --- a/electron/src/renderer/router/index.js +++ b/electron/src/renderer/router/index.js @@ -5,32 +5,32 @@ * Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. * */ - -import Vue from 'vue' -import Router from 'vue-router' - -Vue.use(Router) - -export default new Router({ - routes: [ +import { createWebHashHistory, createRouter } from 'vue-router' +const routes = [ { - path: '/simulator', - name: 'simulator', - component: require('@/components/Simulator').default + path: '/simulator', + name: 'simulator', + component: () => import('../components/Simulator.vue') }, { - path: '/install', - name: 'install', - component: require('@/components/InstallPalettes').default + path: '/preferences', + name: 'preferences', + component: () => import('../components/Preferences.vue') }, { - path: '/preferences', - name: 'preferences', - component: require('@/components/Preferences').default + path: '/:pathMatch(.*)*', + name: 'NotFound', + component: () => import('../components/NotFound.vue') }, - { - path: '*', - redirect: '/' - } - ] +] +const router = createRouter({ + history: createWebHashHistory(), + routes +}) +// Sets title for each routes +const DEFAULT_TITLE = 'Ink/Stitch'; + +router.beforeEach((to) => { + document.title = to.meta.title || DEFAULT_TITLE }) +export default router |
