Update electron version to v14.2.9 (#2214)

Authored-by: rejbasket
Co-authored-by: Kaalleen
Co-authored-by: Lex Neva
pull/2316/head
rejbasket 2023-05-22 22:33:19 +02:00 zatwierdzone przez GitHub
rodzic da54f104e6
commit ef6f6580df
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
72 zmienionych plików z 1457 dodań i 13020 usunięć

Wyświetl plik

@ -182,8 +182,8 @@ jobs:
echo "${{ env.pythonLocation }}/bin" >> $GITHUB_PATH
- shell: bash
run: |
# disable electron-builder signing
#export CSC_IDENTITY_AUTO_DISCOVERY=false
# disable electron-builder signing and make dist
export CSC_IDENTITY_AUTO_DISCOVERY=false
make dist
env:
BUILD: osx

2
.gitignore vendored
Wyświetl plik

@ -24,3 +24,5 @@ locales/
/profile_stats.prof
/.vscode
__pycache__
flaskserverport.json
electron/yarn.lock

Wyświetl plik

@ -1,10 +1,19 @@
# used for distlocal
OS=$(shell uname)
dist: version locales inx
python bin/generate-flaskserverport-file
bash bin/build-python
bash bin/build-electron
bash bin/build-distribution-archives
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
inx: version locales

Wyświetl plik

@ -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)}"
ARCH="$(uname -m)"
mkdir artifacts
@ -6,7 +6,7 @@ mkdir artifacts
if [ "$BUILD" = "osx" ]; then
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
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/
# Install location for pkgbuild
PKG_INSTALL_PATH="/tmp/inkstitch/"

Wyświetl plik

@ -2,15 +2,6 @@
set -e
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
args="-w --ia32"

Wyświetl plik

@ -2,26 +2,6 @@
set -e
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
# libraries if we develop a GUI application for Mac:
@ -29,9 +9,6 @@ if [ "$BUILD" = "osx" -o "$BUILD" = "windows" ]; then
pyinstaller_args+="--windowed "
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
pyinstaller_args+="--log-level DEBUG "
@ -67,7 +44,7 @@ if [ "$BUILD" = "windows" ]; then
pyinstaller_args+="--version-file installer_scripts/file_version_info.txt "
python -m PyInstaller $pyinstaller_args inkstitch.py
else
LD_LIBRARY_PATH="${site_packages}/wx" python -m PyInstaller $pyinstaller_args --strip inkstitch.py;
python -m PyInstaller $pyinstaller_args --strip inkstitch.py;
fi
# pyinstaller put a whole mess of libraries under dist/inkstitch. We'd like

2
bin/build-windows-installer 100644 → 100755
Wyświetl plik

@ -1,5 +1,5 @@
#!/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)}"
# Create windows installer
mkdir win

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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"]
}

Wyświetl plik

@ -0,0 +1,4 @@
# https://github.com/browserslist/browserslist#queries
> 1%
last 2 versions
not dead

Wyświetl plik

@ -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"
}
}
}
}

Wyświetl plik

@ -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()
}

Wyświetl plik

@ -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>
`
}
})

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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
}
}

Wyświetl plik

@ -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
}
}

1
electron/.gitattributes vendored 100644
Wyświetl plik

@ -0,0 +1 @@
* text=auto eol=lf

Wyświetl plik

@ -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/],
}

Wyświetl plik

@ -4,10 +4,12 @@
"version": "11.99.11",
"description": "Ink/Stitch GUI",
"main": "./dist/electron/main.js",
"private": true,
"scripts": {
"pack": "electron-builder --dir",
"dist": "node .electron-vue/build.js && electron-builder",
"dev": "node --openssl-legacy-provider .electron-vue/dev-runner.js"
"dev": "node service/commands/dev.js",
"just-build": "node service/commands/build.js && node service/commands/build-main.js",
"dist": "yarn just-build && electron-builder",
"print": "yarn just-build && yarn dev"
},
"build": {
"productName": "inkstitch-gui",
@ -22,10 +24,7 @@
"icon": "build/icons",
"target": [
{
"target": "dir",
"arch": [
"CPU_ARCH"
]
"target": "dir"
}
]
},
@ -37,10 +36,7 @@
"icon": "build/icons/mac/inkstitch.icns",
"target": [
{
"target": "dir",
"arch": [
"CPU_ARCH"
]
"target": "dir"
}
],
"hardenedRuntime": true,
@ -54,78 +50,70 @@
"author": "lex",
"license": "GPL-3.0-or-later",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.22",
"@fortawesome/free-solid-svg-icons": "^5.10.2",
"@fortawesome/vue-fontawesome": "^0.1.6",
"@mdi/font": "^5.5.55",
"@svgdotjs/svg.filter.js": "^3.0.7",
"@svgdotjs/svg.js": "^3.0.16",
"@svgdotjs/svg.panzoom.js": "https://github.com/inkstitch/svg.panzoom.js",
"axios": "^0.19.0",
"electron-compile": "^6.4.4",
"@babel/plugin-transform-runtime": "^7.21.0",
"@babel/runtime": "^7.17.9",
"@fortawesome/fontawesome-svg-core": "^6.1.1",
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/vue-fontawesome": "^3.0.0-5",
"@svgdotjs/svg.filter.js": "^3.0.8",
"@svgdotjs/svg.js": "^3.1.2",
"@svgdotjs/svg.panzoom.js": "^2.1.2",
"axios": "^0.27.2",
"core-js": "^3.22.2",
"lodash.throttle": "^4.1.1",
"mousetrap": "^1.6.3",
"query-string": "^6.8.2",
"svgpath": "^2.2.3",
"tmp": "0.1.0",
"vue": "^2.5.16",
"vue-gettext": "^2.1.5",
"vue-loading-overlay": "^3.2.0",
"vue-router": "^3.0.1",
"vue-slider-component": "^3.0.38",
"vue2-transitions": "^0.3.0",
"vuetify": "^2.3.9"
"node-polyfill-webpack-plugin": "^2.0.1",
"query-string": "^7.1.1",
"svgpath": "^2.5.0",
"vue": "^3.2.33",
"vue-loading-overlay": "^5.0",
"vue-mousetrap": "^1.0.5",
"vue-router": "4",
"vue-slider-component": "^4.1.0-beta.0",
"vue3-gettext": "^2.2.3",
"vue3-transitions": "^1.0.0",
"vuetify": "^3.1.7",
"webpack-plugin-vuetify": "^2.0.1"
},
"devDependencies": {
"ajv": "^6.5.0",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"babili-webpack-plugin": "^0.1.2",
"cfonts": "^2.1.2",
"chalk": "^2.4.1",
"copy-webpack-plugin": "^4.5.1",
"cross-env": "^5.1.6",
"css-loader": "^0.28.11",
"@babel/core": "^7.17.9",
"@babel/preset-env": "^7.16.11",
"@types/webpack-env": "^1.16.4",
"@vue/compiler-sfc": "^3.2.33",
"autoprefixer": "^10.4.5",
"babel-loader": "^8.2.5",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"chalk": "^4.1.2",
"copy-webpack-plugin": "^10.2.4",
"css-loader": "^6.7.1",
"deepmerge": "^4.2.2",
"del": "^3.0.0",
"devtron": "^1.4.0",
"easygettext": "^2.7.0",
"electron": "4.1.3",
"dotenv": "^16.0.0",
"dotenv-expand": "^8.0.3",
"electron": "14.2.9",
"electron-builder": "^23.0.3",
"electron-debug": "^1.5.0",
"electron-devtools-installer": "^2.2.4",
"electron-prebuilt-compile": "4.0.0",
"eslint": "^4.19.1",
"eslint-config-standard": "^11.0.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-html": "^4.0.3",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-standard": "^3.1.0",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "0.4.0",
"multispinner": "^0.2.1",
"node-loader": "^0.6.0",
"sass": "^1.26.10",
"sass-loader": "^9.0.3",
"style-loader": "^0.21.0",
"url-loader": "^1.0.1",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.2.4",
"vue-style-loader": "^4.1.0",
"vue-template-compiler": "^2.5.16",
"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"
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.0",
"ora": "^5.4.1",
"postcss": "^8.4.12",
"postcss-html": "^1.4.1",
"postcss-loader": "^6.2.1",
"rimraf": "^3.0.2",
"sass": "~1.32",
"sass-loader": "^13.0.0",
"strip-ansi": "^6.0.0",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.1",
"thread-loader": "^3.0.4",
"ts-loader": "^9.2.8",
"typescript": "^4.6.3",
"url-loader": "^4.1.1",
"vue-loader": "^17.0.0",
"vue-style-loader": "^4.1.3",
"wait-on": "^6.0.1",
"webpack": "^5.72.0",
"webpack-dev-server": "^4.8.1",
"webpack-merge": "^5.8.0"
},
"engines": {
"node": ">=12.13.0"
}
}

Wyświetl plik

@ -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')
})

Wyświetl plik

@ -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')
})
})

Wyświetl plik

@ -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)
}
})

Wyświetl plik

@ -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]' },
},
],
},
}

Wyświetl plik

@ -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(),
},
}

Wyświetl plik

@ -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,
},
})

Wyświetl plik

@ -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,
},
},
],
},
],
},
}
)

Wyświetl plik

@ -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,
},
},
},
},
})

Wyświetl plik

@ -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'],
})

Wyświetl plik

@ -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,
})

Wyświetl plik

@ -0,0 +1,16 @@
'use strict'
module.exports = {
// orginal was dist
outputDir: 'dist/electron',
dev: {
publicPath: '/',
port: 8080,
},
build: {
// orginal was /
publicPath: './',
},
}

Wyświetl plik

@ -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
}
}
}
}

Wyświetl plik

@ -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
}
}
}

Wyświetl plik

@ -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)
}
}
}

Wyświetl plik

@ -0,0 +1,6 @@
'use strict'
const path = require('path')
// gen absolute path
exports.resolve = (...args) => path.posix.join(process.cwd(), ...args)

Wyświetl plik

@ -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
}
}

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -6,11 +6,19 @@
*
*/
const axios = require('axios')
const queryString = require('query-string')
import axios from 'axios';
import flaskserverport from './flaskserverport.json'
var port = queryString.parse(global.location.search).port
if (flaskserverport.port === undefined) {
var theflaskport = window.inkstitchAPI.flaskport()
console.log("Installed mode")
console.log(theflaskport)
} else {
var theflaskport = flaskserverport.port
console.log("Dev mode")
console.log(theflaskport)
}
module.exports = axios.create({
baseURL: `http://127.0.0.1:${port}/`
export const inkStitch = axios.create({
baseURL: `http://127.0.0.1:${theflaskport}`
})

Wyświetl plik

@ -6,22 +6,33 @@
*
*/
module.exports.selectLanguage = function (translations) {
export function selectLanguage(translations, flaskport) {
var port = flaskport
// get language from flask server, process in modern electron isn't exposed to renderer
const request = new XMLHttpRequest();
request.open('GET', `http://127.0.0.1:${port}/languages`, false)
request.send(null)
var process = undefined
if (request.status === 200) {
process = JSON.parse(request.responseText)
}
// get a list of available translations
var availableTranslations = ['en_US'];
for(var k in translations) availableTranslations.push(k);
for (var k in translations) availableTranslations.push(k);
var lang = undefined;
// get system language / Inkscape language
['LANG', 'LC_MESSAGES', 'LC_ALL', 'LANGUAGE'].forEach(language => {
if (process.env[language]) {
if (process[language]) {
// split encoding information, we don't need it
var current_lang = process.env[language].split(".")[0];
var current_lang = process[language].split('.')[0];
if (current_lang.length == 2) {
// current language has only two letters (e.g. en),
// compare with available languages and if present, set to a long locale name (e.g. en_US)
lang = availableTranslations.find(elem => elem.startsWith(current_lang));
lang = availableTranslations.find((elem) => elem.startsWith(current_lang));
} else {
lang = current_lang;
}
@ -33,3 +44,4 @@ module.exports.selectLanguage = function (translations) {
}
return lang
}

Wyświetl plik

@ -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')

Wyświetl plik

@ -8,113 +8,104 @@
'use strict'
import {app, BrowserWindow, ipcMain, dialog, shell} from 'electron'
var fs = require('fs');
var path = require('path');
var tmp = require('tmp');
const path = require('path')
const fs = require('fs')
const tmp = require('tmp')
const url = require('url')
const { app, BrowserWindow, ipcMain, dialog, shell, Menu} = require('electron')
// url for printPDF flask server which is used in development and production mode
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
*/
if (process.env.NODE_ENV === 'development') {
// we were run as electron --inspect=5858 path/to/main.js <args>
// so get rid of the first two args
console.log("args " + process.argv)
process.argv.shift()
process.argv.shift()
var port = process.env.FLASKPORT
const printPdfUrl = `http://127.0.0.1:${port}/`
const isDev = process.env.BABEL_ENV === 'development'
var target = null
// Finds this url in the argv array and sets to target value
if (process.argv.includes(printPdfUrl)) {
target = printPdfUrl
} 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 winURL = null;
var winURL = null
// Print PDF will give us a full URL to a flask server, bypassing Vue entirely.
// Eventually this will be migrated to Vue.
if (targetURL.protocol) {
winURL = target
winURL = target
} else {
if (process.env.NODE_ENV === 'development') {
winURL = `http://localhost:9080/?${targetURL.query || ""}#${targetURL.pathname || ""}`
} else {
winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}`;
}
winURL = `file://${__dirname}/index.html?${targetURL.query || ""}#${targetURL.pathname || ""}`
}
function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
webPreferences: {nodeIntegration: true}
})
mainWindow.loadURL(winURL)
mainWindow.maximize()
mainWindow.on('closed', () => {
mainWindow = null
})
const mainWindow = new BrowserWindow({
useContentSize: true,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false,
contextIsolation: true,
},
})
if (isDev) {
// printPDF in development mode will have dev tools activated
// Vuejs parts of Ink/Stich will not and dev tools must be accessed though the menu of electron window
mainWindow.loadURL(winURL)
mainWindow.webContents.openDevTools()
} else {
mainWindow.loadURL(winURL)
}
// This will remove the menu from the release, in dev mode the menu is available.
if(process.platform === "darwin" && !isDev) {
Menu.setApplicationMenu(Menu.buildFromTemplate([]));
} if(process.platform === "win32" || process.platform === "linux" && !isDev) {
mainWindow.removeMenu();
}
mainWindow.maximize()
// save to PDF
ipcMain.on('save-pdf', (event, pageSize) => {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
const saveOpt = {
title: "Save PDF",
defaultPath: "Inkstitch.pdf",
bookmark: "true",
}
win.webContents.printToPDF({}).then(pageSize => {
dialog.showSaveDialog(saveOpt).then(filename => {
const { filePath } = filename;
fs.writeFileSync(filePath, pageSize, (error) => {
if (error) {
throw error
}
console.log(`Wrote PDF successfully to ${pdfPath}`)
})
}).catch(error => {
console.log(`Failed to write PDF to ${pdfPath}: `, error)
})
})
})
// 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.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()
})
*/

Wyświetl plik

@ -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,
})

Wyświetl plik

@ -9,20 +9,9 @@
<template>
<div id="app">
<v-app>
<v-main>
<router-view></router-view>
</v-main>
</v-app>
</div>
</template>
<script>
export default {
name: 'my-project'
}
</script>
<style>
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons');
</style>

Wyświetl plik

@ -5,19 +5,18 @@
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
*
*/
import { inkStitch } from '../../../lib/api.js'
const inkStitch = require("../../../lib/api")
const Mousetrap = require("mousetrap")
import { SVG } from '@svgdotjs/svg.js'
require('@svgdotjs/svg.panzoom.js/src/svg.panzoom.js')
require('@svgdotjs/svg.filter.js')
const svgpath = require('svgpath')
import '@svgdotjs/svg.panzoom.js'
import '@svgdotjs/svg.filter.js'
import svgpath from 'svgpath'
import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';
import { reactive, toRefs } from 'vue'
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
const throttle = require('lodash.throttle')
import 'vue-slider-component/theme/antd.css'
import throttle from 'lodash/throttle'
function SliderMark(command, icon) {
this.label = ""
@ -31,6 +30,10 @@ export default {
Loading,
VueSlider
},
setup() {
const data = reactive({ value: 0 })
return toRefs(data)
},
data: function () {
return {
loading: false,
@ -511,15 +514,23 @@ export default {
},
generatePage () {
this.$refs.simulator.style.backgroundColor = this.page_specs.deskcolor
let page = this.svg.rect(this.page_specs.width, this.page_specs.height)
.move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1])
.fill(this.page_specs.pagecolor)
.stroke({width: 1, color: 'black'})
.filterWith(add => {
let blur = add.offset(2,2).in(add.$sourceAlpha).gaussianBlur(2)
add.blend(add.$source, blur)
})
.stroke({width: 0.1, color: this.page_specs.bordercolor})
.back()
if (this.page_specs.showpageshadow === "true") {
let shadow = this.svg.rect(this.page_specs.width, this.page_specs.height)
.move(-this.stitchPlan.bounding_box[0],-this.stitchPlan.bounding_box[1])
.fill(this.page_specs.bordercolor)
.filterWith(add => {
let blur = add.offset(.5,.5).in(add.$source).gaussianBlur(.5)
})
.back()
}
this.page_specs["bbox"] = page.bbox()
},
zoomDesign () {
@ -606,29 +617,30 @@ export default {
this.generateColorSections()
this.generateScale()
this.generateCursor()
this.resizeCursor()
this.loading = false
// v-on:keydown doesn't seem to work, maybe an Electron issue?
Mousetrap.bind("up", this.animationSpeedUp)
Mousetrap.bind("down", this.animationSlowDown)
Mousetrap.bind("left", this.animationReverse)
Mousetrap.bind("right", this.animationForward)
Mousetrap.bind("pagedown", this.animationPreviousCommand)
Mousetrap.bind("pageup", this.animationNextCommand)
Mousetrap.bind("space", this.toggleAnimation)
Mousetrap.bind("+", this.animationForwardOneStitch)
Mousetrap.bind("-", this.animationBackwardOneStitch)
Mousetrap.bind("]", this.zoomDesign)
Mousetrap.bind("[", this.zoomPage)
this.$mousetrap.bind("up", this.animationSpeedUp)
this.$mousetrap.bind("down", this.animationSlowDown)
this.$mousetrap.bind("left", this.animationReverse)
this.$mousetrap.bind("right", this.animationForward)
this.$mousetrap.bind("pagedown", this.animationPreviousCommand)
this.$mousetrap.bind("pageup", this.animationNextCommand)
this.$mousetrap.bind("space", this.toggleAnimation)
this.$mousetrap.bind("+", this.animationForwardOneStitch)
this.$mousetrap.bind("-", this.animationBackwardOneStitch)
this.$mousetrap.bind("]", this.zoomDesign)
this.$mousetrap.bind("[", this.zoomPage)
this.svg.on('zoom', this.resizeCursor)
this.resizeCursor()
inkStitch.get('page_specs').then(response => {
this.page_specs = response.data
this.generatePage()
})
this.start()
})
}

Wyświetl plik

@ -5,11 +5,10 @@
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
*
*/
* {
box-sizing: border-box;
* {
padding: 1px;
margin: 1px;
}
.loading-icon {
text-align: center;
margin-bottom: 1rem;
@ -32,7 +31,7 @@ button {
align-items: flex-start;
text-align: center;
cursor: default;
background-color: buttonface;
background: linear-gradient(0deg, rgba(169,169,169,1) 0%, rgba(255,255,255,1) 68%, rgba(227,227,227,1) 100%);
box-sizing: border-box;
padding: 2px 6px 3px;
border-width: 2px;
@ -183,7 +182,7 @@ button.pressed {
}
.vue-slider {
height: 25px !important;
height: 10px !important;
margin-bottom: 14px;
}
@ -203,7 +202,7 @@ button.pressed {
margin-right: 10px;
}
.slider-container::v-deep .vue-slider-mark-step {
.slider-container :deep(.vue-slider-mark-step) {
width: 2px;
height: 20px;
border-radius: 2px;
@ -212,26 +211,26 @@ button.pressed {
box-shadow: inset 1px 0 1px #ffffffbd, inset -1px 0 1px black;
}
.slider-container::v-deep .vue-slider-mark:first-child .vue-slider-mark-step,
.slider-container::v-deep .vue-slider-mark:last-child .vue-slider-mark-step {
.slider-container :deep(.vue-slider-mark:first-child .vue-slider-mark-step),
.slider-container :deep(.vue-slider-mark:last-child .vue-slider-mark-step) {
display: block;
}
.slider-container::v-deep .vue-slider-rail {
.slider-container :deep(.vue-slider-rail) {
border: 1px solid #dedede;
}
.slider-container::v-deep .vue-slider-process {
.slider-container :deep(.vue-slider-process) {
border-radius: 0;
box-shadow: inset 0px 2px 2px #ffffff80, inset 0px -2px 2px #0000002e;
}
.slider-container::v-deep .vue-slider-process:first-child {
.slider-container :deep(.vue-slider-process:first-child) {
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
.slider-container::v-deep .vue-slider-process:nth-last-child(3) {
.slider-container :deep(.vue-slider-process:nth-last-child(3)) {
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
@ -247,20 +246,20 @@ button.pressed {
}
.slider-label-trim {
transform: scale(1, 0.75) translate(-50%, -9px);
transform: scale(1, 0.75) translate(-50%, -9px) !important;;
}
.slider-label-stop {
font-size: 1.2rem;
transform: translate(-50%, 12px);
transform: translate(-50%, 12px) !important;;
}
.slider-label-jump {
transform: translate(-50%, -50px);
transform: translate(-50%, -50px) !important;;
}
.slider-label-color-change {
transform: translate(-50%, 10px);
transform: translate(-50%, 10px) !important;;
}
.current-stitch-input {
@ -286,23 +285,23 @@ button.pressed {
/* we need ::v-deep here because the svg tag is added by svg.js and so Vue
can't add the data-v-* attribute
*/
div.simulator::v-deep svg.simulation {
div.simulator :deep(svg.simulation) {
flex-grow: 1;
flex-shrink: 1;
order: -2;
margin-bottom: -48px;
}
div.simulator::v-deep svg.simulation-scale {
div.simulator :deep(svg.simulation-scale) {
height: 50px;
order: -1;
margin-left: 5px;
}
div.simulator::v-deep .simulation-scale-label {
div.simulator :deep(.simulation-scale-label) {
font-size: 14px;
}
div.simulator::v-deep .cursor {
div.simulator :deep(.cursor) {
/* not sure what to add here to make it more visible */
}

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -1,13 +1,22 @@
<!--
Authors: see git history
Copyright (c) 2010 Authors
Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
-->
<template>
<v-card raised rounded="lg" class="preferences-card">
<v-card elevation="8" rounded="lg" class="preferences-card">
<v-card-title class="text-center justify-center py-6">
<h1 class="font-weight-bold text-h2 basil--text">
<h1 class="font-weight-bold text-h2 text-basil">
Ink/Stitch Settings
</h1>
</v-card-title>
<v-card-text>
<v-tabs v-model="tab" background-color="transparent" grow>
<v-tabs v-model="tab" bg-color="transparent" class="text-primary" grow>
<v-tab key="this_svg_settings">
This SVG
</v-tab>
@ -16,16 +25,16 @@
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item key="this_svg_settings">
<v-window v-model="tab">
<v-window-item key="this_svg_settings">
<v-card flat>
<v-card-text>
<table>
<tr>
<td class="label">
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="collapse_len_mm" v-on="on" v-bind="attrs"><translate>Minimum jump stitch length</translate></label>
<template v-slot:activator="{ props }">
<label for="collapse_len_mm" v-bind="props"><translate>Minimum jump stitch length</translate></label>
</template>
<label for="collapse_len_mm"><translate>Jump stitches smaller than this will be treated as normal stitches.</translate></label>
</v-tooltip>
@ -45,8 +54,8 @@
<tr>
<td class="label">
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Minimum stitch length</translate></label>
<template v-slot:activator="{ props }">
<label for="min_stitch_len_mm" v-bind="props"><translate>Minimum stitch length</translate></label>
</template>
<label for="min_stitch_len_mm"><translate>Drop stitches smaller than this value.</translate></label>
</v-tooltip>
@ -66,16 +75,16 @@
</table>
</v-card-text>
</v-card>
</v-tab-item>
<v-tab-item key="global_settings">
</v-window-item>
<v-window-item key="global_settings">
<v-card flat>
<v-card-text>
<table>
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="default_collapse_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum jump stitch length</translate></label>
<template v-slot:activator="{ props }">
<label for="default_collapse_len_mm" v-bind="props"><translate>Default minimum jump stitch length</translate></label>
</template>
<label for="default_collapse_len_mm"><translate>Used for new SVGs.</translate></label>
</v-tooltip>
@ -90,8 +99,8 @@
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="default_min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum stitch length</translate></label>
<template v-slot:activator="{ props }">
<label for="default_min_stitch_len_mm" v-bind="props"><translate>Default minimum stitch length</translate></label>
</template>
<label for="default_min_stitch_len_mm"><translate>Used for new SVGs.</translate></label>
</v-tooltip>
@ -106,8 +115,8 @@
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="cache_size" v-on="on" v-bind="attrs"><translate>Stitch plan cache size</translate></label>
<template v-slot:activator="{ props }">
<label for="cache_size" v-bind="props"><translate>Stitch plan cache size</translate></label>
</template>
<label for="default_min_stitch_len_mm"><translate>The greater the number, the more stitch plans can be cached, speeding up stitch plan calculation. Default: 100</translate></label>
</v-tooltip>
@ -125,8 +134,8 @@
</table>
</v-card-text>
</v-card>
</v-tab-item>
</v-tabs-items>
</v-window-item>
</v-window>
</v-card-text>
<v-card-actions>
<v-btn text color="primary" @click="close"><translate>done</translate></v-btn>
@ -136,8 +145,7 @@
</template>
<script>
const inkStitch = require("../../lib/api")
import { inkStitch } from '../../lib/api.js'
export default {
name: "Preferences",
data: function () {
@ -202,10 +210,11 @@ td.label {
td.preference {
padding-right: 4px;
padding-left: 16px;
max-width: 100px;
max-width: 15em;
min-width: 8em;
}
td.preference::v-deep input {
td.preference :deep(input) {
text-align: right;
}

Wyświetl plik

@ -13,7 +13,7 @@
<div class="window-controls">
<div ref="controlInfoButton" class="control-info-button" v-on:click="toggleInfo">
<font-awesome-icon icon="info"/>
<collapse-transition>
<Transition name="collapse">
<div class="control-info" v-show="infoExpanded" v-bind:style="{'max-height': infoMaxHeight + 'px'}">
<h1>
<font-awesome-icon icon="info" class="info-icon"/>
@ -163,14 +163,14 @@
</p>
</div>
</div>
</collapse-transition>
</Transition>
</div>
<div class="toggle-controls" v-on:click="toggleControls">
<font-awesome-icon v-if="controlsExpanded" icon="minus"/>
<font-awesome-icon v-else icon="plus"/>
</div>
</div>
<collapse-transition>
<Transition name="collapse">
<div class="panel" v-show="controlsExpanded">
<fieldset class="controls">
<legend>
@ -203,7 +203,7 @@
</fieldset>
<fieldset class="speed">
<legend>
<translate :translate-n="speed" translate-plural="Speed: %{speed} stitches/sec">Speed: %{speed} stitch/sec</translate>
<translate :translate-params="{ speed: speed }" :translate-n="speed" translate-plural="Speed: %{speed} stitches/sec">Speed: %{speed} stitch/sec</translate>
</legend>
<button v-on:click="animationSlowDown" :title="$gettext('Slow down (arrow down)')">
<font-awesome-icon icon="hippo" size="2x" class="fa-button"/>
@ -248,7 +248,7 @@
<input id="stop-checkbox" type="checkbox" v-model="showStops"/>
<label for="stop-checkbox"><font-awesome-icon icon="pause"/> <translate>stops</translate></label>
</span>
<span>
<span class="npp">
<input id="npp-checkbox" type="checkbox" v-model="showNeedlePenetrationPoints"/>
<label for="npp-checkbox">
<font-awesome-layers>
@ -270,12 +270,11 @@
</span>
</fieldset>
</div>
</collapse-transition>
</Transition>
<div class="slider-container">
<span>1</span>
<span class="slider-box">
<vue-slider
:value="currentStitchDisplay"
<vue-slider v-model="currentStitchDisplay"
@change="setCurrentStitch"
:min="0"
:max="numStitches"
@ -297,7 +296,7 @@
@focus="stop"/>
</div>
</fieldset>
<loading :active.sync="loading" :is-full-page="false">
<loading :active="loading" :is-full-page="false">
<div class="loading">
<div class="loading-icon">
<font-awesome-icon icon="spinner" size="4x" pulse/>

Wyświetl plik

@ -7,111 +7,68 @@
*/
// ES6
import Vue from 'vue'
import axios from 'axios'
import App from './App'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import {library} from '@fortawesome/fontawesome-svg-core'
import {
faAlignRight,
faAngleDoubleLeft,
faAngleDoubleRight,
faAngleRight,
faCircle,
faCut,
faExchangeAlt,
faEye,
faFrog,
faLink,
faHippo,
faHorse,
faInfo,
faMinus,
faPalette,
faPause,
faPlay,
faPlus,
faShoePrints,
faSpinner,
faStepBackward,
faStepForward,
faStop,
faSearchPlus,
faSearchMinus
} from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon, FontAwesomeLayers} from '@fortawesome/vue-fontawesome'
import Transitions from 'vue2-transitions'
import GetTextPlugin from 'vue-gettext'
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
import { createGettext } from 'vue3-gettext'
import translations from './assets/translations.json'
import {selectLanguage} from '../lib/i18n'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import '@mdi/font/css/materialdesignicons.css'
import { selectLanguage } from '../lib/i18n.js'
// We have to add to the library every icon we use anywhere in the UI.
// This avoids the need to bundle the entire font-awesome icon set with
// Ink/Stitch.
library.add(
faAlignRight,
faAngleDoubleLeft,
faAngleDoubleRight,
faAngleRight,
faCircle,
faCut,
faExchangeAlt,
faEye,
faFrog,
faLink,
faHippo,
faHorse,
faInfo,
faMinus,
faPalette,
faPause,
faPlay,
faPlus,
faShoePrints,
faSpinner,
faStepBackward,
faStepForward,
faStop,
faSearchPlus,
faSearchMinus
)
import flaskserverport from '../lib/flaskserverport.json'
Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.component('font-awesome-layers', FontAwesomeLayers)
import { createVuetify, ThemeDefinition } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import 'vuetify/styles'
Vue.use(Transitions)
Vue.use(GetTextPlugin, {
translations: translations,
defaultLanguage: selectLanguage(translations),
silent: true
})
import VueMousetrapPlugin from 'vue-mousetrap'
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
if (flaskserverport.port === undefined) {
var theflaskport = window.inkstitchAPI.flaskport()
console.log("Installed mode")
console.log(theflaskport)
} else {
var theflaskport = flaskserverport.port
console.log("Dev mode")
console.log(theflaskport)
}
Vue.use(Vuetify)
const vuetify = new Vuetify({
const inkStitchTheme = {
dark: false,
colors: {
primary: '#003399',
secondary: '#000000',
accent: '#8c9eff',
error: '#b71c1c',
}
}
const vuetify = new createVuetify({
components,
directives,
ssr: true,
theme: {
defaultTheme: 'inkStitchTheme',
themes: {
light: {
primary: '#003399',
secondary: '#000000',
accent: '#8c9eff',
error: '#b71c1c',
},
},
},
inkStitchTheme,
}
}
})
/* eslint-disable no-new */
new Vue({
vuetify,
components: {App},
router,
template: '<App/>'
}).$mount('#app')
library.add(fas)
const app = createApp(App)
app.component('font-awesome-icon', FontAwesomeIcon)
app.component('font-awesome-layers', FontAwesomeLayers)
app.use(createGettext({
defaultLanguage: selectLanguage(translations, theflaskport),
translations: translations,
silent: true,
setGlobalProperties: true,
}))
app.use(VueMousetrapPlugin)
app.use(vuetify)
app.use(router)
app.mount('#app')

Wyświetl plik

@ -5,32 +5,32 @@
* Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
*
*/
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
import { createWebHashHistory, createRouter } from 'vue-router'
const routes = [
{
path: '/simulator',
name: 'simulator',
component: require('@/components/Simulator').default
path: '/simulator',
name: 'simulator',
component: () => import('../components/Simulator.vue')
},
{
path: '/install',
name: 'install',
component: require('@/components/InstallPalettes').default
path: '/preferences',
name: 'preferences',
component: () => import('../components/Preferences.vue')
},
{
path: '/preferences',
name: 'preferences',
component: require('@/components/Preferences').default
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('../components/NotFound.vue')
},
{
path: '*',
redirect: '/'
}
]
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
// Sets title for each routes
const DEFAULT_TITLE = 'Ink/Stitch';
router.beforeEach((to) => {
document.title = to.meta.title || DEFAULT_TITLE
})
export default router

Wyświetl plik

@ -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"]
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -22,7 +22,7 @@ AppUpdatesURL={#URL}
DefaultDirName={userappdata}\inkscape\extensions\
DefaultGroupName={#PROGRAMNAME}
; Remove the following line to run in administrative install mode (install for all users.)
ArchitecturesAllowed=x64 x86
ArchitecturesAllowed=x64 x86 arm64
PrivilegesRequired=lowest
OutputBaseFilename=inkstitch
OutputDir=.

Wyświetl plik

@ -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()

11
lib/api/lang.py 100644
Wyświetl plik

@ -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)

Wyświetl plik

@ -15,16 +15,22 @@ def get_page_specs():
height = svg.get('height', 0)
pagecolor = "white"
deskcolor = "white"
bordercolor = "black"
showpageshadow = True
namedview = svg.namedview
if namedview is not None:
pagecolor = namedview.get('pagecolor', pagecolor)
deskcolor = namedview.get('inkscape:deskcolor', deskcolor)
bordercolor = namedview.get('bordercolor', bordercolor)
showpageshadow = namedview.get('inkscape:showpageshadow', showpageshadow)
page_specs = {
"width": width,
"height": height,
"pagecolor": pagecolor,
"deskcolor": deskcolor
"deskcolor": deskcolor,
"bordercolor": bordercolor,
"showpageshadow": showpageshadow
}
return jsonify(page_specs)

Wyświetl plik

@ -9,17 +9,20 @@ import socket
import sys
import time
from threading import Thread
from contextlib import closing
import requests
from flask import Flask, g
from werkzeug.serving import make_server
from ..utils.json import InkStitchJSONProvider
from .install import install
from .simulator import simulator
from .stitch_plan import stitch_plan
from .preferences import preferences
from .page_specs import page_specs
from .lang import languages
# this for electron axios
from flask_cors import CORS
class APIServer(Thread):
@ -42,13 +45,14 @@ class APIServer(Thread):
cli.show_server_banner = lambda *x: None
self.app = Flask(__name__)
CORS(self.app)
self.app.json = InkStitchJSONProvider(self.app)
self.app.register_blueprint(simulator, url_prefix="/simulator")
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(page_specs, url_prefix="/page_specs")
self.app.register_blueprint(languages, url_prefix="/languages")
@self.app.before_request
def store_extension():
@ -67,25 +71,21 @@ class APIServer(Thread):
def disable_logging(self):
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):
self.disable_logging()
self.host = "127.0.0.1"
self.port = 5000
while True:
try:
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
self.port = self.find_free_port()
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()
def ready_checker(self):
"""Wait until the server is started.

Wyświetl plik

@ -4,18 +4,48 @@
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from .base import InkstitchExtension
from ..api import APIServer
from ..gui import open_url
import os
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):
def __init__(self):
InkstitchExtension.__init__(self)
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self, *args, **kwargs)
def effect(self):
api_server = APIServer(self)
port = api_server.start_server()
electron = open_url("/install?port=%d" % port)
electron.wait()
api_server.stop()
api_server.join()
path = os.path.join(guess_inkscape_config_path(), 'palettes')
src_dir = get_bundled_dir('palettes')
try:
copy_files(glob(os.path.join(src_dir, "*")), path)
errormsg(_("Successfully installed color palettes for Inkscape.\n\n"
"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)

Wyświetl plik

@ -27,7 +27,7 @@ class Preferences(InkstitchExtension):
def effect(self):
api_server = APIServer(self)
port = api_server.start_server()
electron = open_url("/preferences?port=%d" % port)
electron = open_url("/preferences", port)
electron.wait()
api_server.stop()
api_server.join()

Wyświetl plik

@ -3,7 +3,6 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import errno
import json
import logging
import os
@ -13,6 +12,7 @@ import time
from copy import deepcopy
from datetime import date
from threading import Thread
from contextlib import closing
import appdirs
from flask import Flask, Response, jsonify, request, send_from_directory
@ -162,25 +162,24 @@ class PrintPreviewServer(Thread):
def disable_logging(self):
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):
self.disable_logging()
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:
try:
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
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()
class Print(InkstitchExtension):
@ -331,13 +330,12 @@ class Print(InkstitchExtension):
realistic_color_block_svgs=realistic_color_block_svgs
)
print_server.start()
# 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
# after startup.
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()
print_server.stop()
print_server.join()

Wyświetl plik

@ -18,7 +18,7 @@ class Simulator(InkstitchExtension):
return
api_server = APIServer(self)
port = api_server.start_server()
electron = open_url("/simulator?port=%d" % port)
electron = open_url("/simulator", port)
electron.wait()
api_server.stop()
api_server.join()

Wyświetl plik

@ -3,6 +3,7 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import json
import os
import subprocess
import sys
@ -12,11 +13,27 @@ from ..utils import get_bundled_dir
app_process = None
def open_url(url):
def open_url(url, port, pdf=False): # noqa: C901
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
searchstring = "http"
if getattr(sys, 'frozen', None) is not None:
electron_path = os.path.join(get_bundled_dir("electron"), "inkstitch-gui")
@ -42,8 +59,33 @@ def open_url(url):
pass
else:
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:
return subprocess.Popen(command, cwd=cwd, stdout=null, env=mac_dev_env)
else:
with open(os.devnull, 'w') as null:
return subprocess.Popen(command, cwd=cwd, stdout=null)
if searchstring in url and getattr(sys, 'frozen', None) is None:
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)

Wyświetl plik

@ -1,5 +1,3 @@
var electron = require('electron');
$.postJSON = function(url, data, success=null) {
return $.ajax(url, {
type: 'POST',
@ -378,14 +376,14 @@ $(function() {
});
$('button.print').click(function() {
var pageSize = $('select#printing-size').find(':selected').text();
electron.ipcRenderer.send('open-pdf', pageSize)
var pageSize = $('select#printing-size').find(':selected').text();
window.inkstitchAPI.openpdf(pageSize)
});
$('button.save-pdf').click(function() {
var pageSize = $('select#printing-size').find(':selected').text();
electron.ipcRenderer.send('save-pdf', pageSize)
});
var pageSize = $('select#printing-size').find(':selected').text();
window.inkstitchAPI.savepdf(pageSize)
});
$('button.settings').click(function(){
$('#settings-ui').show();

Wyświetl plik

@ -27,6 +27,6 @@ fonttools
trimesh>=3.15.2
scipy
diskcache
flask-cors
pywinutils ; sys_platform == 'win32'
pywin32 ; sys_platform == 'win32'