kopia lustrzana https://github.com/inkstitch/inkstitch
Update electron version to v14.2.9 (#2214)
Authored-by: rejbasket Co-authored-by: Kaalleen Co-authored-by: Lex Nevapull/2316/head
rodzic
da54f104e6
commit
ef6f6580df
|
@ -182,8 +182,8 @@ jobs:
|
||||||
echo "${{ env.pythonLocation }}/bin" >> $GITHUB_PATH
|
echo "${{ env.pythonLocation }}/bin" >> $GITHUB_PATH
|
||||||
- shell: bash
|
- shell: bash
|
||||||
run: |
|
run: |
|
||||||
# disable electron-builder signing
|
# disable electron-builder signing and make dist
|
||||||
#export CSC_IDENTITY_AUTO_DISCOVERY=false
|
export CSC_IDENTITY_AUTO_DISCOVERY=false
|
||||||
make dist
|
make dist
|
||||||
env:
|
env:
|
||||||
BUILD: osx
|
BUILD: osx
|
||||||
|
|
|
@ -24,3 +24,5 @@ locales/
|
||||||
/profile_stats.prof
|
/profile_stats.prof
|
||||||
/.vscode
|
/.vscode
|
||||||
__pycache__
|
__pycache__
|
||||||
|
flaskserverport.json
|
||||||
|
electron/yarn.lock
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -1,10 +1,19 @@
|
||||||
|
# used for distlocal
|
||||||
|
OS=$(shell uname)
|
||||||
|
|
||||||
dist: version locales inx
|
dist: version locales inx
|
||||||
|
python bin/generate-flaskserverport-file
|
||||||
bash bin/build-python
|
bash bin/build-python
|
||||||
bash bin/build-electron
|
bash bin/build-electron
|
||||||
bash bin/build-distribution-archives
|
bash bin/build-distribution-archives
|
||||||
|
|
||||||
distclean:
|
distclean:
|
||||||
rm -rf build dist inx locales artifacts win mac *.spec *.tar.gz *.zip electron/node_modules electron/dist
|
rm -rf build dist inx locales artifacts win mac *.spec *.tar.gz *.zip electron/node_modules electron/dist electron/build/mac electron/build/mac-arm64 electron/build/win-ia32-unpacked electron/build/linux-unpacked electron/build/linux-arm64-unpacked electron/src/lib/flaskserverport.json
|
||||||
|
|
||||||
|
distlocal:
|
||||||
|
@case ${OS} in "Darwin") export BUILD=osx ;; "Linux")export BUILD=linux ;; *) export BUILD=windows ;; esac; export VERSION=local-build; make distclean && make dist;
|
||||||
|
manual:
|
||||||
|
make inx && cd electron && yarn install && cd ..
|
||||||
|
|
||||||
.PHONY: inx
|
.PHONY: inx
|
||||||
inx: version locales
|
inx: version locales
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
VERSION="$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')"
|
VERSION="${VERSION:-$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')}"
|
||||||
OS="${BUILD:-$(uname)}"
|
OS="${BUILD:-$(uname)}"
|
||||||
ARCH="$(uname -m)"
|
ARCH="$(uname -m)"
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
@ -6,7 +6,7 @@ mkdir artifacts
|
||||||
if [ "$BUILD" = "osx" ]; then
|
if [ "$BUILD" = "osx" ]; then
|
||||||
cp -a icons locales print LICENSE VERSION images/examples palettes symbols fonts tiles dbus inx dist/inkstitch.app/Contents/Resources
|
cp -a icons locales print LICENSE VERSION images/examples palettes symbols fonts tiles dbus inx dist/inkstitch.app/Contents/Resources
|
||||||
# adding version to Info.plist
|
# adding version to Info.plist
|
||||||
sed -i '' 's/0.0.0/'${VERSION}'/' dist/inkstitch.app/Contents/Info.plist
|
plutil -replace CFBundleShortVersionString -string ${VERSION} dist/inkstitch.app/Contents/Info.plist
|
||||||
rm -rf dist/inkstitch/
|
rm -rf dist/inkstitch/
|
||||||
# Install location for pkgbuild
|
# Install location for pkgbuild
|
||||||
PKG_INSTALL_PATH="/tmp/inkstitch/"
|
PKG_INSTALL_PATH="/tmp/inkstitch/"
|
||||||
|
|
|
@ -2,15 +2,6 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
ARCH="$(uname -m)"
|
|
||||||
# Check for cpu arch to build mac and linux electron arch
|
|
||||||
if [[ "$ARCH" = "arm64" ]] || [[ "$ARCH" = "aarch64" ]]; then
|
|
||||||
echo "Found ARM"
|
|
||||||
sed -i'' -e 's/CPU_ARCH/'arm64'/' electron/package.json
|
|
||||||
else
|
|
||||||
echo "Found x64"
|
|
||||||
sed -i'' -e 's/CPU_ARCH/'x64'/' electron/package.json
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$BUILD" = "windows" ]; then
|
if [ "$BUILD" = "windows" ]; then
|
||||||
args="-w --ia32"
|
args="-w --ia32"
|
||||||
|
|
|
@ -2,26 +2,6 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
info_year=$( date "+%Y" )
|
info_year=$( date "+%Y" )
|
||||||
site_packages="$(python -c "import os; print(os.path.dirname(os.__file__) + '/site-packages')")"
|
|
||||||
arch=$(uname -m)
|
|
||||||
if [ "$BUILD" = "linux" ]; then
|
|
||||||
pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/gio/modules/libgiolibproxy.so:. "
|
|
||||||
pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/libproxy.so.1:. "
|
|
||||||
pyinstaller_args+="--add-binary /lib/"$arch"-linux-gnu/libnsl.so.1:. "
|
|
||||||
pyinstaller_args+="--add-binary /usr/lib/"$arch"-linux-gnu/libxcb.so.1:. "
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This one's tricky. ink/stitch doesn't actually _use_ gi.repository.Gtk,
|
|
||||||
# but it does use GTK (through wxPython). pyinstaller has some special
|
|
||||||
# logic to handle GTK apps that is engaged when you import
|
|
||||||
# gi.repository.Gtk that pulls in things like themes, icons, etc. Without
|
|
||||||
# that, the Params dialog is unthemed and barely usable. This hidden
|
|
||||||
# import option is actually the only reason we had to install python-gi
|
|
||||||
# above!
|
|
||||||
pyinstaller_args+="--hidden-import gi.repository.Gtk "
|
|
||||||
|
|
||||||
# mac and windows build seem to miss wx import
|
|
||||||
pyinstaller_args+="--hidden-import wx "
|
|
||||||
|
|
||||||
# We need to use the precompiled bootloader linked with graphical Mac OS X
|
# We need to use the precompiled bootloader linked with graphical Mac OS X
|
||||||
# libraries if we develop a GUI application for Mac:
|
# libraries if we develop a GUI application for Mac:
|
||||||
|
@ -29,9 +9,6 @@ if [ "$BUILD" = "osx" -o "$BUILD" = "windows" ]; then
|
||||||
pyinstaller_args+="--windowed "
|
pyinstaller_args+="--windowed "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# This lets pyinstaller see inkex.py, etc.
|
|
||||||
pyinstaller_args+="-p inkscape/share/extensions "
|
|
||||||
|
|
||||||
# output useful debugging info that helps us trace library dependency issues
|
# output useful debugging info that helps us trace library dependency issues
|
||||||
pyinstaller_args+="--log-level DEBUG "
|
pyinstaller_args+="--log-level DEBUG "
|
||||||
|
|
||||||
|
@ -67,7 +44,7 @@ if [ "$BUILD" = "windows" ]; then
|
||||||
pyinstaller_args+="--version-file installer_scripts/file_version_info.txt "
|
pyinstaller_args+="--version-file installer_scripts/file_version_info.txt "
|
||||||
python -m PyInstaller $pyinstaller_args inkstitch.py
|
python -m PyInstaller $pyinstaller_args inkstitch.py
|
||||||
else
|
else
|
||||||
LD_LIBRARY_PATH="${site_packages}/wx" python -m PyInstaller $pyinstaller_args --strip inkstitch.py;
|
python -m PyInstaller $pyinstaller_args --strip inkstitch.py;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# pyinstaller put a whole mess of libraries under dist/inkstitch. We'd like
|
# pyinstaller put a whole mess of libraries under dist/inkstitch. We'd like
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
VERSION="$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')"
|
VERSION="${VERSION:-$(echo ${GITHUB_REF} | sed -e 's|refs/heads/||' -e 's|refs/tags/||' -e 's|/|-|g')}"
|
||||||
OS="${BUILD:-$(uname)}"
|
OS="${BUILD:-$(uname)}"
|
||||||
# Create windows installer
|
# Create windows installer
|
||||||
mkdir win
|
mkdir win
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
from json import dump
|
||||||
|
from os.path import dirname
|
||||||
|
|
||||||
|
path = os.path.join(dirname(dirname(__file__)), 'electron', 'src', 'lib', 'flaskserverport.json')
|
||||||
|
|
||||||
|
data = {"_comment1" : "port should not be declared when commiting"}
|
||||||
|
# write data to font.json into the same directory as the font file
|
||||||
|
with open(path, 'w', encoding="utf8") as output:
|
||||||
|
dump(data, output, indent=4, ensure_ascii=False)
|
|
@ -1,46 +0,0 @@
|
||||||
#!/bin/sh -u
|
|
||||||
# source of this code: https://github.com/rednoah/notarize-app
|
|
||||||
ASC_PROVIDER="$1"
|
|
||||||
ASC_USERNAME="$2"
|
|
||||||
ASC_PASSWORD="$3"
|
|
||||||
|
|
||||||
BUNDLE_ID="$4"
|
|
||||||
BUNDLE_PKG="$5"
|
|
||||||
|
|
||||||
|
|
||||||
# create temporary files
|
|
||||||
NOTARIZE_APP_LOG=$(mktemp -t notarize-app)
|
|
||||||
NOTARIZE_INFO_LOG=$(mktemp -t notarize-info)
|
|
||||||
|
|
||||||
# delete temporary files on exit
|
|
||||||
function finish {
|
|
||||||
rm "$NOTARIZE_APP_LOG" "$NOTARIZE_INFO_LOG"
|
|
||||||
}
|
|
||||||
trap finish EXIT
|
|
||||||
|
|
||||||
|
|
||||||
# submit app for notarization
|
|
||||||
if xcrun altool --notarize-app --primary-bundle-id "$BUNDLE_ID" --asc-provider "$ASC_PROVIDER" --username "$ASC_USERNAME" --password "$ASC_PASSWORD" -f "$BUNDLE_PKG" > "$NOTARIZE_APP_LOG" 2>&1; then
|
|
||||||
cat "$NOTARIZE_APP_LOG"
|
|
||||||
RequestUUID=$(awk -F ' = ' '/RequestUUID/ {print $2}' "$NOTARIZE_APP_LOG")
|
|
||||||
|
|
||||||
# check status periodically
|
|
||||||
while sleep 60 && date; do
|
|
||||||
# check notarization status
|
|
||||||
if xcrun altool --notarization-info "$RequestUUID" --asc-provider "$ASC_PROVIDER" --username "$ASC_USERNAME" --password "$ASC_PASSWORD" > "$NOTARIZE_INFO_LOG" 2>&1; then
|
|
||||||
cat "$NOTARIZE_INFO_LOG"
|
|
||||||
|
|
||||||
# once notarization is complete, run stapler and exit
|
|
||||||
if ! grep -q "Status: in progress" "$NOTARIZE_INFO_LOG"; then
|
|
||||||
xcrun stapler staple "$BUNDLE_PKG"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
cat "$NOTARIZE_INFO_LOG" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
cat "$NOTARIZE_APP_LOG" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"comments": false,
|
|
||||||
"env": {
|
|
||||||
"main": {
|
|
||||||
"presets": [
|
|
||||||
["env", {
|
|
||||||
"targets": { "node": 7 }
|
|
||||||
}],
|
|
||||||
"stage-0"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"renderer": {
|
|
||||||
"presets": [
|
|
||||||
["env", {
|
|
||||||
"modules": false
|
|
||||||
}],
|
|
||||||
"stage-0"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"web": {
|
|
||||||
"presets": [
|
|
||||||
["env", {
|
|
||||||
"modules": false
|
|
||||||
}],
|
|
||||||
"stage-0"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"plugins": ["transform-runtime"]
|
|
||||||
}
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# https://github.com/browserslist/browserslist#queries
|
||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
|
not dead
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"development": {
|
|
||||||
"application/javascript": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"electron": "4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"transform-async-to-generator"
|
|
||||||
],
|
|
||||||
"sourceMaps": "inline"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"production": {
|
|
||||||
"application/javascript": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"electron": "4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"transform-async-to-generator"
|
|
||||||
],
|
|
||||||
"sourceMaps": "none"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
process.env.NODE_ENV = 'production'
|
|
||||||
|
|
||||||
const { say } = require('cfonts')
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const del = require('del')
|
|
||||||
const { spawn } = require('child_process')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
const Multispinner = require('multispinner')
|
|
||||||
|
|
||||||
|
|
||||||
const mainConfig = require('./webpack.main.config')
|
|
||||||
const rendererConfig = require('./webpack.renderer.config')
|
|
||||||
const webConfig = require('./webpack.web.config')
|
|
||||||
|
|
||||||
const doneLog = chalk.bgGreen.white(' DONE ') + ' '
|
|
||||||
const errorLog = chalk.bgRed.white(' ERROR ') + ' '
|
|
||||||
const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
|
|
||||||
const isCI = process.env.CI || false
|
|
||||||
|
|
||||||
if (process.env.BUILD_TARGET === 'clean') clean()
|
|
||||||
else if (process.env.BUILD_TARGET === 'web') web()
|
|
||||||
else build()
|
|
||||||
|
|
||||||
function clean () {
|
|
||||||
del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
|
|
||||||
console.log(`\n${doneLog}\n`)
|
|
||||||
process.exit()
|
|
||||||
}
|
|
||||||
|
|
||||||
function build () {
|
|
||||||
greeting()
|
|
||||||
|
|
||||||
del.sync(['dist/electron/*', '!.gitkeep'])
|
|
||||||
|
|
||||||
const tasks = ['main', 'renderer']
|
|
||||||
const m = new Multispinner(tasks, {
|
|
||||||
preText: 'building',
|
|
||||||
postText: 'process'
|
|
||||||
})
|
|
||||||
|
|
||||||
let results = ''
|
|
||||||
|
|
||||||
m.on('success', () => {
|
|
||||||
process.stdout.write('\x1B[2J\x1B[0f')
|
|
||||||
console.log(`\n\n${results}`)
|
|
||||||
console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
|
|
||||||
process.exit()
|
|
||||||
})
|
|
||||||
|
|
||||||
pack(mainConfig).then(result => {
|
|
||||||
results += result + '\n\n'
|
|
||||||
m.success('main')
|
|
||||||
}).catch(err => {
|
|
||||||
m.error('main')
|
|
||||||
console.log(`\n ${errorLog}failed to build main process`)
|
|
||||||
console.error(`\n${err}\n`)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
pack(rendererConfig).then(result => {
|
|
||||||
results += result + '\n\n'
|
|
||||||
m.success('renderer')
|
|
||||||
}).catch(err => {
|
|
||||||
m.error('renderer')
|
|
||||||
console.log(`\n ${errorLog}failed to build renderer process`)
|
|
||||||
console.error(`\n${err}\n`)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function pack (config) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
config.mode = 'production'
|
|
||||||
webpack(config, (err, stats) => {
|
|
||||||
if (err) reject(err.stack || err)
|
|
||||||
else if (stats.hasErrors()) {
|
|
||||||
let err = ''
|
|
||||||
|
|
||||||
stats.toString({
|
|
||||||
chunks: false,
|
|
||||||
colors: true
|
|
||||||
})
|
|
||||||
.split(/\r?\n/)
|
|
||||||
.forEach(line => {
|
|
||||||
err += ` ${line}\n`
|
|
||||||
})
|
|
||||||
|
|
||||||
reject(err)
|
|
||||||
} else {
|
|
||||||
resolve(stats.toString({
|
|
||||||
chunks: false,
|
|
||||||
colors: true
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function web () {
|
|
||||||
del.sync(['dist/web/*', '!.gitkeep'])
|
|
||||||
webConfig.mode = 'production'
|
|
||||||
webpack(webConfig, (err, stats) => {
|
|
||||||
if (err || stats.hasErrors()) console.log(err)
|
|
||||||
|
|
||||||
console.log(stats.toString({
|
|
||||||
chunks: false,
|
|
||||||
colors: true
|
|
||||||
}))
|
|
||||||
|
|
||||||
process.exit()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function greeting () {
|
|
||||||
const cols = process.stdout.columns
|
|
||||||
let text = ''
|
|
||||||
|
|
||||||
if (cols > 85) text = 'lets-build'
|
|
||||||
else if (cols > 60) text = 'lets-|build'
|
|
||||||
else text = false
|
|
||||||
|
|
||||||
if (text && !isCI) {
|
|
||||||
say(text, {
|
|
||||||
colors: ['yellow'],
|
|
||||||
font: 'simple3d',
|
|
||||||
space: false
|
|
||||||
})
|
|
||||||
} else console.log(chalk.yellow.bold('\n lets-build'))
|
|
||||||
console.log()
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
|
|
||||||
|
|
||||||
hotClient.subscribe(event => {
|
|
||||||
/**
|
|
||||||
* Reload browser when HTMLWebpackPlugin emits a new index.html
|
|
||||||
*
|
|
||||||
* Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
|
|
||||||
* https://github.com/SimulatedGREG/electron-vue/issues/437
|
|
||||||
* https://github.com/jantimon/html-webpack-plugin/issues/680
|
|
||||||
*/
|
|
||||||
// if (event.action === 'reload') {
|
|
||||||
// window.location.reload()
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify `mainWindow` when `main` process is compiling,
|
|
||||||
* giving notice for an expected reload of the `electron` process
|
|
||||||
*/
|
|
||||||
if (event.action === 'compiling') {
|
|
||||||
document.body.innerHTML += `
|
|
||||||
<style>
|
|
||||||
#dev-client {
|
|
||||||
background: #4fc08d;
|
|
||||||
border-radius: 4px;
|
|
||||||
bottom: 20px;
|
|
||||||
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
|
|
||||||
color: #fff;
|
|
||||||
font-family: 'Source Sans Pro', sans-serif;
|
|
||||||
left: 20px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="dev-client">
|
|
||||||
Compiling Main Process...
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -1,192 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const electron = require('electron')
|
|
||||||
const path = require('path')
|
|
||||||
const { say } = require('cfonts')
|
|
||||||
const { spawn } = require('child_process')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
const WebpackDevServer = require('webpack-dev-server')
|
|
||||||
const webpackHotMiddleware = require('webpack-hot-middleware')
|
|
||||||
|
|
||||||
const mainConfig = require('./webpack.main.config')
|
|
||||||
const rendererConfig = require('./webpack.renderer.config')
|
|
||||||
|
|
||||||
let electronProcess = null
|
|
||||||
let manualRestart = false
|
|
||||||
let hotMiddleware
|
|
||||||
|
|
||||||
function logStats (proc, data) {
|
|
||||||
let log = ''
|
|
||||||
|
|
||||||
log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
|
|
||||||
log += '\n\n'
|
|
||||||
|
|
||||||
if (typeof data === 'object') {
|
|
||||||
data.toString({
|
|
||||||
colors: true,
|
|
||||||
chunks: false
|
|
||||||
}).split(/\r?\n/).forEach(line => {
|
|
||||||
log += ' ' + line + '\n'
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
log += ` ${data}\n`
|
|
||||||
}
|
|
||||||
|
|
||||||
log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
|
|
||||||
|
|
||||||
console.log(log)
|
|
||||||
}
|
|
||||||
|
|
||||||
function startRenderer () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
|
|
||||||
rendererConfig.mode = 'development'
|
|
||||||
const compiler = webpack(rendererConfig)
|
|
||||||
hotMiddleware = webpackHotMiddleware(compiler, {
|
|
||||||
log: false,
|
|
||||||
heartbeat: 2500
|
|
||||||
})
|
|
||||||
|
|
||||||
compiler.hooks.compilation.tap('compilation', compilation => {
|
|
||||||
compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
|
|
||||||
hotMiddleware.publish({ action: 'reload' })
|
|
||||||
cb()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
compiler.hooks.done.tap('done', stats => {
|
|
||||||
logStats('Renderer', stats)
|
|
||||||
})
|
|
||||||
|
|
||||||
const server = new WebpackDevServer(
|
|
||||||
compiler,
|
|
||||||
{
|
|
||||||
contentBase: path.join(__dirname, '../'),
|
|
||||||
quiet: true,
|
|
||||||
before (app, ctx) {
|
|
||||||
app.use(hotMiddleware)
|
|
||||||
ctx.middleware.waitUntilValid(() => {
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
server.listen(9080)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function startMain () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
|
|
||||||
mainConfig.mode = 'development'
|
|
||||||
const compiler = webpack(mainConfig)
|
|
||||||
|
|
||||||
compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
|
|
||||||
logStats('Main', chalk.white.bold('compiling...'))
|
|
||||||
hotMiddleware.publish({ action: 'compiling' })
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
compiler.watch({}, (err, stats) => {
|
|
||||||
if (err) {
|
|
||||||
console.log(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logStats('Main', stats)
|
|
||||||
|
|
||||||
if (electronProcess && electronProcess.kill) {
|
|
||||||
manualRestart = true
|
|
||||||
process.kill(electronProcess.pid)
|
|
||||||
electronProcess = null
|
|
||||||
startElectron()
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
manualRestart = false
|
|
||||||
}, 5000)
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function startElectron () {
|
|
||||||
process.argv.shift();
|
|
||||||
process.argv.shift();
|
|
||||||
var args = [
|
|
||||||
'--inspect=5858',
|
|
||||||
path.join(__dirname, '../dist/electron/main.js')
|
|
||||||
].concat(process.argv)
|
|
||||||
|
|
||||||
// detect yarn or npm and process commandline args accordingly
|
|
||||||
if (process.env.npm_execpath.endsWith('yarn.js')) {
|
|
||||||
args = args.concat(process.argv.slice(3))
|
|
||||||
} else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
|
|
||||||
args = args.concat(process.argv.slice(2))
|
|
||||||
}
|
|
||||||
|
|
||||||
electronProcess = spawn(electron, args)
|
|
||||||
|
|
||||||
electronProcess.stdout.on('data', data => {
|
|
||||||
electronLog(data, 'blue')
|
|
||||||
})
|
|
||||||
electronProcess.stderr.on('data', data => {
|
|
||||||
electronLog(data, 'red')
|
|
||||||
})
|
|
||||||
|
|
||||||
electronProcess.on('close', () => {
|
|
||||||
if (!manualRestart) process.exit()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function electronLog (data, color) {
|
|
||||||
let log = ''
|
|
||||||
data = data.toString().split(/\r?\n/)
|
|
||||||
data.forEach(line => {
|
|
||||||
log += ` ${line}\n`
|
|
||||||
})
|
|
||||||
if (/[0-9A-z]+/.test(log)) {
|
|
||||||
console.log(
|
|
||||||
chalk[color].bold('┏ Electron -------------------') +
|
|
||||||
'\n\n' +
|
|
||||||
log +
|
|
||||||
chalk[color].bold('┗ ----------------------------') +
|
|
||||||
'\n'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function greeting () {
|
|
||||||
const cols = process.stdout.columns
|
|
||||||
let text = ''
|
|
||||||
|
|
||||||
if (cols > 104) text = 'electron-vue'
|
|
||||||
else if (cols > 76) text = 'electron-|vue'
|
|
||||||
else text = false
|
|
||||||
|
|
||||||
if (text) {
|
|
||||||
say(text, {
|
|
||||||
colors: ['yellow'],
|
|
||||||
font: 'simple3d',
|
|
||||||
space: false
|
|
||||||
})
|
|
||||||
} else console.log(chalk.yellow.bold('\n electron-vue'))
|
|
||||||
console.log(chalk.blue(' getting ready...') + '\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
function init () {
|
|
||||||
greeting()
|
|
||||||
|
|
||||||
Promise.all([startRenderer(), startMain()])
|
|
||||||
.then(() => {
|
|
||||||
startElectron()
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
init()
|
|
|
@ -1,72 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
process.env.BABEL_ENV = 'main'
|
|
||||||
|
|
||||||
const path = require('path')
|
|
||||||
const { dependencies } = require('../package.json')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
|
|
||||||
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
|
||||||
|
|
||||||
let mainConfig = {
|
|
||||||
entry: {
|
|
||||||
main: path.join(__dirname, '../src/main/index.js')
|
|
||||||
},
|
|
||||||
externals: [
|
|
||||||
...Object.keys(dependencies || {})
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
use: 'babel-loader',
|
|
||||||
exclude: /node_modules/
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.node$/,
|
|
||||||
use: 'node-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
__dirname: process.env.NODE_ENV !== 'production',
|
|
||||||
__filename: process.env.NODE_ENV !== 'production'
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
libraryTarget: 'commonjs2',
|
|
||||||
path: path.join(__dirname, '../dist/electron')
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new webpack.NoEmitOnErrorsPlugin()
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.json', '.node']
|
|
||||||
},
|
|
||||||
target: 'electron-main'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust mainConfig for development settings
|
|
||||||
*/
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
|
||||||
mainConfig.plugins.push(
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust mainConfig for production settings
|
|
||||||
*/
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
mainConfig.plugins.push(
|
|
||||||
new BabiliWebpackPlugin(),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': '"production"'
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = mainConfig
|
|
|
@ -1,202 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
process.env.BABEL_ENV = 'renderer'
|
|
||||||
|
|
||||||
const path = require('path')
|
|
||||||
const { dependencies } = require('../package.json')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
|
|
||||||
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
const { VueLoaderPlugin } = require('vue-loader')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of node_modules to include in webpack bundle
|
|
||||||
*
|
|
||||||
* Required for specific packages like Vue UI libraries
|
|
||||||
* that provide pure *.vue files that need compiling
|
|
||||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
|
|
||||||
*/
|
|
||||||
// 'vue-slider-component' needed here due to this issue:
|
|
||||||
// https://github.com/SimulatedGREG/electron-vue/issues/725
|
|
||||||
let whiteListedModules = ['vue', 'vue-slider-component', 'vuetify']
|
|
||||||
|
|
||||||
let rendererConfig = {
|
|
||||||
devtool: '#cheap-module-eval-source-map',
|
|
||||||
entry: {
|
|
||||||
renderer: path.join(__dirname, '../src/renderer/main.js')
|
|
||||||
},
|
|
||||||
externals: [
|
|
||||||
...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.less$/,
|
|
||||||
use: ['vue-style-loader', 'css-loader', 'less-loader']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['vue-style-loader', 'css-loader']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
use: 'vue-html-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
use: 'babel-loader',
|
|
||||||
exclude: /node_modules/
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.node$/,
|
|
||||||
use: 'node-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.vue$/,
|
|
||||||
use: {
|
|
||||||
loader: 'vue-loader',
|
|
||||||
options: {
|
|
||||||
extractCSS: process.env.NODE_ENV === 'production',
|
|
||||||
loaders: {
|
|
||||||
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
|
|
||||||
scss: 'vue-style-loader!css-loader!sass-loader',
|
|
||||||
less: 'vue-style-loader!css-loader!less-loader'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
|
||||||
use: {
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: 'imgs/[name]--[folder].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 10000,
|
|
||||||
name: 'media/[name]--[folder].[ext]'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
|
||||||
use: {
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: 'fonts/[name]--[folder].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.s(c|a)ss$/,
|
|
||||||
use: [
|
|
||||||
'vue-style-loader',
|
|
||||||
'css-loader',
|
|
||||||
{
|
|
||||||
loader: 'sass-loader',
|
|
||||||
// Requires sass-loader@^8.0.0
|
|
||||||
options: {
|
|
||||||
implementation: require('sass'),
|
|
||||||
sassOptions: {
|
|
||||||
indentedSyntax: true // optional
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
__dirname: process.env.NODE_ENV !== 'production',
|
|
||||||
__filename: process.env.NODE_ENV !== 'production'
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new VueLoaderPlugin(),
|
|
||||||
new MiniCssExtractPlugin({filename: 'styles.css'}),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
filename: 'index.html',
|
|
||||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
|
||||||
templateParameters(compilation, assets, options) {
|
|
||||||
return {
|
|
||||||
compilation: compilation,
|
|
||||||
webpack: compilation.getStats().toJson(),
|
|
||||||
webpackConfig: compilation.options,
|
|
||||||
htmlWebpackPlugin: {
|
|
||||||
files: assets,
|
|
||||||
options: options
|
|
||||||
},
|
|
||||||
process
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minify: {
|
|
||||||
collapseWhitespace: true,
|
|
||||||
removeAttributeQuotes: true,
|
|
||||||
removeComments: true
|
|
||||||
},
|
|
||||||
nodeModules: process.env.NODE_ENV !== 'production'
|
|
||||||
? path.resolve(__dirname, '../node_modules')
|
|
||||||
: false
|
|
||||||
}),
|
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
|
||||||
new webpack.NoEmitOnErrorsPlugin()
|
|
||||||
],
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
libraryTarget: 'commonjs2',
|
|
||||||
path: path.join(__dirname, '../dist/electron')
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': path.join(__dirname, '../src/renderer'),
|
|
||||||
'vue$': 'vue/dist/vue.esm.js'
|
|
||||||
},
|
|
||||||
extensions: ['.js', '.vue', '.json', '.css', '.node']
|
|
||||||
},
|
|
||||||
target: 'electron-renderer'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust rendererConfig for development settings
|
|
||||||
*/
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
|
||||||
rendererConfig.plugins.push(
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust rendererConfig for production settings
|
|
||||||
*/
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
rendererConfig.devtool = ''
|
|
||||||
|
|
||||||
rendererConfig.plugins.push(
|
|
||||||
new BabiliWebpackPlugin(),
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{
|
|
||||||
from: path.join(__dirname, '../static'),
|
|
||||||
to: path.join(__dirname, '../dist/electron/static'),
|
|
||||||
ignore: ['.*']
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': '"production"'
|
|
||||||
}),
|
|
||||||
new webpack.LoaderOptionsPlugin({
|
|
||||||
minimize: true
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = rendererConfig
|
|
|
@ -1,161 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
process.env.BABEL_ENV = 'web'
|
|
||||||
|
|
||||||
const path = require('path')
|
|
||||||
const webpack = require('webpack')
|
|
||||||
|
|
||||||
const BabiliWebpackPlugin = require('babili-webpack-plugin')
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
||||||
const { VueLoaderPlugin } = require('vue-loader')
|
|
||||||
|
|
||||||
let webConfig = {
|
|
||||||
devtool: '#cheap-module-eval-source-map',
|
|
||||||
entry: {
|
|
||||||
web: path.join(__dirname, '../src/renderer/main.js')
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.less$/,
|
|
||||||
use: ['vue-style-loader', 'css-loader', 'less-loader']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['vue-style-loader', 'css-loader']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
use: 'vue-html-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
use: 'babel-loader',
|
|
||||||
include: [ path.resolve(__dirname, '../src/renderer') ],
|
|
||||||
exclude: /node_modules/
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.vue$/,
|
|
||||||
use: {
|
|
||||||
loader: 'vue-loader',
|
|
||||||
options: {
|
|
||||||
extractCSS: true,
|
|
||||||
loaders: {
|
|
||||||
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
|
|
||||||
scss: 'vue-style-loader!css-loader!sass-loader',
|
|
||||||
less: 'vue-style-loader!css-loader!less-loader'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
|
||||||
use: {
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: 'imgs/[name].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
|
||||||
use: {
|
|
||||||
loader: 'url-loader',
|
|
||||||
query: {
|
|
||||||
limit: 10000,
|
|
||||||
name: 'fonts/[name].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.s(c|a)ss$/,
|
|
||||||
use: [
|
|
||||||
'vue-style-loader',
|
|
||||||
'css-loader',
|
|
||||||
{
|
|
||||||
loader: 'sass-loader',
|
|
||||||
// Requires sass-loader@^8.0.0
|
|
||||||
options: {
|
|
||||||
implementation: require('sass'),
|
|
||||||
sassOptions: {
|
|
||||||
indentedSyntax: true // optional
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new VueLoaderPlugin(),
|
|
||||||
new MiniCssExtractPlugin({filename: 'styles.css'}),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
filename: 'index.html',
|
|
||||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
|
||||||
templateParameters(compilation, assets, options) {
|
|
||||||
return {
|
|
||||||
compilation: compilation,
|
|
||||||
webpack: compilation.getStats().toJson(),
|
|
||||||
webpackConfig: compilation.options,
|
|
||||||
htmlWebpackPlugin: {
|
|
||||||
files: assets,
|
|
||||||
options: options
|
|
||||||
},
|
|
||||||
process
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minify: {
|
|
||||||
collapseWhitespace: true,
|
|
||||||
removeAttributeQuotes: true,
|
|
||||||
removeComments: true
|
|
||||||
},
|
|
||||||
nodeModules: false
|
|
||||||
}),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.IS_WEB': 'true'
|
|
||||||
}),
|
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
|
||||||
new webpack.NoEmitOnErrorsPlugin()
|
|
||||||
],
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
path: path.join(__dirname, '../dist/web')
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': path.join(__dirname, '../src/renderer'),
|
|
||||||
'vue$': 'vue/dist/vue.esm.js'
|
|
||||||
},
|
|
||||||
extensions: ['.js', '.vue', '.json', '.css']
|
|
||||||
},
|
|
||||||
target: 'web'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust webConfig for production settings
|
|
||||||
*/
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
webConfig.devtool = ''
|
|
||||||
|
|
||||||
webConfig.plugins.push(
|
|
||||||
new BabiliWebpackPlugin(),
|
|
||||||
new CopyWebpackPlugin([
|
|
||||||
{
|
|
||||||
from: path.join(__dirname, '../static'),
|
|
||||||
to: path.join(__dirname, '../dist/web/static'),
|
|
||||||
ignore: ['.*']
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': '"production"'
|
|
||||||
}),
|
|
||||||
new webpack.LoaderOptionsPlugin({
|
|
||||||
minimize: true
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = webConfig
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "eslint-config-airbnb",
|
|
||||||
"rules": {
|
|
||||||
"import/extensions": 0,
|
|
||||||
"import/no-extraneous-dependencies": 0,
|
|
||||||
"import/no-unresolved": [2, { "ignore": ["electron"] }],
|
|
||||||
"linebreak-style": 0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
parser: 'babel-eslint',
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true
|
|
||||||
},
|
|
||||||
extends: 'standard',
|
|
||||||
globals: {
|
|
||||||
__static: true
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
'html'
|
|
||||||
],
|
|
||||||
'rules': {
|
|
||||||
// allow paren-less arrow functions
|
|
||||||
'arrow-parens': 0,
|
|
||||||
// allow async-await
|
|
||||||
'generator-star-spacing': 0,
|
|
||||||
// allow debugger during development
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
* text=auto eol=lf
|
|
@ -0,0 +1,16 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
useBuiltIns: 'usage', // adds specific imports for polyfills when they are used in each file.
|
||||||
|
modules: false, // preserve ES modules.
|
||||||
|
corejs: { version: 3, proposals: true }, // enable polyfilling of every proposal supported by core-js.
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-transform-runtime', // enables the re-use of Babel's injected helper code to save on codesize.
|
||||||
|
],
|
||||||
|
exclude: [/core-js/],
|
||||||
|
}
|
|
@ -4,10 +4,12 @@
|
||||||
"version": "11.99.11",
|
"version": "11.99.11",
|
||||||
"description": "Ink/Stitch GUI",
|
"description": "Ink/Stitch GUI",
|
||||||
"main": "./dist/electron/main.js",
|
"main": "./dist/electron/main.js",
|
||||||
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pack": "electron-builder --dir",
|
"dev": "node service/commands/dev.js",
|
||||||
"dist": "node .electron-vue/build.js && electron-builder",
|
"just-build": "node service/commands/build.js && node service/commands/build-main.js",
|
||||||
"dev": "node --openssl-legacy-provider .electron-vue/dev-runner.js"
|
"dist": "yarn just-build && electron-builder",
|
||||||
|
"print": "yarn just-build && yarn dev"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"productName": "inkstitch-gui",
|
"productName": "inkstitch-gui",
|
||||||
|
@ -22,10 +24,7 @@
|
||||||
"icon": "build/icons",
|
"icon": "build/icons",
|
||||||
"target": [
|
"target": [
|
||||||
{
|
{
|
||||||
"target": "dir",
|
"target": "dir"
|
||||||
"arch": [
|
|
||||||
"CPU_ARCH"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -37,10 +36,7 @@
|
||||||
"icon": "build/icons/mac/inkstitch.icns",
|
"icon": "build/icons/mac/inkstitch.icns",
|
||||||
"target": [
|
"target": [
|
||||||
{
|
{
|
||||||
"target": "dir",
|
"target": "dir"
|
||||||
"arch": [
|
|
||||||
"CPU_ARCH"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hardenedRuntime": true,
|
"hardenedRuntime": true,
|
||||||
|
@ -54,78 +50,70 @@
|
||||||
"author": "lex",
|
"author": "lex",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.22",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.10.2",
|
"@babel/runtime": "^7.17.9",
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.6",
|
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||||
"@mdi/font": "^5.5.55",
|
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||||
"@svgdotjs/svg.filter.js": "^3.0.7",
|
"@fortawesome/vue-fontawesome": "^3.0.0-5",
|
||||||
"@svgdotjs/svg.js": "^3.0.16",
|
"@svgdotjs/svg.filter.js": "^3.0.8",
|
||||||
"@svgdotjs/svg.panzoom.js": "https://github.com/inkstitch/svg.panzoom.js",
|
"@svgdotjs/svg.js": "^3.1.2",
|
||||||
"axios": "^0.19.0",
|
"@svgdotjs/svg.panzoom.js": "^2.1.2",
|
||||||
"electron-compile": "^6.4.4",
|
"axios": "^0.27.2",
|
||||||
|
"core-js": "^3.22.2",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"mousetrap": "^1.6.3",
|
"node-polyfill-webpack-plugin": "^2.0.1",
|
||||||
"query-string": "^6.8.2",
|
"query-string": "^7.1.1",
|
||||||
"svgpath": "^2.2.3",
|
"svgpath": "^2.5.0",
|
||||||
"tmp": "0.1.0",
|
"vue": "^3.2.33",
|
||||||
"vue": "^2.5.16",
|
"vue-loading-overlay": "^5.0",
|
||||||
"vue-gettext": "^2.1.5",
|
"vue-mousetrap": "^1.0.5",
|
||||||
"vue-loading-overlay": "^3.2.0",
|
"vue-router": "4",
|
||||||
"vue-router": "^3.0.1",
|
"vue-slider-component": "^4.1.0-beta.0",
|
||||||
"vue-slider-component": "^3.0.38",
|
"vue3-gettext": "^2.2.3",
|
||||||
"vue2-transitions": "^0.3.0",
|
"vue3-transitions": "^1.0.0",
|
||||||
"vuetify": "^2.3.9"
|
"vuetify": "^3.1.7",
|
||||||
|
"webpack-plugin-vuetify": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ajv": "^6.5.0",
|
"@babel/core": "^7.17.9",
|
||||||
"babel-core": "^6.26.3",
|
"@babel/preset-env": "^7.16.11",
|
||||||
"babel-eslint": "^8.2.3",
|
"@types/webpack-env": "^1.16.4",
|
||||||
"babel-loader": "^7.1.4",
|
"@vue/compiler-sfc": "^3.2.33",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"autoprefixer": "^10.4.5",
|
||||||
"babel-preset-env": "^1.7.0",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-preset-stage-0": "^6.24.1",
|
"case-sensitive-paths-webpack-plugin": "^2.4.0",
|
||||||
"babel-register": "^6.26.0",
|
"chalk": "^4.1.2",
|
||||||
"babili-webpack-plugin": "^0.1.2",
|
"copy-webpack-plugin": "^10.2.4",
|
||||||
"cfonts": "^2.1.2",
|
"css-loader": "^6.7.1",
|
||||||
"chalk": "^2.4.1",
|
|
||||||
"copy-webpack-plugin": "^4.5.1",
|
|
||||||
"cross-env": "^5.1.6",
|
|
||||||
"css-loader": "^0.28.11",
|
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"del": "^3.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"devtron": "^1.4.0",
|
"dotenv-expand": "^8.0.3",
|
||||||
"easygettext": "^2.7.0",
|
"electron": "14.2.9",
|
||||||
"electron": "4.1.3",
|
|
||||||
"electron-builder": "^23.0.3",
|
"electron-builder": "^23.0.3",
|
||||||
"electron-debug": "^1.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"mini-css-extract-plugin": "^2.6.0",
|
||||||
"electron-prebuilt-compile": "4.0.0",
|
"ora": "^5.4.1",
|
||||||
"eslint": "^4.19.1",
|
"postcss": "^8.4.12",
|
||||||
"eslint-config-standard": "^11.0.0",
|
"postcss-html": "^1.4.1",
|
||||||
"eslint-friendly-formatter": "^4.0.1",
|
"postcss-loader": "^6.2.1",
|
||||||
"eslint-loader": "^2.0.0",
|
"rimraf": "^3.0.2",
|
||||||
"eslint-plugin-html": "^4.0.3",
|
"sass": "~1.32",
|
||||||
"eslint-plugin-import": "^2.12.0",
|
"sass-loader": "^13.0.0",
|
||||||
"eslint-plugin-node": "^6.0.1",
|
"strip-ansi": "^6.0.0",
|
||||||
"eslint-plugin-promise": "^3.8.0",
|
"style-loader": "^3.3.1",
|
||||||
"eslint-plugin-standard": "^3.1.0",
|
"terser-webpack-plugin": "^5.3.1",
|
||||||
"file-loader": "^1.1.11",
|
"thread-loader": "^3.0.4",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"ts-loader": "^9.2.8",
|
||||||
"mini-css-extract-plugin": "0.4.0",
|
"typescript": "^4.6.3",
|
||||||
"multispinner": "^0.2.1",
|
"url-loader": "^4.1.1",
|
||||||
"node-loader": "^0.6.0",
|
"vue-loader": "^17.0.0",
|
||||||
"sass": "^1.26.10",
|
"vue-style-loader": "^4.1.3",
|
||||||
"sass-loader": "^9.0.3",
|
"wait-on": "^6.0.1",
|
||||||
"style-loader": "^0.21.0",
|
"webpack": "^5.72.0",
|
||||||
"url-loader": "^1.0.1",
|
"webpack-dev-server": "^4.8.1",
|
||||||
"vue-html-loader": "^1.2.4",
|
"webpack-merge": "^5.8.0"
|
||||||
"vue-loader": "^15.2.4",
|
},
|
||||||
"vue-style-loader": "^4.1.0",
|
"engines": {
|
||||||
"vue-template-compiler": "^2.5.16",
|
"node": ">=12.13.0"
|
||||||
"webpack": "^4.15.1",
|
|
||||||
"webpack-cli": "^3.0.8",
|
|
||||||
"webpack-dev-server": "^3.1.4",
|
|
||||||
"webpack-hot-middleware": "^2.22.2",
|
|
||||||
"webpack-merge": "^4.1.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const loadEnv = require('../utils/loadEnv')
|
||||||
|
loadEnv()
|
||||||
|
loadEnv('production')
|
||||||
|
|
||||||
|
const rm = require('rimraf')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
|
||||||
|
const { error, done } = require('../utils/logger')
|
||||||
|
const { logWithSpinner, stopSpinner } = require('../utils/spinner')
|
||||||
|
const paths = require('../utils/paths')
|
||||||
|
// after renderer is built, main is next to build
|
||||||
|
const webpackConfig = require('../config/main')
|
||||||
|
const config = require('../project.config')
|
||||||
|
|
||||||
|
logWithSpinner('Building for production...')
|
||||||
|
// removed rm function to prevent the deletion of renderer
|
||||||
|
webpack(webpackConfig, (err, stats) => {
|
||||||
|
stopSpinner(false)
|
||||||
|
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
process.stdout.write(
|
||||||
|
stats.toString({
|
||||||
|
colors: true,
|
||||||
|
modules: false,
|
||||||
|
children: false,
|
||||||
|
chunks: false,
|
||||||
|
chunkModules: false,
|
||||||
|
}) + '\n\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (stats.hasErrors()) {
|
||||||
|
error('Build failed with errors.\n')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
done('Build complete.\n')
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const loadEnv = require('../utils/loadEnv')
|
||||||
|
loadEnv()
|
||||||
|
loadEnv('production')
|
||||||
|
|
||||||
|
const rm = require('rimraf')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
|
||||||
|
const { error, done } = require('../utils/logger')
|
||||||
|
const { logWithSpinner, stopSpinner } = require('../utils/spinner')
|
||||||
|
const paths = require('../utils/paths')
|
||||||
|
// build renderer first
|
||||||
|
const webpackConfig = require('../config/renderer')
|
||||||
|
const config = require('../project.config')
|
||||||
|
|
||||||
|
logWithSpinner('Building for production...')
|
||||||
|
|
||||||
|
rm(paths.resolve(config.outputDir), (err) => {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
webpack(webpackConfig, (err, stats) => {
|
||||||
|
stopSpinner(false)
|
||||||
|
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
process.stdout.write(
|
||||||
|
stats.toString({
|
||||||
|
colors: true,
|
||||||
|
modules: false,
|
||||||
|
children: false,
|
||||||
|
chunks: false,
|
||||||
|
chunkModules: false,
|
||||||
|
}) + '\n\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (stats.hasErrors()) {
|
||||||
|
error('Build failed with errors.\n')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
done('Build complete.\n')
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,102 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const loadEnv = require('../utils/loadEnv')
|
||||||
|
loadEnv()
|
||||||
|
loadEnv('development')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
const WebpackDevServer = require('webpack-dev-server')
|
||||||
|
const { info } = require('../utils/logger')
|
||||||
|
const getLocalIP = require('../utils/getLocalIP')
|
||||||
|
const devWebpackConfig = require('../config/dev')
|
||||||
|
const devServerOptions = devWebpackConfig.devServer
|
||||||
|
const { spawn } = require('node:child_process')
|
||||||
|
const electron = require('electron')
|
||||||
|
const path = require('path')
|
||||||
|
const url = require('url')
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
let electronProcess = null
|
||||||
|
let manualRestart = false
|
||||||
|
// disable warnings in browser console
|
||||||
|
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'false'
|
||||||
|
|
||||||
|
const protocol = devServerOptions.https ? 'https' : 'http'
|
||||||
|
const host = devServerOptions.host || '0.0.0.0'
|
||||||
|
const port = devServerOptions.port || 8080
|
||||||
|
|
||||||
|
// older code that sets the url for the path I would assume
|
||||||
|
var parseArg = process.argv[2] || ""
|
||||||
|
var yarnArg = url.parse(parseArg)
|
||||||
|
|
||||||
|
function resetPort() {
|
||||||
|
let resetData = { "_comment1": "port should not be declared when commiting" }
|
||||||
|
fs.writeFileSync(path.join(__dirname, "../../src/lib/flaskserverport.json"), JSON.stringify(resetData), 'utf8')
|
||||||
|
console.log("Resetting the flaskport")
|
||||||
|
}
|
||||||
|
|
||||||
|
function startElectron(webpackport) {
|
||||||
|
var wbport = webpackport
|
||||||
|
// this sends url to proper position
|
||||||
|
process.argv.shift()
|
||||||
|
process.argv.shift()
|
||||||
|
// get URL from PrintPDF
|
||||||
|
// checks if url is http
|
||||||
|
if (yarnArg.protocol) {
|
||||||
|
var args = [
|
||||||
|
'--inspect=5858',
|
||||||
|
path.join(__dirname, '../../dist/electron/main.js')
|
||||||
|
].concat(process.argv)
|
||||||
|
} else {
|
||||||
|
var args = [
|
||||||
|
'--inspect=5858',
|
||||||
|
`http://0.0.0.0:${wbport}/#${process.argv}`
|
||||||
|
].concat(process.argv)
|
||||||
|
}
|
||||||
|
// detect yarn or npm and process commandline args accordingly
|
||||||
|
if (process.env.npm_execpath.endsWith('yarn.js')) {
|
||||||
|
args = args.concat(process.argv.slice(3))
|
||||||
|
} else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
|
||||||
|
args = args.concat(process.argv.slice(2))
|
||||||
|
}
|
||||||
|
electronProcess = spawn(electron, args)
|
||||||
|
electronProcess.on('close', () => {
|
||||||
|
if (!manualRestart) {
|
||||||
|
process.exit()
|
||||||
|
} else {
|
||||||
|
process.kill(electronProcess.pid)
|
||||||
|
}
|
||||||
|
resetPort()
|
||||||
|
})
|
||||||
|
electronProcess.on('exit', () => {
|
||||||
|
resetPort()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
info('Starting development server...')
|
||||||
|
const compiler = webpack(devWebpackConfig)
|
||||||
|
const server = new WebpackDevServer(devServerOptions, compiler)
|
||||||
|
|
||||||
|
compiler.hooks.done.tap('serve', (stats) => {
|
||||||
|
console.log()
|
||||||
|
console.log()
|
||||||
|
console.log(`App running at:`)
|
||||||
|
console.log(` - Local: ${chalk.cyan(`${protocol}://${host}:${port}`)}`)
|
||||||
|
console.log(` - Network: ${chalk.cyan(`${protocol}://${getLocalIP()}:${port}`)}`)
|
||||||
|
console.log()
|
||||||
|
|
||||||
|
// allows livereload for webpack devserver to work without multiple instances of electron
|
||||||
|
if (electronProcess) {
|
||||||
|
manualRestart = true
|
||||||
|
} else {
|
||||||
|
manualRestart = false
|
||||||
|
// starts nodejs electron commandline browser
|
||||||
|
startElectron(devServerOptions.port)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
server.start(port, host, (err) => {
|
||||||
|
if (err) {
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,126 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { DefinePlugin, EnvironmentPlugin } = require('webpack')
|
||||||
|
const { VueLoaderPlugin } = require('vue-loader')
|
||||||
|
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
|
||||||
|
const HTMLPlugin = require('html-webpack-plugin')
|
||||||
|
const { VuetifyPlugin } = require('webpack-plugin-vuetify')
|
||||||
|
|
||||||
|
const resolveClientEnv = require('../utils/resolveClientEnv')
|
||||||
|
const paths = require('../utils/paths')
|
||||||
|
|
||||||
|
const config = require('../project.config')
|
||||||
|
|
||||||
|
const isProd = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
context: process.cwd(),
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: paths.resolve(config.outputDir),
|
||||||
|
publicPath: config.dev.publicPath,
|
||||||
|
filename: '[name].js',
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': paths.resolve('src'),
|
||||||
|
},
|
||||||
|
extensions: ['.ts', '.tsx', '.js', '.jsx', '.vue', '.json', 'html', 'ejs'],
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
new VueLoaderPlugin(),
|
||||||
|
new EnvironmentPlugin(['NODE_ENV']),
|
||||||
|
new CaseSensitivePathsPlugin(),
|
||||||
|
new HTMLPlugin({
|
||||||
|
template: paths.resolve('src/index.html'),
|
||||||
|
templateParameters: {
|
||||||
|
...resolveClientEnv(
|
||||||
|
{ publicPath: isProd ? config.build.publicPath : config.dev.publicPath },
|
||||||
|
false /* raw */
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new VuetifyPlugin({ autoImport: true }),
|
||||||
|
new DefinePlugin({
|
||||||
|
// vue3 feature flags <http://link.vuejs.org/feature-flags>
|
||||||
|
__VUE_OPTIONS_API__: 'true',
|
||||||
|
__VUE_PROD_DEVTOOLS__: 'false',
|
||||||
|
|
||||||
|
...resolveClientEnv({
|
||||||
|
publicPath: isProd ? config.build.publicPath : config.dev.publicPath,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
module: {
|
||||||
|
noParse: /^(vue|vue-router)$/,
|
||||||
|
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: 'vue-loader',
|
||||||
|
},
|
||||||
|
// babel
|
||||||
|
{
|
||||||
|
test: /\.m?jsx?$/,
|
||||||
|
exclude: (file) => {
|
||||||
|
// always transpile js in vue files
|
||||||
|
if (/\.vue\.jsx?$/.test(file)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Don't transpile node_modules
|
||||||
|
return /node_modules/.test(file)
|
||||||
|
},
|
||||||
|
use: ['thread-loader', 'babel-loader'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ts
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: [
|
||||||
|
'thread-loader',
|
||||||
|
'babel-loader',
|
||||||
|
{
|
||||||
|
loader: 'ts-loader',
|
||||||
|
options: {
|
||||||
|
transpileOnly: true,
|
||||||
|
appendTsSuffixTo: ['\\.vue$'],
|
||||||
|
happyPackMode: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// images
|
||||||
|
{
|
||||||
|
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
|
||||||
|
type: 'asset',
|
||||||
|
generator: { filename: 'img/[contenthash:8][ext][query]' },
|
||||||
|
},
|
||||||
|
|
||||||
|
// do not base64-inline SVGs.
|
||||||
|
// https://github.com/facebookincubator/create-react-app/pull/1180
|
||||||
|
{
|
||||||
|
test: /\.(svg)(\?.*)?$/,
|
||||||
|
type: 'asset/resource',
|
||||||
|
generator: { filename: 'img/[contenthash:8][ext][query]' },
|
||||||
|
},
|
||||||
|
|
||||||
|
// media
|
||||||
|
{
|
||||||
|
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||||
|
type: 'asset',
|
||||||
|
generator: { filename: 'media/[contenthash:8][ext][query]' },
|
||||||
|
},
|
||||||
|
|
||||||
|
// fonts
|
||||||
|
{
|
||||||
|
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
|
||||||
|
type: 'asset',
|
||||||
|
generator: { filename: 'fonts/[contenthash:8][ext][query]' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
|
|
||||||
|
const isProd = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
|
const plugins = []
|
||||||
|
if (isProd) {
|
||||||
|
const filename = 'css/[name].[contenthash:8].css'
|
||||||
|
|
||||||
|
plugins.push(
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename,
|
||||||
|
chunkFilename: filename,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const genStyleRules = () => {
|
||||||
|
const cssLoader = {
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
// how many loaders before css-loader should be applied to [@import]ed resources.
|
||||||
|
// stylePostLoader injected by vue-loader + postcss-loader
|
||||||
|
importLoaders: 1 + 1,
|
||||||
|
esModule: false, // css-loader using ES Modules as default in v4, but vue-style-loader support cjs only.
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const postcssLoader = {
|
||||||
|
loader: 'postcss-loader',
|
||||||
|
options: {
|
||||||
|
postcssOptions: {
|
||||||
|
plugins: [require('autoprefixer')]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const extractPluginLoader = {
|
||||||
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
}
|
||||||
|
const vueStyleLoader = {
|
||||||
|
loader: 'vue-style-loader',
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCSSRule(test, loader, loaderOptions) {
|
||||||
|
const loaders = [cssLoader, postcssLoader]
|
||||||
|
|
||||||
|
if (isProd) {
|
||||||
|
loaders.unshift(extractPluginLoader)
|
||||||
|
} else {
|
||||||
|
loaders.unshift(vueStyleLoader)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader) {
|
||||||
|
loaders.push({ loader, options: loaderOptions })
|
||||||
|
}
|
||||||
|
|
||||||
|
return { test, use: loaders }
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
createCSSRule(/\.css$/),
|
||||||
|
createCSSRule(/\.p(ost)?css$/),
|
||||||
|
createCSSRule(/\.scss$/, 'sass-loader')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
plugins,
|
||||||
|
module: {
|
||||||
|
rules: genStyleRules(),
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
|
||||||
|
const baseWebpackConfig = require('./base')
|
||||||
|
const cssWebpackConfig = require('./css')
|
||||||
|
const config = require('../project.config')
|
||||||
|
const { ProvidePlugin, DefinePlugin } = require('webpack')
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = merge(baseWebpackConfig, cssWebpackConfig, {
|
||||||
|
entry: {
|
||||||
|
main: './src/renderer/main.js'
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: 'development',
|
||||||
|
|
||||||
|
devtool: 'eval-cheap-module-source-map',
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
watchFiles: ['src/**/*'],
|
||||||
|
historyApiFallback: {
|
||||||
|
rewrites: [{ from: /./, to: '/index.html' }],
|
||||||
|
},
|
||||||
|
devMiddleware: {
|
||||||
|
publicPath: config.dev.publicPath,
|
||||||
|
},
|
||||||
|
open: false,
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 'auto',
|
||||||
|
liveReload: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
infrastructureLogging: {
|
||||||
|
level: 'warn',
|
||||||
|
},
|
||||||
|
|
||||||
|
stats: {
|
||||||
|
assets: false,
|
||||||
|
modules: false,
|
||||||
|
errorDetails: false,
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,73 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
|
||||||
|
const config = require('../project.config')
|
||||||
|
|
||||||
|
const resolveClientEnv = require('../utils/resolveClientEnv')
|
||||||
|
const paths = require('../utils/paths')
|
||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin')
|
||||||
|
const cssWebpackConfig = require('./css')
|
||||||
|
const terserOptions = require('./terserOptions')
|
||||||
|
const isProd = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
|
module.exports = merge(cssWebpackConfig, {
|
||||||
|
context: process.cwd(),
|
||||||
|
mode: 'production',
|
||||||
|
entry: {
|
||||||
|
main: './src/main/index.js',
|
||||||
|
preload: './src/main/preload.js',
|
||||||
|
},
|
||||||
|
|
||||||
|
node: {
|
||||||
|
__dirname: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [new TerserPlugin(terserOptions())],
|
||||||
|
moduleIds: 'named',
|
||||||
|
},
|
||||||
|
target: ['electron-main'],
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: paths.resolve(config.outputDir),
|
||||||
|
publicPath: config.dev.publicPath,
|
||||||
|
filename: '[name].js',
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': paths.resolve('src'),
|
||||||
|
},
|
||||||
|
extensions: ['.ts', '.tsx', '.js', '.jsx', '.vue', '.json', 'html', 'ejs'],
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
new CaseSensitivePathsPlugin(),
|
||||||
|
],
|
||||||
|
|
||||||
|
module: {
|
||||||
|
noParse: /^(vue|vue-router)$/,
|
||||||
|
|
||||||
|
rules: [
|
||||||
|
// ts
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: [
|
||||||
|
'thread-loader',
|
||||||
|
'babel-loader',
|
||||||
|
{
|
||||||
|
loader: 'ts-loader',
|
||||||
|
options: {
|
||||||
|
transpileOnly: true,
|
||||||
|
appendTsSuffixTo: ['\\.vue$'],
|
||||||
|
happyPackMode: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,41 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin')
|
||||||
|
|
||||||
|
const baseWebpackConfig = require('./base')
|
||||||
|
const cssWebpackConfig = require('./css')
|
||||||
|
const config = require('../project.config')
|
||||||
|
const terserOptions = require('./terserOptions')
|
||||||
|
|
||||||
|
module.exports = merge(baseWebpackConfig, cssWebpackConfig, {
|
||||||
|
mode: 'production',
|
||||||
|
|
||||||
|
output: {
|
||||||
|
publicPath: config.build.publicPath,
|
||||||
|
},
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [new TerserPlugin(terserOptions())],
|
||||||
|
moduleIds: 'deterministic',
|
||||||
|
moduleIds: 'named',
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
defaultVendors: {
|
||||||
|
name: `chunk-vendors`,
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
priority: -10,
|
||||||
|
chunks: 'initial',
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
name: `chunk-common`,
|
||||||
|
minChunks: 2,
|
||||||
|
priority: -20,
|
||||||
|
chunks: 'initial',
|
||||||
|
reuseExistingChunk: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,45 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { merge } = require('webpack-merge')
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin')
|
||||||
|
|
||||||
|
const baseWebpackConfig = require('./base')
|
||||||
|
const cssWebpackConfig = require('./css')
|
||||||
|
const config = require('../project.config')
|
||||||
|
const terserOptions = require('./terserOptions')
|
||||||
|
|
||||||
|
module.exports = merge(baseWebpackConfig, cssWebpackConfig, {
|
||||||
|
mode: 'production',
|
||||||
|
entry: {
|
||||||
|
renderer: './src/renderer/main.js',
|
||||||
|
},
|
||||||
|
|
||||||
|
output: {
|
||||||
|
publicPath: config.build.publicPath,
|
||||||
|
},
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [new TerserPlugin(terserOptions())],
|
||||||
|
moduleIds: 'deterministic',
|
||||||
|
moduleIds: 'named',
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
defaultVendors: {
|
||||||
|
name: `chunk-vendors`,
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
priority: -10,
|
||||||
|
chunks: 'initial',
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
name: `chunk-common`,
|
||||||
|
minChunks: 2,
|
||||||
|
priority: -20,
|
||||||
|
chunks: 'initial',
|
||||||
|
reuseExistingChunk: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
target: ['electron-renderer'],
|
||||||
|
})
|
|
@ -0,0 +1,42 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = (options) => ({
|
||||||
|
terserOptions: {
|
||||||
|
compress: {
|
||||||
|
// turn off flags with small gains to speed up minification
|
||||||
|
arrows: false,
|
||||||
|
collapse_vars: false, // 0.3kb
|
||||||
|
comparisons: false,
|
||||||
|
computed_props: false,
|
||||||
|
hoist_funs: false,
|
||||||
|
hoist_props: false,
|
||||||
|
hoist_vars: false,
|
||||||
|
inline: false,
|
||||||
|
loops: false,
|
||||||
|
negate_iife: false,
|
||||||
|
properties: false,
|
||||||
|
reduce_funcs: false,
|
||||||
|
reduce_vars: false,
|
||||||
|
switches: false,
|
||||||
|
toplevel: false,
|
||||||
|
typeofs: false,
|
||||||
|
|
||||||
|
// a few flags with noticable gains/speed ratio
|
||||||
|
// numbers based on out of the box vendor bundle
|
||||||
|
booleans: true, // 0.7kb
|
||||||
|
if_return: true, // 0.4kb
|
||||||
|
sequences: true, // 0.7kb
|
||||||
|
unused: true, // 2.3kb
|
||||||
|
|
||||||
|
// required features to drop conditional branches
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
},
|
||||||
|
mangle: {
|
||||||
|
safari10: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// parallel: options.parallel,
|
||||||
|
extractComments: false,
|
||||||
|
})
|
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// orginal was dist
|
||||||
|
outputDir: 'dist/electron',
|
||||||
|
|
||||||
|
dev: {
|
||||||
|
publicPath: '/',
|
||||||
|
port: 8080,
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
// orginal was /
|
||||||
|
publicPath: './',
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const os = require('os')
|
||||||
|
|
||||||
|
module.exports = function getLocalIP() {
|
||||||
|
const interfaces = os.networkInterfaces()
|
||||||
|
|
||||||
|
for (const devName in interfaces) {
|
||||||
|
const iface = interfaces[devName]
|
||||||
|
for (let i = 0; i < iface.length; i++) {
|
||||||
|
const alias = iface[i]
|
||||||
|
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
|
||||||
|
return alias.address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
const dotenv = require('dotenv')
|
||||||
|
const dotenvExpand = require('dotenv-expand')
|
||||||
|
const { error } = require('./logger')
|
||||||
|
|
||||||
|
module.exports = function loadEnv(mode) {
|
||||||
|
const basePath = path.resolve(process.cwd(), `.env${mode ? `.${mode}` : ``}`)
|
||||||
|
const localPath = `${basePath}.local`
|
||||||
|
|
||||||
|
const load = (envPath) => {
|
||||||
|
try {
|
||||||
|
const env = dotenv.config({ path: envPath, debug: process.env.DEBUG })
|
||||||
|
dotenvExpand.expand(env)
|
||||||
|
} catch (err) {
|
||||||
|
// only ignore error if file is not found
|
||||||
|
if (err.toString().indexOf('ENOENT') < 0) {
|
||||||
|
error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load(localPath)
|
||||||
|
load(basePath)
|
||||||
|
|
||||||
|
// by default, NODE_ENV and BABEL_ENV are set to "development" unless mode
|
||||||
|
// is production or test. However the value in .env files will take higher
|
||||||
|
// priority.
|
||||||
|
if (mode) {
|
||||||
|
const defaultNodeEnv = mode === 'production' || mode === 'test' ? mode : 'development'
|
||||||
|
if (process.env.NODE_ENV == null) {
|
||||||
|
process.env.NODE_ENV = defaultNodeEnv
|
||||||
|
}
|
||||||
|
if (process.env.BABEL_ENV == null) {
|
||||||
|
process.env.BABEL_ENV = defaultNodeEnv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const stripAnsi = require('strip-ansi')
|
||||||
|
const readline = require('readline')
|
||||||
|
const EventEmitter = require('events')
|
||||||
|
|
||||||
|
exports.events = new EventEmitter()
|
||||||
|
|
||||||
|
function _log(type, tag, message) {
|
||||||
|
if (process.env.VUE_CLI_API_MODE && message) {
|
||||||
|
exports.events.emit('log', {
|
||||||
|
message,
|
||||||
|
type,
|
||||||
|
tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const format = (label, msg) => {
|
||||||
|
return msg
|
||||||
|
.split('\n')
|
||||||
|
.map((line, i) => {
|
||||||
|
return i === 0 ? `${label} ${line}` : line.padStart(stripAnsi(label).length)
|
||||||
|
})
|
||||||
|
.join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
const chalkTag = (msg) => chalk.bgBlackBright.white.dim(` ${msg} `)
|
||||||
|
|
||||||
|
exports.log = (msg = '', tag = null) => {
|
||||||
|
tag ? console.log(format(chalkTag(tag), msg)) : console.log(msg)
|
||||||
|
_log('log', tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.info = (msg, tag = null) => {
|
||||||
|
console.log(format(chalk.bgBlue.black(' INFO ') + (tag ? chalkTag(tag) : ''), msg))
|
||||||
|
_log('info', tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.done = (msg, tag = null) => {
|
||||||
|
console.log(format(chalk.bgGreen.black(' DONE ') + (tag ? chalkTag(tag) : ''), msg))
|
||||||
|
_log('done', tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.warn = (msg, tag = null) => {
|
||||||
|
console.warn(
|
||||||
|
format(chalk.bgYellow.black(' WARN ') + (tag ? chalkTag(tag) : ''), chalk.yellow(msg))
|
||||||
|
)
|
||||||
|
_log('warn', tag, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.error = (msg, tag = null) => {
|
||||||
|
console.error(format(chalk.bgRed(' ERROR ') + (tag ? chalkTag(tag) : ''), chalk.red(msg)))
|
||||||
|
_log('error', tag, msg)
|
||||||
|
if (msg instanceof Error) {
|
||||||
|
console.error(msg.stack)
|
||||||
|
_log('error', tag, msg.stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.clearConsole = (title) => {
|
||||||
|
if (process.stdout.isTTY) {
|
||||||
|
const blank = '\n'.repeat(process.stdout.rows)
|
||||||
|
console.log(blank)
|
||||||
|
readline.cursorTo(process.stdout, 0, 0)
|
||||||
|
readline.clearScreenDown(process.stdout)
|
||||||
|
if (title) {
|
||||||
|
console.log(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
// gen absolute path
|
||||||
|
exports.resolve = (...args) => path.posix.join(process.cwd(), ...args)
|
|
@ -0,0 +1,11 @@
|
||||||
|
'use strict'
|
||||||
|
const prefixRE = /^VUE_APP_/
|
||||||
|
|
||||||
|
module.exports = function resolveClientEnv(options, raw) {
|
||||||
|
process.env.PUBLIC_PATH = options.publicPath
|
||||||
|
|
||||||
|
if (raw) {
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const ora = require('ora')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
const spinner = ora()
|
||||||
|
let lastMsg = null
|
||||||
|
let isPaused = false
|
||||||
|
|
||||||
|
exports.logWithSpinner = (symbol, msg) => {
|
||||||
|
if (!msg) {
|
||||||
|
msg = symbol
|
||||||
|
symbol = chalk.green('✔')
|
||||||
|
}
|
||||||
|
if (lastMsg) {
|
||||||
|
spinner.stopAndPersist({
|
||||||
|
symbol: lastMsg.symbol,
|
||||||
|
text: lastMsg.text,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
spinner.text = ' ' + msg
|
||||||
|
lastMsg = {
|
||||||
|
symbol: symbol + ' ',
|
||||||
|
text: msg,
|
||||||
|
}
|
||||||
|
spinner.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.stopSpinner = (persist) => {
|
||||||
|
if (lastMsg && persist !== false) {
|
||||||
|
spinner.stopAndPersist({
|
||||||
|
symbol: lastMsg.symbol,
|
||||||
|
text: lastMsg.text,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
spinner.stop()
|
||||||
|
}
|
||||||
|
lastMsg = null
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.pauseSpinner = () => {
|
||||||
|
if (spinner.isSpinning) {
|
||||||
|
spinner.stop()
|
||||||
|
isPaused = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.resumeSpinner = () => {
|
||||||
|
if (isPaused) {
|
||||||
|
spinner.start()
|
||||||
|
isPaused = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.failSpinner = (text) => {
|
||||||
|
spinner.fail(text)
|
||||||
|
}
|
|
@ -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>
|
|
|
@ -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>
|
|
@ -6,11 +6,19 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const axios = require('axios')
|
import axios from 'axios';
|
||||||
const queryString = require('query-string')
|
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({
|
export const inkStitch = axios.create({
|
||||||
baseURL: `http://127.0.0.1:${port}/`
|
baseURL: `http://127.0.0.1:${theflaskport}`
|
||||||
})
|
})
|
||||||
|
|
|
@ -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
|
// get a list of available translations
|
||||||
var availableTranslations = ['en_US'];
|
var availableTranslations = ['en_US'];
|
||||||
for(var k in translations) availableTranslations.push(k);
|
for (var k in translations) availableTranslations.push(k);
|
||||||
|
|
||||||
var lang = undefined;
|
var lang = undefined;
|
||||||
|
|
||||||
// get system language / Inkscape language
|
// get system language / Inkscape language
|
||||||
['LANG', 'LC_MESSAGES', 'LC_ALL', 'LANGUAGE'].forEach(language => {
|
['LANG', 'LC_MESSAGES', 'LC_ALL', 'LANGUAGE'].forEach(language => {
|
||||||
if (process.env[language]) {
|
if (process[language]) {
|
||||||
// split encoding information, we don't need it
|
// 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) {
|
if (current_lang.length == 2) {
|
||||||
// current language has only two letters (e.g. en),
|
// 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)
|
// 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 {
|
} else {
|
||||||
lang = current_lang;
|
lang = current_lang;
|
||||||
}
|
}
|
||||||
|
@ -33,3 +44,4 @@ module.exports.selectLanguage = function (translations) {
|
||||||
}
|
}
|
||||||
return lang
|
return lang
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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')
|
|
|
@ -8,113 +8,104 @@
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import {app, BrowserWindow, ipcMain, dialog, shell} from 'electron'
|
const path = require('path')
|
||||||
var fs = require('fs');
|
const fs = require('fs')
|
||||||
var path = require('path');
|
const tmp = require('tmp')
|
||||||
var tmp = require('tmp');
|
|
||||||
|
|
||||||
const url = require('url')
|
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
|
||||||
|
|
||||||
/**
|
var port = process.env.FLASKPORT
|
||||||
* Set `__static` path to static files in production
|
const printPdfUrl = `http://127.0.0.1:${port}/`
|
||||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
|
||||||
*/
|
const isDev = process.env.BABEL_ENV === 'development'
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
// we were run as electron --inspect=5858 path/to/main.js <args>
|
var target = null
|
||||||
// so get rid of the first two args
|
// Finds this url in the argv array and sets to target value
|
||||||
console.log("args " + process.argv)
|
if (process.argv.includes(printPdfUrl)) {
|
||||||
process.argv.shift()
|
target = printPdfUrl
|
||||||
process.argv.shift()
|
|
||||||
} else {
|
} else {
|
||||||
global.__static = path.join(__dirname, '/static').replace(/\\/g, '\\\\')
|
target = process.argv[1] || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
let mainWindow
|
|
||||||
|
|
||||||
var target = process.argv[1] || "";
|
|
||||||
var targetURL = url.parse(target)
|
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.
|
// Eventually this will be migrated to Vue.
|
||||||
if (targetURL.protocol) {
|
if (targetURL.protocol) {
|
||||||
winURL = target
|
winURL = target
|
||||||
} else {
|
} else {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}`
|
||||||
winURL = `http://localhost:9080/?${targetURL.query || ""}#${targetURL.pathname || ""}`
|
|
||||||
} else {
|
|
||||||
winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
/**
|
const mainWindow = new BrowserWindow({
|
||||||
* Initial window options
|
useContentSize: true,
|
||||||
*/
|
webPreferences: {
|
||||||
mainWindow = new BrowserWindow({
|
preload: path.join(__dirname, 'preload.js'),
|
||||||
height: 563,
|
nodeIntegration: false,
|
||||||
useContentSize: true,
|
contextIsolation: true,
|
||||||
width: 1000,
|
},
|
||||||
webPreferences: {nodeIntegration: true}
|
})
|
||||||
})
|
if (isDev) {
|
||||||
|
// printPDF in development mode will have dev tools activated
|
||||||
mainWindow.loadURL(winURL)
|
// Vuejs parts of Ink/Stich will not and dev tools must be accessed though the menu of electron window
|
||||||
mainWindow.maximize()
|
mainWindow.loadURL(winURL)
|
||||||
|
mainWindow.webContents.openDevTools()
|
||||||
mainWindow.on('closed', () => {
|
} else {
|
||||||
mainWindow = null
|
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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// 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, pageSize, 'utf-8');
|
||||||
|
shell.openPath(path);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on('ready', createWindow)
|
app.whenReady().then(() => {
|
||||||
|
createWindow()
|
||||||
|
app.on('activate', () => {
|
||||||
|
if(BrowserWindow.getAllWindows().length === 0) {
|
||||||
|
createWindow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
app.quit()
|
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');
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.on('open-pdf', function (event, pageSize) {
|
|
||||||
mainWindow.webContents.printToPDF({"pageSize": pageSize}, function(error, data) {
|
|
||||||
tmp.file({keep: true, discardDescriptor: true}, function(err, path, fd, cleanupCallback) {
|
|
||||||
fs.writeFileSync(path, data, 'utf-8');
|
|
||||||
shell.openItem(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.on('ready', () => {
|
|
||||||
if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
|
@ -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,
|
||||||
|
})
|
|
@ -9,20 +9,9 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<v-app>
|
|
||||||
<v-main>
|
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</v-main>
|
|
||||||
</v-app>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'my-project'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons');
|
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons');
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -5,19 +5,18 @@
|
||||||
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
* 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'
|
import { SVG } from '@svgdotjs/svg.js'
|
||||||
require('@svgdotjs/svg.panzoom.js/src/svg.panzoom.js')
|
import '@svgdotjs/svg.panzoom.js'
|
||||||
require('@svgdotjs/svg.filter.js')
|
import '@svgdotjs/svg.filter.js'
|
||||||
const svgpath = require('svgpath')
|
import svgpath from 'svgpath'
|
||||||
import Loading from 'vue-loading-overlay';
|
import Loading from 'vue-loading-overlay';
|
||||||
import 'vue-loading-overlay/dist/vue-loading.css';
|
import 'vue-loading-overlay/dist/vue-loading.css';
|
||||||
|
import { reactive, toRefs } from 'vue'
|
||||||
import VueSlider from 'vue-slider-component'
|
import VueSlider from 'vue-slider-component'
|
||||||
import 'vue-slider-component/theme/default.css'
|
import 'vue-slider-component/theme/antd.css'
|
||||||
|
import throttle from 'lodash/throttle'
|
||||||
const throttle = require('lodash.throttle')
|
|
||||||
|
|
||||||
function SliderMark(command, icon) {
|
function SliderMark(command, icon) {
|
||||||
this.label = ""
|
this.label = ""
|
||||||
|
@ -31,6 +30,10 @@ export default {
|
||||||
Loading,
|
Loading,
|
||||||
VueSlider
|
VueSlider
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const data = reactive({ value: 0 })
|
||||||
|
return toRefs(data)
|
||||||
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -511,15 +514,23 @@ export default {
|
||||||
},
|
},
|
||||||
generatePage () {
|
generatePage () {
|
||||||
this.$refs.simulator.style.backgroundColor = this.page_specs.deskcolor
|
this.$refs.simulator.style.backgroundColor = this.page_specs.deskcolor
|
||||||
|
|
||||||
let page = this.svg.rect(this.page_specs.width, this.page_specs.height)
|
let page = this.svg.rect(this.page_specs.width, this.page_specs.height)
|
||||||
.move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1])
|
.move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1])
|
||||||
.fill(this.page_specs.pagecolor)
|
.fill(this.page_specs.pagecolor)
|
||||||
.stroke({width: 1, color: 'black'})
|
.stroke({width: 0.1, color: this.page_specs.bordercolor})
|
||||||
.filterWith(add => {
|
|
||||||
let blur = add.offset(2,2).in(add.$sourceAlpha).gaussianBlur(2)
|
|
||||||
add.blend(add.$source, blur)
|
|
||||||
})
|
|
||||||
.back()
|
.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()
|
this.page_specs["bbox"] = page.bbox()
|
||||||
},
|
},
|
||||||
zoomDesign () {
|
zoomDesign () {
|
||||||
|
@ -606,29 +617,30 @@ export default {
|
||||||
this.generateColorSections()
|
this.generateColorSections()
|
||||||
this.generateScale()
|
this.generateScale()
|
||||||
this.generateCursor()
|
this.generateCursor()
|
||||||
|
this.resizeCursor()
|
||||||
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
||||||
// v-on:keydown doesn't seem to work, maybe an Electron issue?
|
// v-on:keydown doesn't seem to work, maybe an Electron issue?
|
||||||
Mousetrap.bind("up", this.animationSpeedUp)
|
this.$mousetrap.bind("up", this.animationSpeedUp)
|
||||||
Mousetrap.bind("down", this.animationSlowDown)
|
this.$mousetrap.bind("down", this.animationSlowDown)
|
||||||
Mousetrap.bind("left", this.animationReverse)
|
this.$mousetrap.bind("left", this.animationReverse)
|
||||||
Mousetrap.bind("right", this.animationForward)
|
this.$mousetrap.bind("right", this.animationForward)
|
||||||
Mousetrap.bind("pagedown", this.animationPreviousCommand)
|
this.$mousetrap.bind("pagedown", this.animationPreviousCommand)
|
||||||
Mousetrap.bind("pageup", this.animationNextCommand)
|
this.$mousetrap.bind("pageup", this.animationNextCommand)
|
||||||
Mousetrap.bind("space", this.toggleAnimation)
|
this.$mousetrap.bind("space", this.toggleAnimation)
|
||||||
Mousetrap.bind("+", this.animationForwardOneStitch)
|
this.$mousetrap.bind("+", this.animationForwardOneStitch)
|
||||||
Mousetrap.bind("-", this.animationBackwardOneStitch)
|
this.$mousetrap.bind("-", this.animationBackwardOneStitch)
|
||||||
Mousetrap.bind("]", this.zoomDesign)
|
this.$mousetrap.bind("]", this.zoomDesign)
|
||||||
Mousetrap.bind("[", this.zoomPage)
|
this.$mousetrap.bind("[", this.zoomPage)
|
||||||
|
|
||||||
this.svg.on('zoom', this.resizeCursor)
|
this.svg.on('zoom', this.resizeCursor)
|
||||||
this.resizeCursor()
|
|
||||||
|
|
||||||
inkStitch.get('page_specs').then(response => {
|
inkStitch.get('page_specs').then(response => {
|
||||||
this.page_specs = response.data
|
this.page_specs = response.data
|
||||||
this.generatePage()
|
this.generatePage()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.start()
|
this.start()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
* {
|
||||||
* {
|
padding: 1px;
|
||||||
box-sizing: border-box;
|
margin: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-icon {
|
.loading-icon {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -32,7 +31,7 @@ button {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: default;
|
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;
|
box-sizing: border-box;
|
||||||
padding: 2px 6px 3px;
|
padding: 2px 6px 3px;
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
|
@ -183,7 +182,7 @@ button.pressed {
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-slider {
|
.vue-slider {
|
||||||
height: 25px !important;
|
height: 10px !important;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +202,7 @@ button.pressed {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-container::v-deep .vue-slider-mark-step {
|
.slider-container :deep(.vue-slider-mark-step) {
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
@ -212,26 +211,26 @@ button.pressed {
|
||||||
box-shadow: inset 1px 0 1px #ffffffbd, inset -1px 0 1px black;
|
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 :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:last-child .vue-slider-mark-step) {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-container::v-deep .vue-slider-rail {
|
.slider-container :deep(.vue-slider-rail) {
|
||||||
border: 1px solid #dedede;
|
border: 1px solid #dedede;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-container::v-deep .vue-slider-process {
|
.slider-container :deep(.vue-slider-process) {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: inset 0px 2px 2px #ffffff80, inset 0px -2px 2px #0000002e;
|
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-top-left-radius: 15px;
|
||||||
border-bottom-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-top-right-radius: 15px;
|
||||||
border-bottom-right-radius: 15px;
|
border-bottom-right-radius: 15px;
|
||||||
}
|
}
|
||||||
|
@ -247,20 +246,20 @@ button.pressed {
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-label-trim {
|
.slider-label-trim {
|
||||||
transform: scale(1, 0.75) translate(-50%, -9px);
|
transform: scale(1, 0.75) translate(-50%, -9px) !important;;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-label-stop {
|
.slider-label-stop {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
transform: translate(-50%, 12px);
|
transform: translate(-50%, 12px) !important;;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-label-jump {
|
.slider-label-jump {
|
||||||
transform: translate(-50%, -50px);
|
transform: translate(-50%, -50px) !important;;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-label-color-change {
|
.slider-label-color-change {
|
||||||
transform: translate(-50%, 10px);
|
transform: translate(-50%, 10px) !important;;
|
||||||
}
|
}
|
||||||
|
|
||||||
.current-stitch-input {
|
.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
|
/* we need ::v-deep here because the svg tag is added by svg.js and so Vue
|
||||||
can't add the data-v-* attribute
|
can't add the data-v-* attribute
|
||||||
*/
|
*/
|
||||||
div.simulator::v-deep svg.simulation {
|
div.simulator :deep(svg.simulation) {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
order: -2;
|
order: -2;
|
||||||
margin-bottom: -48px;
|
margin-bottom: -48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.simulator::v-deep svg.simulation-scale {
|
div.simulator :deep(svg.simulation-scale) {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
order: -1;
|
order: -1;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.simulator::v-deep .simulation-scale-label {
|
div.simulator :deep(.simulation-scale-label) {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.simulator::v-deep .cursor {
|
div.simulator :deep(.cursor) {
|
||||||
/* not sure what to add here to make it more visible */
|
/* not sure what to add here to make it more visible */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
|
@ -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>
|
|
@ -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>
|
<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">
|
<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
|
Ink/Stitch Settings
|
||||||
</h1>
|
</h1>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
|
||||||
<v-card-text>
|
<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">
|
<v-tab key="this_svg_settings">
|
||||||
This SVG
|
This SVG
|
||||||
</v-tab>
|
</v-tab>
|
||||||
|
@ -16,16 +25,16 @@
|
||||||
</v-tab>
|
</v-tab>
|
||||||
</v-tabs>
|
</v-tabs>
|
||||||
|
|
||||||
<v-tabs-items v-model="tab">
|
<v-window v-model="tab">
|
||||||
<v-tab-item key="this_svg_settings">
|
<v-window-item key="this_svg_settings">
|
||||||
<v-card flat>
|
<v-card flat>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">
|
<td class="label">
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{on, attrs}">
|
<template v-slot:activator="{ props }">
|
||||||
<label for="collapse_len_mm" v-on="on" v-bind="attrs"><translate>Minimum jump stitch length</translate></label>
|
<label for="collapse_len_mm" v-bind="props"><translate>Minimum jump stitch length</translate></label>
|
||||||
</template>
|
</template>
|
||||||
<label for="collapse_len_mm"><translate>Jump stitches smaller than this will be treated as normal stitches.</translate></label>
|
<label for="collapse_len_mm"><translate>Jump stitches smaller than this will be treated as normal stitches.</translate></label>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
@ -45,8 +54,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">
|
<td class="label">
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{on, attrs}">
|
<template v-slot:activator="{ props }">
|
||||||
<label for="min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Minimum stitch length</translate></label>
|
<label for="min_stitch_len_mm" v-bind="props"><translate>Minimum stitch length</translate></label>
|
||||||
</template>
|
</template>
|
||||||
<label for="min_stitch_len_mm"><translate>Drop stitches smaller than this value.</translate></label>
|
<label for="min_stitch_len_mm"><translate>Drop stitches smaller than this value.</translate></label>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
@ -66,16 +75,16 @@
|
||||||
</table>
|
</table>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-tab-item>
|
</v-window-item>
|
||||||
<v-tab-item key="global_settings">
|
<v-window-item key="global_settings">
|
||||||
<v-card flat>
|
<v-card flat>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{on, attrs}">
|
<template v-slot:activator="{ props }">
|
||||||
<label for="default_collapse_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum jump stitch length</translate></label>
|
<label for="default_collapse_len_mm" v-bind="props"><translate>Default minimum jump stitch length</translate></label>
|
||||||
</template>
|
</template>
|
||||||
<label for="default_collapse_len_mm"><translate>Used for new SVGs.</translate></label>
|
<label for="default_collapse_len_mm"><translate>Used for new SVGs.</translate></label>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
@ -90,8 +99,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{on, attrs}">
|
<template v-slot:activator="{ props }">
|
||||||
<label for="default_min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum stitch length</translate></label>
|
<label for="default_min_stitch_len_mm" v-bind="props"><translate>Default minimum stitch length</translate></label>
|
||||||
</template>
|
</template>
|
||||||
<label for="default_min_stitch_len_mm"><translate>Used for new SVGs.</translate></label>
|
<label for="default_min_stitch_len_mm"><translate>Used for new SVGs.</translate></label>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
@ -106,8 +115,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{on, attrs}">
|
<template v-slot:activator="{ props }">
|
||||||
<label for="cache_size" v-on="on" v-bind="attrs"><translate>Stitch plan cache size</translate></label>
|
<label for="cache_size" v-bind="props"><translate>Stitch plan cache size</translate></label>
|
||||||
</template>
|
</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>
|
<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>
|
</v-tooltip>
|
||||||
|
@ -125,8 +134,8 @@
|
||||||
</table>
|
</table>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-tab-item>
|
</v-window-item>
|
||||||
</v-tabs-items>
|
</v-window>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn text color="primary" @click="close"><translate>done</translate></v-btn>
|
<v-btn text color="primary" @click="close"><translate>done</translate></v-btn>
|
||||||
|
@ -136,8 +145,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const inkStitch = require("../../lib/api")
|
import { inkStitch } from '../../lib/api.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Preferences",
|
name: "Preferences",
|
||||||
data: function () {
|
data: function () {
|
||||||
|
@ -202,10 +210,11 @@ td.label {
|
||||||
td.preference {
|
td.preference {
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
max-width: 100px;
|
max-width: 15em;
|
||||||
|
min-width: 8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.preference::v-deep input {
|
td.preference :deep(input) {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<div class="window-controls">
|
<div class="window-controls">
|
||||||
<div ref="controlInfoButton" class="control-info-button" v-on:click="toggleInfo">
|
<div ref="controlInfoButton" class="control-info-button" v-on:click="toggleInfo">
|
||||||
<font-awesome-icon icon="info"/>
|
<font-awesome-icon icon="info"/>
|
||||||
<collapse-transition>
|
<Transition name="collapse">
|
||||||
<div class="control-info" v-show="infoExpanded" v-bind:style="{'max-height': infoMaxHeight + 'px'}">
|
<div class="control-info" v-show="infoExpanded" v-bind:style="{'max-height': infoMaxHeight + 'px'}">
|
||||||
<h1>
|
<h1>
|
||||||
<font-awesome-icon icon="info" class="info-icon"/>
|
<font-awesome-icon icon="info" class="info-icon"/>
|
||||||
|
@ -163,14 +163,14 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</collapse-transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
<div class="toggle-controls" v-on:click="toggleControls">
|
<div class="toggle-controls" v-on:click="toggleControls">
|
||||||
<font-awesome-icon v-if="controlsExpanded" icon="minus"/>
|
<font-awesome-icon v-if="controlsExpanded" icon="minus"/>
|
||||||
<font-awesome-icon v-else icon="plus"/>
|
<font-awesome-icon v-else icon="plus"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<collapse-transition>
|
<Transition name="collapse">
|
||||||
<div class="panel" v-show="controlsExpanded">
|
<div class="panel" v-show="controlsExpanded">
|
||||||
<fieldset class="controls">
|
<fieldset class="controls">
|
||||||
<legend>
|
<legend>
|
||||||
|
@ -203,7 +203,7 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="speed">
|
<fieldset class="speed">
|
||||||
<legend>
|
<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>
|
</legend>
|
||||||
<button v-on:click="animationSlowDown" :title="$gettext('Slow down (arrow down)')">
|
<button v-on:click="animationSlowDown" :title="$gettext('Slow down (arrow down)')">
|
||||||
<font-awesome-icon icon="hippo" size="2x" class="fa-button"/>
|
<font-awesome-icon icon="hippo" size="2x" class="fa-button"/>
|
||||||
|
@ -248,7 +248,7 @@
|
||||||
<input id="stop-checkbox" type="checkbox" v-model="showStops"/>
|
<input id="stop-checkbox" type="checkbox" v-model="showStops"/>
|
||||||
<label for="stop-checkbox"><font-awesome-icon icon="pause"/> <translate>stops</translate></label>
|
<label for="stop-checkbox"><font-awesome-icon icon="pause"/> <translate>stops</translate></label>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span class="npp">
|
||||||
<input id="npp-checkbox" type="checkbox" v-model="showNeedlePenetrationPoints"/>
|
<input id="npp-checkbox" type="checkbox" v-model="showNeedlePenetrationPoints"/>
|
||||||
<label for="npp-checkbox">
|
<label for="npp-checkbox">
|
||||||
<font-awesome-layers>
|
<font-awesome-layers>
|
||||||
|
@ -270,12 +270,11 @@
|
||||||
</span>
|
</span>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</collapse-transition>
|
</Transition>
|
||||||
<div class="slider-container">
|
<div class="slider-container">
|
||||||
<span>1</span>
|
<span>1</span>
|
||||||
<span class="slider-box">
|
<span class="slider-box">
|
||||||
<vue-slider
|
<vue-slider v-model="currentStitchDisplay"
|
||||||
:value="currentStitchDisplay"
|
|
||||||
@change="setCurrentStitch"
|
@change="setCurrentStitch"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="numStitches"
|
:max="numStitches"
|
||||||
|
@ -297,7 +296,7 @@
|
||||||
@focus="stop"/>
|
@focus="stop"/>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<loading :active.sync="loading" :is-full-page="false">
|
<loading :active="loading" :is-full-page="false">
|
||||||
<div class="loading">
|
<div class="loading">
|
||||||
<div class="loading-icon">
|
<div class="loading-icon">
|
||||||
<font-awesome-icon icon="spinner" size="4x" pulse/>
|
<font-awesome-icon icon="spinner" size="4x" pulse/>
|
||||||
|
|
|
@ -7,111 +7,68 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ES6
|
// ES6
|
||||||
import Vue from 'vue'
|
import { createApp } from 'vue'
|
||||||
import axios from 'axios'
|
import App from './App.vue'
|
||||||
|
|
||||||
import App from './App'
|
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {library} from '@fortawesome/fontawesome-svg-core'
|
import { fas } from '@fortawesome/free-solid-svg-icons'
|
||||||
import {
|
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
|
||||||
faAlignRight,
|
import { createGettext } from 'vue3-gettext'
|
||||||
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 translations from './assets/translations.json'
|
import translations from './assets/translations.json'
|
||||||
import {selectLanguage} from '../lib/i18n'
|
import { selectLanguage } from '../lib/i18n.js'
|
||||||
import Vuetify from 'vuetify'
|
|
||||||
import 'vuetify/dist/vuetify.min.css'
|
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
|
||||||
|
|
||||||
// We have to add to the library every icon we use anywhere in the UI.
|
import flaskserverport from '../lib/flaskserverport.json'
|
||||||
// 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
|
|
||||||
)
|
|
||||||
|
|
||||||
Vue.component('font-awesome-icon', FontAwesomeIcon)
|
import { createVuetify, ThemeDefinition } from 'vuetify'
|
||||||
Vue.component('font-awesome-layers', FontAwesomeLayers)
|
import * as components from 'vuetify/components'
|
||||||
|
import * as directives from 'vuetify/directives'
|
||||||
|
import 'vuetify/styles'
|
||||||
|
|
||||||
Vue.use(Transitions)
|
import VueMousetrapPlugin from 'vue-mousetrap'
|
||||||
Vue.use(GetTextPlugin, {
|
|
||||||
translations: translations,
|
|
||||||
defaultLanguage: selectLanguage(translations),
|
|
||||||
silent: true
|
|
||||||
})
|
|
||||||
|
|
||||||
Vue.http = Vue.prototype.$http = axios
|
if (flaskserverport.port === undefined) {
|
||||||
Vue.config.productionTip = false
|
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 inkStitchTheme = {
|
||||||
const vuetify = new Vuetify({
|
dark: false,
|
||||||
|
colors: {
|
||||||
|
primary: '#003399',
|
||||||
|
secondary: '#000000',
|
||||||
|
accent: '#8c9eff',
|
||||||
|
error: '#b71c1c',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const vuetify = new createVuetify({
|
||||||
|
components,
|
||||||
|
directives,
|
||||||
|
ssr: true,
|
||||||
theme: {
|
theme: {
|
||||||
|
defaultTheme: 'inkStitchTheme',
|
||||||
themes: {
|
themes: {
|
||||||
light: {
|
inkStitchTheme,
|
||||||
primary: '#003399',
|
}
|
||||||
secondary: '#000000',
|
}
|
||||||
accent: '#8c9eff',
|
|
||||||
error: '#b71c1c',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
library.add(fas)
|
||||||
new Vue({
|
const app = createApp(App)
|
||||||
vuetify,
|
app.component('font-awesome-icon', FontAwesomeIcon)
|
||||||
components: {App},
|
app.component('font-awesome-layers', FontAwesomeLayers)
|
||||||
router,
|
|
||||||
template: '<App/>'
|
app.use(createGettext({
|
||||||
}).$mount('#app')
|
defaultLanguage: selectLanguage(translations, theflaskport),
|
||||||
|
translations: translations,
|
||||||
|
silent: true,
|
||||||
|
setGlobalProperties: true,
|
||||||
|
}))
|
||||||
|
app.use(VueMousetrapPlugin)
|
||||||
|
app.use(vuetify)
|
||||||
|
app.use(router)
|
||||||
|
app.mount('#app')
|
||||||
|
|
|
@ -5,32 +5,32 @@
|
||||||
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
import { createWebHashHistory, createRouter } from 'vue-router'
|
||||||
import Vue from 'vue'
|
const routes = [
|
||||||
import Router from 'vue-router'
|
|
||||||
|
|
||||||
Vue.use(Router)
|
|
||||||
|
|
||||||
export default new Router({
|
|
||||||
routes: [
|
|
||||||
{
|
{
|
||||||
path: '/simulator',
|
path: '/simulator',
|
||||||
name: 'simulator',
|
name: 'simulator',
|
||||||
component: require('@/components/Simulator').default
|
component: () => import('../components/Simulator.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/install',
|
path: '/preferences',
|
||||||
name: 'install',
|
name: 'preferences',
|
||||||
component: require('@/components/InstallPalettes').default
|
component: () => import('../components/Preferences.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/preferences',
|
path: '/:pathMatch(.*)*',
|
||||||
name: 'preferences',
|
name: 'NotFound',
|
||||||
component: require('@/components/Preferences').default
|
component: () => import('../components/NotFound.vue')
|
||||||
},
|
},
|
||||||
{
|
]
|
||||||
path: '*',
|
const router = createRouter({
|
||||||
redirect: '/'
|
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
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"importHelpers": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"types": ["webpack-env"],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
},
|
||||||
|
"lib": ["ESNext", "DOM", "DOM.Iterable", "ScriptHost"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
11337
electron/yarn.lock
11337
electron/yarn.lock
Plik diff jest za duży
Load Diff
|
@ -22,7 +22,7 @@ AppUpdatesURL={#URL}
|
||||||
DefaultDirName={userappdata}\inkscape\extensions\
|
DefaultDirName={userappdata}\inkscape\extensions\
|
||||||
DefaultGroupName={#PROGRAMNAME}
|
DefaultGroupName={#PROGRAMNAME}
|
||||||
; Remove the following line to run in administrative install mode (install for all users.)
|
; Remove the following line to run in administrative install mode (install for all users.)
|
||||||
ArchitecturesAllowed=x64 x86
|
ArchitecturesAllowed=x64 x86 arm64
|
||||||
PrivilegesRequired=lowest
|
PrivilegesRequired=lowest
|
||||||
OutputBaseFilename=inkstitch
|
OutputBaseFilename=inkstitch
|
||||||
OutputDir=.
|
OutputDir=.
|
||||||
|
|
|
@ -1,55 +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.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from glob import glob
|
|
||||||
|
|
||||||
from flask import Blueprint, jsonify, request
|
|
||||||
|
|
||||||
from ..utils import get_bundled_dir, guess_inkscape_config_path
|
|
||||||
|
|
||||||
install = Blueprint('install', __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@install.route('/palettes', methods=["POST"])
|
|
||||||
def palettes():
|
|
||||||
try:
|
|
||||||
base_path = request.json.get('path') or guess_inkscape_config_path()
|
|
||||||
path = os.path.join(base_path, 'palettes')
|
|
||||||
src_dir = get_bundled_dir('palettes')
|
|
||||||
copy_files(glob(os.path.join(src_dir, "*")), path)
|
|
||||||
except Exception as exc:
|
|
||||||
return jsonify({"error": str(exc)}), 500
|
|
||||||
|
|
||||||
return jsonify({"status": "success"})
|
|
||||||
|
|
||||||
|
|
||||||
if sys.platform == "win32":
|
|
||||||
# If we try to just use shutil.copy it says the operation requires elevation.
|
|
||||||
def copy_files(files, dest):
|
|
||||||
import pythoncom
|
|
||||||
import winutils
|
|
||||||
|
|
||||||
pythoncom.CoInitialize()
|
|
||||||
|
|
||||||
if not os.path.exists(dest):
|
|
||||||
os.makedirs(dest)
|
|
||||||
|
|
||||||
winutils.copy(files, dest)
|
|
||||||
else:
|
|
||||||
def copy_files(files, dest):
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
if not os.path.exists(dest):
|
|
||||||
os.makedirs(dest)
|
|
||||||
|
|
||||||
for palette_file in files:
|
|
||||||
shutil.copy(palette_file, dest)
|
|
||||||
|
|
||||||
|
|
||||||
@install.route('/default-path')
|
|
||||||
def default_path():
|
|
||||||
return guess_inkscape_config_path()
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from flask import Blueprint, jsonify
|
||||||
|
|
||||||
|
languages = Blueprint('languages', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@languages.route('')
|
||||||
|
def get_lang():
|
||||||
|
languages = dict(os.environ)
|
||||||
|
return jsonify(languages)
|
|
@ -15,16 +15,22 @@ def get_page_specs():
|
||||||
height = svg.get('height', 0)
|
height = svg.get('height', 0)
|
||||||
pagecolor = "white"
|
pagecolor = "white"
|
||||||
deskcolor = "white"
|
deskcolor = "white"
|
||||||
|
bordercolor = "black"
|
||||||
|
showpageshadow = True
|
||||||
|
|
||||||
namedview = svg.namedview
|
namedview = svg.namedview
|
||||||
if namedview is not None:
|
if namedview is not None:
|
||||||
pagecolor = namedview.get('pagecolor', pagecolor)
|
pagecolor = namedview.get('pagecolor', pagecolor)
|
||||||
deskcolor = namedview.get('inkscape:deskcolor', deskcolor)
|
deskcolor = namedview.get('inkscape:deskcolor', deskcolor)
|
||||||
|
bordercolor = namedview.get('bordercolor', bordercolor)
|
||||||
|
showpageshadow = namedview.get('inkscape:showpageshadow', showpageshadow)
|
||||||
|
|
||||||
page_specs = {
|
page_specs = {
|
||||||
"width": width,
|
"width": width,
|
||||||
"height": height,
|
"height": height,
|
||||||
"pagecolor": pagecolor,
|
"pagecolor": pagecolor,
|
||||||
"deskcolor": deskcolor
|
"deskcolor": deskcolor,
|
||||||
|
"bordercolor": bordercolor,
|
||||||
|
"showpageshadow": showpageshadow
|
||||||
}
|
}
|
||||||
return jsonify(page_specs)
|
return jsonify(page_specs)
|
||||||
|
|
|
@ -9,17 +9,20 @@ import socket
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from flask import Flask, g
|
from flask import Flask, g
|
||||||
from werkzeug.serving import make_server
|
from werkzeug.serving import make_server
|
||||||
|
|
||||||
from ..utils.json import InkStitchJSONProvider
|
from ..utils.json import InkStitchJSONProvider
|
||||||
from .install import install
|
|
||||||
from .simulator import simulator
|
from .simulator import simulator
|
||||||
from .stitch_plan import stitch_plan
|
from .stitch_plan import stitch_plan
|
||||||
from .preferences import preferences
|
from .preferences import preferences
|
||||||
from .page_specs import page_specs
|
from .page_specs import page_specs
|
||||||
|
from .lang import languages
|
||||||
|
# this for electron axios
|
||||||
|
from flask_cors import CORS
|
||||||
|
|
||||||
|
|
||||||
class APIServer(Thread):
|
class APIServer(Thread):
|
||||||
|
@ -42,13 +45,14 @@ class APIServer(Thread):
|
||||||
cli.show_server_banner = lambda *x: None
|
cli.show_server_banner = lambda *x: None
|
||||||
|
|
||||||
self.app = Flask(__name__)
|
self.app = Flask(__name__)
|
||||||
|
CORS(self.app)
|
||||||
self.app.json = InkStitchJSONProvider(self.app)
|
self.app.json = InkStitchJSONProvider(self.app)
|
||||||
|
|
||||||
self.app.register_blueprint(simulator, url_prefix="/simulator")
|
self.app.register_blueprint(simulator, url_prefix="/simulator")
|
||||||
self.app.register_blueprint(stitch_plan, url_prefix="/stitch_plan")
|
self.app.register_blueprint(stitch_plan, url_prefix="/stitch_plan")
|
||||||
self.app.register_blueprint(install, url_prefix="/install")
|
|
||||||
self.app.register_blueprint(preferences, url_prefix="/preferences")
|
self.app.register_blueprint(preferences, url_prefix="/preferences")
|
||||||
self.app.register_blueprint(page_specs, url_prefix="/page_specs")
|
self.app.register_blueprint(page_specs, url_prefix="/page_specs")
|
||||||
|
self.app.register_blueprint(languages, url_prefix="/languages")
|
||||||
|
|
||||||
@self.app.before_request
|
@self.app.before_request
|
||||||
def store_extension():
|
def store_extension():
|
||||||
|
@ -67,25 +71,21 @@ class APIServer(Thread):
|
||||||
def disable_logging(self):
|
def disable_logging(self):
|
||||||
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
# https://github.com/aluo-x/Learning_Neural_Acoustic_Fields/blob/master/train.py
|
||||||
|
# https://github.com/pytorch/pytorch/issues/71029
|
||||||
|
def find_free_port(self):
|
||||||
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
||||||
|
s.bind(('localhost', 0))
|
||||||
|
return s.getsockname()[1]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.disable_logging()
|
self.disable_logging()
|
||||||
|
|
||||||
self.host = "127.0.0.1"
|
self.host = "127.0.0.1"
|
||||||
self.port = 5000
|
self.port = self.find_free_port()
|
||||||
|
self.flask_server = make_server(self.host, self.port, self.app)
|
||||||
while True:
|
self.server_thread = Thread(target=self.flask_server.serve_forever)
|
||||||
try:
|
self.server_thread.start()
|
||||||
self.flask_server = make_server(self.host, self.port, self.app)
|
|
||||||
self.server_thread = Thread(target=self.flask_server.serve_forever)
|
|
||||||
self.server_thread.start()
|
|
||||||
except socket.error as e:
|
|
||||||
if e.errno == errno.EADDRINUSE:
|
|
||||||
self.port += 1
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
def ready_checker(self):
|
def ready_checker(self):
|
||||||
"""Wait until the server is started.
|
"""Wait until the server is started.
|
||||||
|
|
|
@ -4,18 +4,48 @@
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
from .base import InkstitchExtension
|
from .base import InkstitchExtension
|
||||||
from ..api import APIServer
|
import os
|
||||||
from ..gui import open_url
|
import sys
|
||||||
|
from glob import glob
|
||||||
|
from ..utils import get_bundled_dir, guess_inkscape_config_path
|
||||||
|
from inkex import errormsg
|
||||||
|
from ..i18n import _
|
||||||
|
|
||||||
|
|
||||||
class Install(InkstitchExtension):
|
class Install(InkstitchExtension):
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
InkstitchExtension.__init__(self)
|
InkstitchExtension.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def effect(self):
|
def effect(self):
|
||||||
api_server = APIServer(self)
|
path = os.path.join(guess_inkscape_config_path(), 'palettes')
|
||||||
port = api_server.start_server()
|
src_dir = get_bundled_dir('palettes')
|
||||||
electron = open_url("/install?port=%d" % port)
|
try:
|
||||||
electron.wait()
|
copy_files(glob(os.path.join(src_dir, "*")), path)
|
||||||
api_server.stop()
|
errormsg(_("Successfully installed color palettes for Inkscape.\n\n"
|
||||||
api_server.join()
|
"Please restart Inkscape."))
|
||||||
|
except IOError:
|
||||||
|
errormsg(_("Could not install color palettes. Please file an issue on "
|
||||||
|
"https://github.com/inkstitch/inkstitch/issues"))
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
# If we try to just use shutil.copy it says the operation requires elevation.
|
||||||
|
def copy_files(files, dest):
|
||||||
|
import pythoncom
|
||||||
|
import winutils
|
||||||
|
|
||||||
|
pythoncom.CoInitialize()
|
||||||
|
|
||||||
|
if not os.path.exists(dest):
|
||||||
|
os.makedirs(dest)
|
||||||
|
|
||||||
|
winutils.copy(files, dest)
|
||||||
|
else:
|
||||||
|
def copy_files(files, dest):
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
if not os.path.exists(dest):
|
||||||
|
os.makedirs(dest)
|
||||||
|
|
||||||
|
for palette_file in files:
|
||||||
|
shutil.copy(palette_file, dest)
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Preferences(InkstitchExtension):
|
||||||
def effect(self):
|
def effect(self):
|
||||||
api_server = APIServer(self)
|
api_server = APIServer(self)
|
||||||
port = api_server.start_server()
|
port = api_server.start_server()
|
||||||
electron = open_url("/preferences?port=%d" % port)
|
electron = open_url("/preferences", port)
|
||||||
electron.wait()
|
electron.wait()
|
||||||
api_server.stop()
|
api_server.stop()
|
||||||
api_server.join()
|
api_server.join()
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# Copyright (c) 2010 Authors
|
# Copyright (c) 2010 Authors
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
import errno
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -13,6 +12,7 @@ import time
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
import appdirs
|
import appdirs
|
||||||
from flask import Flask, Response, jsonify, request, send_from_directory
|
from flask import Flask, Response, jsonify, request, send_from_directory
|
||||||
|
@ -162,25 +162,24 @@ class PrintPreviewServer(Thread):
|
||||||
def disable_logging(self):
|
def disable_logging(self):
|
||||||
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
# https://github.com/aluo-x/Learning_Neural_Acoustic_Fields/blob/master/train.py
|
||||||
|
# https://github.com/pytorch/pytorch/issues/71029
|
||||||
|
def find_free_port(self):
|
||||||
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
||||||
|
s.bind(('localhost', 0))
|
||||||
|
return s.getsockname()[1]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.disable_logging()
|
self.disable_logging()
|
||||||
|
|
||||||
self.host = "127.0.0.1"
|
self.host = "127.0.0.1"
|
||||||
self.port = 5000
|
self.port = self.find_free_port()
|
||||||
|
# exporting the port number for languages to work in electron vuejs part of inkstitch
|
||||||
|
os.environ['FLASKPORT'] = str(self.port)
|
||||||
|
|
||||||
while True:
|
self.flask_server = make_server(self.host, self.port, self.app)
|
||||||
try:
|
self.server_thread = Thread(target=self.flask_server.serve_forever)
|
||||||
self.flask_server = make_server(self.host, self.port, self.app)
|
self.server_thread.start()
|
||||||
self.server_thread = Thread(target=self.flask_server.serve_forever)
|
|
||||||
self.server_thread.start()
|
|
||||||
except socket.error as e:
|
|
||||||
if e.errno == errno.EADDRINUSE:
|
|
||||||
self.port += 1
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
class Print(InkstitchExtension):
|
class Print(InkstitchExtension):
|
||||||
|
@ -331,13 +330,12 @@ class Print(InkstitchExtension):
|
||||||
realistic_color_block_svgs=realistic_color_block_svgs
|
realistic_color_block_svgs=realistic_color_block_svgs
|
||||||
)
|
)
|
||||||
print_server.start()
|
print_server.start()
|
||||||
|
|
||||||
# Wait for print_server.host and print_server.port to be populated.
|
# Wait for print_server.host and print_server.port to be populated.
|
||||||
# Hacky, but Flask doesn't have an option for a callback to be run
|
# Hacky, but Flask doesn't have an option for a callback to be run
|
||||||
# after startup.
|
# after startup.
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
browser_window = open_url("http://%s:%s/" % (print_server.host, print_server.port))
|
browser_window = open_url(print_server.host, print_server.port, True)
|
||||||
browser_window.wait()
|
browser_window.wait()
|
||||||
print_server.stop()
|
print_server.stop()
|
||||||
print_server.join()
|
print_server.join()
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Simulator(InkstitchExtension):
|
||||||
return
|
return
|
||||||
api_server = APIServer(self)
|
api_server = APIServer(self)
|
||||||
port = api_server.start_server()
|
port = api_server.start_server()
|
||||||
electron = open_url("/simulator?port=%d" % port)
|
electron = open_url("/simulator", port)
|
||||||
electron.wait()
|
electron.wait()
|
||||||
api_server.stop()
|
api_server.stop()
|
||||||
api_server.join()
|
api_server.join()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Copyright (c) 2010 Authors
|
# Copyright (c) 2010 Authors
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
@ -12,11 +13,27 @@ from ..utils import get_bundled_dir
|
||||||
app_process = None
|
app_process = None
|
||||||
|
|
||||||
|
|
||||||
def open_url(url):
|
def open_url(url, port, pdf=False): # noqa: C901
|
||||||
global app
|
global app
|
||||||
|
|
||||||
command = []
|
if not pdf:
|
||||||
|
url = f'{url}?port={port}'
|
||||||
|
os.environ['FLASKPORT'] = str(port)
|
||||||
|
|
||||||
|
# this creates the .json for dev mode to get translations
|
||||||
|
if getattr(sys, 'frozen', None) is None:
|
||||||
|
dynamic_port = {
|
||||||
|
"_comment1": "port should not be declared when commiting",
|
||||||
|
"port": port,
|
||||||
|
}
|
||||||
|
port_object = json.dumps(dynamic_port, indent=1)
|
||||||
|
with open(os.path.join("electron/src/lib/flaskserverport.json"), "w") as outfile:
|
||||||
|
outfile.write(port_object)
|
||||||
|
else:
|
||||||
|
url = f'http://{url}:{port}/'
|
||||||
|
|
||||||
cwd = None
|
cwd = None
|
||||||
|
searchstring = "http"
|
||||||
|
|
||||||
if getattr(sys, 'frozen', None) is not None:
|
if getattr(sys, 'frozen', None) is not None:
|
||||||
electron_path = os.path.join(get_bundled_dir("electron"), "inkstitch-gui")
|
electron_path = os.path.join(get_bundled_dir("electron"), "inkstitch-gui")
|
||||||
|
@ -42,8 +59,33 @@ def open_url(url):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
mac_dev_env["PATH"] = yarn_path + mac_dev_env["PATH"]
|
mac_dev_env["PATH"] = yarn_path + mac_dev_env["PATH"]
|
||||||
|
# checking URL for flask server address for printToPDF
|
||||||
|
if searchstring in url:
|
||||||
|
with open(os.devnull, 'w') as null:
|
||||||
|
subprocess.Popen(["yarn", "just-build"], cwd=cwd, stdout=null, env=mac_dev_env).wait()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
with open(os.devnull, 'w') as null:
|
with open(os.devnull, 'w') as null:
|
||||||
return subprocess.Popen(command, cwd=cwd, stdout=null, env=mac_dev_env)
|
return subprocess.Popen(command, cwd=cwd, stdout=null, env=mac_dev_env)
|
||||||
else:
|
else:
|
||||||
with open(os.devnull, 'w') as null:
|
if searchstring in url and getattr(sys, 'frozen', None) is None:
|
||||||
return subprocess.Popen(command, cwd=cwd, stdout=null)
|
with open(os.devnull, 'w') as null:
|
||||||
|
subprocess.Popen(["yarn", "just-build"], cwd=cwd, stdout=null).wait()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
if sys.platform == "linux":
|
||||||
|
# Pyinstaller fix for gnome document view not opening.
|
||||||
|
lenv = dict(os.environ)
|
||||||
|
lp_key = 'LD_LIBRARY_PATH'
|
||||||
|
lp_orig = lenv.get(lp_key + '_ORIG')
|
||||||
|
if lp_orig is not None:
|
||||||
|
lenv[lp_key] = lp_orig # restore the original, unmodified value
|
||||||
|
else:
|
||||||
|
lenv.pop(lp_key, None)
|
||||||
|
|
||||||
|
with open(os.devnull, 'w') as null:
|
||||||
|
return subprocess.Popen(command, cwd=cwd, stdout=null, env=lenv)
|
||||||
|
else:
|
||||||
|
with open(os.devnull, 'w') as null:
|
||||||
|
return subprocess.Popen(command, cwd=cwd, stdout=null)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
var electron = require('electron');
|
|
||||||
|
|
||||||
$.postJSON = function(url, data, success=null) {
|
$.postJSON = function(url, data, success=null) {
|
||||||
return $.ajax(url, {
|
return $.ajax(url, {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
|
@ -378,14 +376,14 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button.print').click(function() {
|
$('button.print').click(function() {
|
||||||
var pageSize = $('select#printing-size').find(':selected').text();
|
var pageSize = $('select#printing-size').find(':selected').text();
|
||||||
electron.ipcRenderer.send('open-pdf', pageSize)
|
window.inkstitchAPI.openpdf(pageSize)
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button.save-pdf').click(function() {
|
$('button.save-pdf').click(function() {
|
||||||
var pageSize = $('select#printing-size').find(':selected').text();
|
var pageSize = $('select#printing-size').find(':selected').text();
|
||||||
electron.ipcRenderer.send('save-pdf', pageSize)
|
window.inkstitchAPI.savepdf(pageSize)
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button.settings').click(function(){
|
$('button.settings').click(function(){
|
||||||
$('#settings-ui').show();
|
$('#settings-ui').show();
|
||||||
|
|
|
@ -27,6 +27,6 @@ fonttools
|
||||||
trimesh>=3.15.2
|
trimesh>=3.15.2
|
||||||
scipy
|
scipy
|
||||||
diskcache
|
diskcache
|
||||||
|
flask-cors
|
||||||
pywinutils ; sys_platform == 'win32'
|
pywinutils ; sys_platform == 'win32'
|
||||||
pywin32 ; sys_platform == 'win32'
|
pywin32 ; sys_platform == 'win32'
|
||||||
|
|
Ładowanie…
Reference in New Issue