version 1
This commit is contained in:
30
.babelrc
Normal file
30
.babelrc
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"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"]
|
||||
}
|
||||
3
.editorconfig
Normal file
3
.editorconfig
Normal file
@ -0,0 +1,3 @@
|
||||
[*{.js, .vue}]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
132
.electron-vue/build.js
Normal file
132
.electron-vue/build.js
Normal file
@ -0,0 +1,132 @@
|
||||
'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()
|
||||
}
|
||||
40
.electron-vue/dev-client.js
Normal file
40
.electron-vue/dev-client.js
Normal file
@ -0,0 +1,40 @@
|
||||
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>
|
||||
`
|
||||
}
|
||||
})
|
||||
190
.electron-vue/dev-runner.js
Normal file
190
.electron-vue/dev-runner.js
Normal file
@ -0,0 +1,190 @@
|
||||
'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 () {
|
||||
var args = [
|
||||
'--inspect=5858',
|
||||
path.join(__dirname, '../dist/electron/main.js')
|
||||
]
|
||||
|
||||
// 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()
|
||||
83
.electron-vue/webpack.main.config.js
Normal file
83
.electron-vue/webpack.main.config.js
Normal file
@ -0,0 +1,83 @@
|
||||
'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)$/,
|
||||
enforce: 'pre',
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'eslint-loader',
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
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
|
||||
182
.electron-vue/webpack.renderer.config.js
Normal file
182
.electron-vue/webpack.renderer.config.js
Normal file
@ -0,0 +1,182 @@
|
||||
'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
|
||||
*/
|
||||
let whiteListedModules = ['vue']
|
||||
|
||||
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: /\.(js|vue)$/,
|
||||
enforce: 'pre',
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'eslint-loader',
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
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]'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
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'),
|
||||
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
|
||||
143
.electron-vue/webpack.web.config.js
Normal file
143
.electron-vue/webpack.web.config.js
Normal file
@ -0,0 +1,143 @@
|
||||
'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: /\.(js|vue)$/,
|
||||
enforce: 'pre',
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'eslint-loader',
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
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]'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin(),
|
||||
new MiniCssExtractPlugin({filename: 'styles.css'}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
||||
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
|
||||
0
.eslintignore
Normal file
0
.eslintignore
Normal file
26
.eslintrc.js
Normal file
26
.eslintrc.js
Normal file
@ -0,0 +1,26 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
.DS_Store
|
||||
dist/electron/*
|
||||
dist/web/*
|
||||
build/*
|
||||
!build/icons
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
npm-debug.log.*
|
||||
thumbs.db
|
||||
!.gitkeep
|
||||
36
.travis.yml
Normal file
36
.travis.yml
Normal file
@ -0,0 +1,36 @@
|
||||
osx_image: xcode8.3
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: c
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
- os: linux
|
||||
env: CC=clang CXX=clang++ npm_config_clang=1
|
||||
compiler: clang
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- "$HOME/.electron"
|
||||
- "$HOME/.cache"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgnome-keyring-dev
|
||||
- icnsutils
|
||||
before_install:
|
||||
- mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
|
||||
"$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
|
||||
| tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
|
||||
install:
|
||||
- nvm install 7
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||
- source ~/.bashrc
|
||||
- npm install -g xvfb-maybe
|
||||
- yarn
|
||||
script:
|
||||
- yarn run build
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
25
README.md
Normal file
25
README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# client-desktop
|
||||
|
||||
> Desktop socket.io chat client
|
||||
|
||||
#### Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# serve with hot reload at localhost:9080
|
||||
npm run dev
|
||||
|
||||
# build electron application for production
|
||||
npm run build
|
||||
|
||||
|
||||
# lint all JS/Vue component files in `src/`
|
||||
npm run lint
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[8fae476](https://github.com/SimulatedGREG/electron-vue/tree/8fae4763e9d225d3691b627e83b9e09b56f6c935) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html).
|
||||
29
appveyor.yml
Normal file
29
appveyor.yml
Normal file
@ -0,0 +1,29 @@
|
||||
version: 0.1.{build}
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
image: Visual Studio 2017
|
||||
platform:
|
||||
- x64
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
- '%APPDATA%\npm-cache'
|
||||
- '%USERPROFILE%\.electron'
|
||||
- '%USERPROFILE%\AppData\Local\Yarn\cache'
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
install:
|
||||
- ps: Install-Product node 8 x64
|
||||
- git reset --hard HEAD
|
||||
- yarn
|
||||
- node --version
|
||||
|
||||
build_script:
|
||||
- yarn build
|
||||
|
||||
test: off
|
||||
BIN
build/icons/256x256.png
Normal file
BIN
build/icons/256x256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
build/icons/icon.icns
Normal file
BIN
build/icons/icon.icns
Normal file
Binary file not shown.
BIN
build/icons/icon.ico
Normal file
BIN
build/icons/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 257 KiB |
116
package.json
Normal file
116
package.json
Normal file
@ -0,0 +1,116 @@
|
||||
{
|
||||
"name": "client-desktop",
|
||||
"version": "0.0.1",
|
||||
"author": "Roman Bessonov <roma.bessonov@gmail.com>",
|
||||
"description": "Desktop socket.io chat client",
|
||||
"license": null,
|
||||
"main": "./dist/electron/main.js",
|
||||
"scripts": {
|
||||
"build": "node .electron-vue/build.js && electron-builder",
|
||||
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
|
||||
"build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
|
||||
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
|
||||
"dev": "node .electron-vue/dev-runner.js",
|
||||
"lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src",
|
||||
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src",
|
||||
"pack": "npm run pack:main && npm run pack:renderer",
|
||||
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
|
||||
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
|
||||
"postinstall": "npm run lint:fix"
|
||||
},
|
||||
"build": {
|
||||
"productName": "client-desktop",
|
||||
"appId": "org.osu.chat-desktop",
|
||||
"directories": {
|
||||
"output": "build"
|
||||
},
|
||||
"files": [
|
||||
"dist/electron/**/*"
|
||||
],
|
||||
"dmg": {
|
||||
"contents": [
|
||||
{
|
||||
"x": 410,
|
||||
"y": 150,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
},
|
||||
{
|
||||
"x": 130,
|
||||
"y": 150,
|
||||
"type": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mac": {
|
||||
"icon": "build/icons/icon.icns"
|
||||
},
|
||||
"win": {
|
||||
"icon": "build/icons/icon.ico"
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icons"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"bootstrap": "^4.2.1",
|
||||
"jquery": "^3.3.1",
|
||||
"popper.js": "^1.14.6",
|
||||
"socket.io": "^2.2.0",
|
||||
"socket.io-client": "^2.2.0",
|
||||
"vue": "^2.5.16",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-form": "^4.10.1",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.0.1",
|
||||
"vuex-electron": "^1.0.0"
|
||||
},
|
||||
"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",
|
||||
"del": "^3.0.0",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^2.0.4",
|
||||
"electron-builder": "^20.19.2",
|
||||
"electron-debug": "^1.5.0",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"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",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
24
src/index.ejs
Normal file
24
src/index.ejs
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>client-desktop</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>
|
||||
24
src/main/index.dev.js
Normal file
24
src/main/index.dev.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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')
|
||||
67
src/main/index.js
Normal file
67
src/main/index.js
Normal file
@ -0,0 +1,67 @@
|
||||
'use strict'
|
||||
|
||||
import { app, BrowserWindow } from 'electron'
|
||||
|
||||
/**
|
||||
* 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') {
|
||||
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
let mainWindow
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080`
|
||||
: `file://${__dirname}/index.html`
|
||||
|
||||
function createWindow () {
|
||||
/**
|
||||
* Initial window options
|
||||
*/
|
||||
mainWindow = new BrowserWindow({
|
||||
height: 563,
|
||||
useContentSize: true,
|
||||
width: 1000
|
||||
})
|
||||
|
||||
mainWindow.loadURL(winURL)
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
app.on('ready', createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 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()
|
||||
})
|
||||
*/
|
||||
15
src/renderer/App.vue
Normal file
15
src/renderer/App.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'client-desktop'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* CSS */
|
||||
</style>
|
||||
0
src/renderer/assets/.gitkeep
Normal file
0
src/renderer/assets/.gitkeep
Normal file
BIN
src/renderer/assets/logo.png
Normal file
BIN
src/renderer/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
22
src/renderer/components/ChatList.vue
Normal file
22
src/renderer/components/ChatList.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="message in messages" :key="message.message">
|
||||
{{message.username}}: <span>{{message.message}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ChatList',
|
||||
computed: {
|
||||
messages () {
|
||||
return this.$store.state.chat.messages
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
44
src/renderer/components/ChatScreen.vue
Normal file
44
src/renderer/components/ChatScreen.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<button @click="logout">Выйти</button>
|
||||
<ChatList></ChatList>
|
||||
<SendMessage></SendMessage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SendMessage from './SendMessage'
|
||||
import ChatList from './ChatList'
|
||||
import SocketConnector from '../data/SocketConnector'
|
||||
|
||||
export default {
|
||||
name: 'ChatScreen',
|
||||
components: {ChatList, SendMessage},
|
||||
computed: {
|
||||
loggedIn () {
|
||||
return this.$store.state.chat.userdata.login !== null && this.$store.state.chat.connected
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
loggedIn (val) {
|
||||
if (!val) {
|
||||
this.$router.push({name: 'connect'})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (!this.loggedIn) {
|
||||
this.$router.push({name: 'connect'})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logout () {
|
||||
SocketConnector.disconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
54
src/renderer/components/Connect.vue
Normal file
54
src/renderer/components/Connect.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="connect-container">
|
||||
<vue-form @submit.prevent="onClick" :state="state">
|
||||
<validate>
|
||||
<label for="address">Адрес сервера</label>
|
||||
|
||||
<input name="address" v-model="data.address" required type="text" id="address">
|
||||
</validate>
|
||||
<validate>
|
||||
<label for="name">Ваше имя</label>
|
||||
|
||||
<input name="name" v-model="data.name" required type="text" id="name">
|
||||
</validate>
|
||||
<button type="submit">Начать</button>
|
||||
</vue-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SocketConnector from '../data/SocketConnector'
|
||||
|
||||
export default {
|
||||
name: 'Connect',
|
||||
data () {
|
||||
return {
|
||||
socket: null,
|
||||
connected: false,
|
||||
data: {
|
||||
address: '',
|
||||
name: ''
|
||||
},
|
||||
state: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick () {
|
||||
if (!this.state.$valid) {
|
||||
return
|
||||
}
|
||||
SocketConnector.connect(this.data.address)
|
||||
this.$store.commit('chat/setLoginData', {login: this.data.name})
|
||||
this.$router.push({name: 'chat'})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.connect-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
128
src/renderer/components/LandingPage.vue
Normal file
128
src/renderer/components/LandingPage.vue
Normal file
@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<div id="wrapper">
|
||||
<img id="logo" src="~@/assets/logo.png" alt="electron-vue">
|
||||
<main>
|
||||
<div class="left-side">
|
||||
<span class="title">
|
||||
Welcome to your new project!
|
||||
</span>
|
||||
<system-information></system-information>
|
||||
</div>
|
||||
|
||||
<div class="right-side">
|
||||
<div class="doc">
|
||||
<div class="title">Getting Started</div>
|
||||
<p>
|
||||
electron-vue comes packed with detailed documentation that covers everything from
|
||||
internal configurations, using the project structure, building your application,
|
||||
and so much more.
|
||||
</p>
|
||||
<button @click="open('https://simulatedgreg.gitbooks.io/electron-vue/content/')">Read the Docs</button><br><br>
|
||||
</div>
|
||||
<div class="doc">
|
||||
<div class="title alt">Other Documentation</div>
|
||||
<button class="alt" @click="open('https://electron.atom.io/docs/')">Electron</button>
|
||||
<button class="alt" @click="open('https://vuejs.org/v2/guide/')">Vue.js</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SystemInformation from './LandingPage/SystemInformation'
|
||||
|
||||
export default {
|
||||
name: 'landing-page',
|
||||
components: { SystemInformation },
|
||||
methods: {
|
||||
open (link) {
|
||||
this.$electron.shell.openExternal(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body { font-family: 'Source Sans Pro', sans-serif; }
|
||||
|
||||
#wrapper {
|
||||
background:
|
||||
radial-gradient(
|
||||
ellipse at top left,
|
||||
rgba(255, 255, 255, 1) 40%,
|
||||
rgba(229, 229, 229, .9) 100%
|
||||
);
|
||||
height: 100vh;
|
||||
padding: 60px 80px;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#logo {
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
main > div { flex-basis: 50%; }
|
||||
|
||||
.left-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
color: #555;
|
||||
font-size: 23px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #2c3e50;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.title.alt {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc p {
|
||||
color: black;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc button {
|
||||
font-size: .8em;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: 0.75em 2em;
|
||||
border-radius: 2em;
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background-color: #4fc08d;
|
||||
transition: all 0.15s ease;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #4fc08d;
|
||||
}
|
||||
|
||||
.doc button.alt {
|
||||
color: #42b983;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
73
src/renderer/components/LandingPage/SystemInformation.vue
Normal file
73
src/renderer/components/LandingPage/SystemInformation.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="title">Information</div>
|
||||
<div class="items">
|
||||
<div class="item">
|
||||
<div class="name">Path:</div>
|
||||
<div class="value">{{ path }}</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="name">Route Name:</div>
|
||||
<div class="value">{{ name }}</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="name">Vue.js:</div>
|
||||
<div class="value">{{ vue }}</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="name">Electron:</div>
|
||||
<div class="value">{{ electron }}</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="name">Node:</div>
|
||||
<div class="value">{{ node }}</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="name">Platform:</div>
|
||||
<div class="value">{{ platform }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
electron: process.versions.electron,
|
||||
name: this.$route.name,
|
||||
node: process.versions.node,
|
||||
path: this.$route.path,
|
||||
platform: require('os').platform(),
|
||||
vue: require('vue/package.json').version
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title {
|
||||
color: #888;
|
||||
font-size: 18px;
|
||||
font-weight: initial;
|
||||
letter-spacing: .25px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.items { margin-top: 8px; }
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.item .name {
|
||||
color: #6a6a6a;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.item .value {
|
||||
color: #35495e;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
34
src/renderer/components/SendMessage.vue
Normal file
34
src/renderer/components/SendMessage.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<vue-form @submit.prevent="onClick" :state="state">
|
||||
<label for="message">Сообщение</label>
|
||||
<input id="message" name="message" v-model="message" required>
|
||||
<button type="submit">Отправить</button>
|
||||
</vue-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SocketConnector from '../data/SocketConnector'
|
||||
|
||||
export default {
|
||||
name: 'SendMessage',
|
||||
data () {
|
||||
return {
|
||||
state: {},
|
||||
message: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick () {
|
||||
if (!this.state.$valid) {
|
||||
return
|
||||
}
|
||||
SocketConnector.sendMessage(this.message)
|
||||
this.message = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
29
src/renderer/data/SocketConnector.js
Normal file
29
src/renderer/data/SocketConnector.js
Normal file
@ -0,0 +1,29 @@
|
||||
import store from '../store'
|
||||
import io from 'socket.io-client'
|
||||
class SocketConnector {
|
||||
constructor () {
|
||||
this._socket = null
|
||||
}
|
||||
connect (address) {
|
||||
this._socket = io(`http://${address}`)
|
||||
store.commit('chat/setConnectedValue', {value: true})
|
||||
|
||||
this._socket.on('user message', (msg) => {
|
||||
store.commit('chat/addMessage', {message: msg})
|
||||
})
|
||||
}
|
||||
sendMessage (message) {
|
||||
this._socket.emit('user message', {username: store.state.chat.userdata.login, message})
|
||||
}
|
||||
disconnect () {
|
||||
if (this._socket !== null) {
|
||||
this._socket.disconnect()
|
||||
this._socket = null
|
||||
}
|
||||
store.commit('chat/setConnectedValue', {value: false})
|
||||
store.commit('chat/setLoginData', {login: null})
|
||||
store.commit('chat/clearMessages')
|
||||
}
|
||||
}
|
||||
|
||||
export default new SocketConnector()
|
||||
24
src/renderer/main.js
Normal file
24
src/renderer/main.js
Normal file
@ -0,0 +1,24 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import VueForm from 'vue-form'
|
||||
import 'popper.js'
|
||||
import 'jquery'
|
||||
import 'bootstrap'
|
||||
|
||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
||||
Vue.http = Vue.prototype.$http = axios
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.use(VueForm)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
components: { App },
|
||||
router,
|
||||
store,
|
||||
template: '<App/>'
|
||||
}).$mount('#app')
|
||||
26
src/renderer/router/index.js
Normal file
26
src/renderer/router/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
import Connect from '../components/Connect'
|
||||
import ChatScreen from '../components/ChatScreen'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'connect',
|
||||
component: Connect
|
||||
},
|
||||
{
|
||||
path: '/chat',
|
||||
name: 'chat',
|
||||
component: ChatScreen
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/'
|
||||
}
|
||||
]
|
||||
})
|
||||
12
src/renderer/store/index.js
Normal file
12
src/renderer/store/index.js
Normal file
@ -0,0 +1,12 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
// import { createPersistedState, createSharedMutations } from 'vuex-electron'
|
||||
import chat from './modules/chat'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {chat},
|
||||
strict: process.env.NODE_ENV !== 'production'
|
||||
})
|
||||
30
src/renderer/store/modules/chat.js
Normal file
30
src/renderer/store/modules/chat.js
Normal file
@ -0,0 +1,30 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = {
|
||||
userdata: {
|
||||
login: null
|
||||
},
|
||||
messages: [],
|
||||
connected: false
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
setLoginData (state, {login}) {
|
||||
state.userdata.login = login
|
||||
},
|
||||
addMessage (state, {message}) {
|
||||
state.messages.push(message)
|
||||
},
|
||||
clearMessages (state) {
|
||||
Vue.set(state, 'messages', [])
|
||||
},
|
||||
setConnectedValue (state, {value}) {
|
||||
state.connected = value
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations
|
||||
}
|
||||
0
static/.gitkeep
Normal file
0
static/.gitkeep
Normal file
Reference in New Issue
Block a user