Browse Source

More code refactoring!

tags/v1.4.4
Ivan Bravo Bravo 11 months ago
parent
commit
212d8e80cd
54 changed files with 1196 additions and 2068 deletions
  1. 0
    8
      src/.env.example
  2. 2
    0
      src/.eslintrc.js
  3. 3
    2
      src/components/Layout/Navigation.vue
  4. 2
    1
      src/components/Nudity/Job.vue
  5. 7
    5
      src/components/Nudity/Upload.vue
  6. 4
    2
      src/components/UI/AppExternalLink.vue
  7. 3
    1
      src/components/UI/AppUpdate.vue
  8. 3
    2
      src/components/UI/BoxItem.vue
  9. 42
    42
      src/electron/src/index.js
  10. 8
    5
      src/electron/src/modules/app-error.js
  11. 1
    1
      src/electron/src/modules/services/base.js
  12. 2
    2
      src/electron/src/modules/services/nucleus.js
  13. 2
    2
      src/electron/src/modules/services/rollbar.js
  14. 5
    5
      src/electron/src/modules/services/settings.js
  15. 210
    192
      src/electron/src/modules/tools/fs.js
  16. 1
    0
      src/electron/src/modules/tools/index.js
  17. 20
    20
      src/electron/src/modules/tools/paths.js
  18. 7
    7
      src/electron/src/modules/tools/power.js
  19. 2
    2
      src/electron/src/modules/tools/shell.js
  20. 28
    17
      src/electron/src/modules/tools/system.js
  21. 457
    0
      src/electron/src/modules/updater/base.js
  22. 77
    0
      src/electron/src/modules/updater/checkpoints.js
  23. 127
    0
      src/electron/src/modules/updater/dreampower.js
  24. 70
    0
      src/electron/src/modules/updater/dreamtime.js
  25. 3
    1
      src/electron/src/modules/updater/index.js
  26. 5
    4
      src/middleware/checks.js
  27. 2
    5
      src/mixins/BaseMixin.js
  28. 4
    4
      src/modules/dream.js
  29. 15
    8
      src/modules/file.js
  30. 2
    4
      src/modules/index.js
  31. 9
    5
      src/modules/models/photo-job.js
  32. 10
    6
      src/modules/models/photo.js
  33. 0
    187
      src/modules/platform.js
  34. 0
    386
      src/modules/update/base.js
  35. 0
    141
      src/modules/update/checkpoints.js
  36. 0
    160
      src/modules/update/dreampower.js
  37. 0
    96
      src/modules/update/dreamtime.js
  38. 0
    44
      src/modules/updater.js
  39. 17
    88
      src/modules/web-error.js
  40. 2
    1
      src/package.json
  41. 3
    1
      src/pages/index.vue
  42. 0
    531
      src/pages/nudify/crop.backup.vue
  43. 3
    1
      src/pages/nudify/crop.vue
  44. 3
    1
      src/pages/nudify/results.vue
  45. 18
    14
      src/pages/system/about.vue
  46. 4
    2
      src/pages/system/settings.vue
  47. 6
    5
      src/pages/system/settings/folders.vue
  48. 1
    1
      src/pages/system/settings/notifications.vue
  49. 1
    1
      src/pages/system/settings/preferences.vue
  50. 1
    1
      src/pages/system/settings/processing.vue
  51. 1
    1
      src/pages/system/settings/telemetry.vue
  52. 1
    1
      src/pages/system/welcome.vue
  53. 2
    2
      src/plugins/boot.js
  54. 0
    50
      src/plugins/setup.js

+ 0
- 8
src/.env.example View File

@@ -1,8 +0,0 @@
APP_NAME = DreamTime
APP_STATUS = stable
APP_VERSION = 1.0.0

SERVER_PORT = 3000
SERVER_HOST = localhost

NUCLEUS_APPID =

+ 2
- 0
src/.eslintrc.js View File

@@ -37,6 +37,8 @@ module.exports = {
"import/order": "error",
"import/prefer-default-export": "off",
"import/no-extraneous-dependencies": "off",
"import/named": "off",
"import/no-cycle": "off",
"linebreak-style": "warn",
"lodash/import-scope": [
"off",

+ 3
- 2
src/components/Layout/Navigation.vue View File

@@ -63,6 +63,8 @@
<script>
import moment from 'moment'

const { settings } = $provider.services

export default {
computed: {
greetings() {
@@ -89,13 +91,12 @@ export default {

isActive() {
// eslint-disable-next-line no-underscore-dangle
return $settings._settings.welcome !== true
return settings.welcome !== true
},
},

methods: {
testBug() {
$tools.testError()
throw new Error('wow much error')
},
},

+ 2
- 1
src/components/Nudity/Job.vue View File

@@ -104,6 +104,7 @@

<script>
import _ from 'lodash'
import { api } from 'electron-utils'

export default {
filters: {
@@ -134,7 +135,7 @@ export default {
view() {},

save() {
const savePath = $tools.shell.showSaveDialog({
const savePath = api.shell.showSaveDialog({
defaultPath: this.job.getFileName(),
filters: [
{ name: 'PNG', extensions: ['png'] },

+ 7
- 5
src/components/Nudity/Upload.vue View File

@@ -88,6 +88,8 @@ import swal from 'sweetalert'
import { Photo } from '~/modules/models'
import { File } from '~/modules'

const { nucleus, rollbar } = $provider.services

export default {
props: {
model: {
@@ -161,7 +163,7 @@ export default {
} has permissions to save files.`,
})

$rollbar.warn(err)
rollbar.warn(err)
}
},

@@ -204,7 +206,7 @@ export default {
return
}

$nucleus.track('UPLOAD_SELECTED')
nucleus.track('UPLOAD_SELECTED')

this.startFromFile(files[0])
event.target.value = ''
@@ -219,7 +221,7 @@ export default {
return
}

$nucleus.track('UPLOAD_URL')
nucleus.track('UPLOAD_URL')

this.startFromURL(this.webAddress)
},
@@ -261,10 +263,10 @@ export default {
const externalURL = event.dataTransfer.getData('url')

if (files.length > 0) {
$nucleus.track('UPLOAD_DROP')
nucleus.track('UPLOAD_DROP')
this.startFromFile(files[0])
} else if (externalURL.length > 0) {
$nucleus.track('UPLOAD_DROP_URL')
nucleus.track('UPLOAD_DROP_URL')
this.startFromURL(externalURL)
}
},

+ 4
- 2
src/components/UI/AppExternalLink.vue View File

@@ -5,6 +5,8 @@
</template>

<script>
import { api } from 'electron-utils'

export default {
props: {
href: {
@@ -15,8 +17,8 @@ export default {

methods: {
openExternal() {
$nucleus.track('EXTERNAL_LINK', { href: this.href })
$tools.shell.openExternal(this.href)
$provider.services.nucleus.track('EXTERNAL_LINK', { href: this.href })
api.shell.openExternal(this.href)
},
},
}

+ 3
- 1
src/components/UI/AppUpdate.vue View File

@@ -48,6 +48,8 @@
</template>

<script>
import { api } from 'electron-utils'

export default {
filters: {
progress(value) {
@@ -96,7 +98,7 @@ export default {

methods: {
openDownload() {
$tools.shell.openItem($tools.paths.get('downloads'))
api.shell.openItem($provider.tools.paths.getPath('downloads'))
},
},
}

+ 3
- 2
src/components/UI/BoxItem.vue View File

@@ -20,6 +20,7 @@

<script>
import _ from 'lodash'
import { api } from 'electron-utils'

export default {
props: {
@@ -65,8 +66,8 @@ export default {
click() {
this.$emit('click')
if (!_.isNil(this.href)) {
$nucleus.track('EXTERNAL_LINK', { href: this.href })
$tools.shell.openExternal(this.href)
$provider.services.nucleus.track('EXTERNAL_LINK', { href: this.href })
api.shell.openExternal(this.href)
}
},
isURL(str) {

+ 42
- 42
src/electron/src/index.js View File

@@ -9,49 +9,44 @@

import { app, BrowserWindow } from 'electron'
import http from 'http'
import path from 'path'
import { dirname, join } from 'path'
import { URL } from 'url'
import fs from 'fs-extra'
import contextMenu from 'electron-context-menu'
import Logger from 'logplease'
import { pack, enforceMacOSAppLocation } from 'electron-utils'

import { AppError } from './modules/app-error'
import { settings, nucleus, rollbar } from './modules/services'
import { system } from './modules/tools'
import { system } from './modules/tools/system'
import { existsSync, mkdirSync } from './modules/tools/fs'
import { getPath } from './modules/tools/paths'
import { dreamtime, dreampower, checkpoints } from './modules/updater'
import config from '~/nuxt.config'

const logger = require('logplease').create('electron')
const logger = Logger.create('electron')

// NuxtJS root directory
config.rootDir = path.dirname(__dirname)

// copyright

console.log(`
DreamTime.
Copyright (C) DreamNet. All rights reserved.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License 3.0 as published by
the Free Software Foundation. See <https://www.gnu.org/licenses/gpl-3.0.html>
`)

logger.info('Starting...')

logger.debug({
env: process.env.NODE_ENV,
isStatic: pack.isStatic(),
paths: {
appPath: app.getAppPath(),
exePath: app.getPath('exe'),
},
})
config.rootDir = dirname(__dirname)

class DreamApp {
/**
* Start the app!
*/
static async start() {
// logger setup
Logger.setLogLevel(process.env.LOG || 'info')
Logger.setLogfile(getPath('userData', 'dreamtime.log'))

logger.info('Starting...')

logger.debug({
env: process.env.NODE_ENV,
isStatic: pack.isStatic(),
paths: {
appPath: app.getAppPath(),
exePath: app.getPath('exe'),
},
})

await this.setup()

this.createWindow()
@@ -87,16 +82,21 @@ class DreamApp {
// user settings.
await settings.setup()

// analytics.
// analytics & app settings.
await nucleus.setup()

// bug tracking.
await rollbar.setup()
// requirements.
await system.scan()
// services
await Promise.all([
rollbar.setup(), // bug tracking.
system.scan(), // requirements.
])

// todo: updates
// update providers
await Promise.all([
dreamtime.setup(),
dreampower.setup(),
checkpoints.setup(),
])

//
this.createDirs()
@@ -124,10 +124,10 @@ class DreamApp {
height: 700,
minWidth: 1200,
minHeight: 700,
icon: path.join(config.rootDir, 'dist', 'icon.ico'),
icon: join(config.rootDir, 'dist', 'icon.ico'),
webPreferences: {
nodeIntegration: false,
preload: path.join(app.getAppPath(), 'electron', 'dist', 'provider.js'),
preload: join(app.getAppPath(), 'electron', 'dist', 'provider.js'),
},
})

@@ -178,7 +178,7 @@ class DreamApp {
*/
static getUiUrl() {
if (!config.dev) {
return path.join(config.rootDir, 'dist', 'index.html')
return join(config.rootDir, 'dist', 'index.html')
}

return `http://localhost:${config.server.port}`
@@ -188,10 +188,10 @@ class DreamApp {
* Create required directories.
*/
static createDirs() {
const modelsPath = path.join(settings.folders.models, 'Uncategorized')
const modelsPath = join(settings.folders.models, 'Uncategorized')

if (!fs.existsSync(modelsPath)) {
fs.mkdirSync(modelsPath, { recursive: true },
if (!existsSync(modelsPath)) {
mkdirSync(modelsPath, { recursive: true },
(error) => {
throw new AppError(`Models directory creation fail.`, { error })
})
@@ -235,6 +235,6 @@ app.on('ready', async () => {
try {
await DreamApp.start()
} catch (error) {
throw new AppError(error, { title: `Failed to start correctly.` })
throw new AppError(error, { title: `Failed to start correctly.`, fatal: true })
}
})

+ 8
- 5
src/electron/src/modules/app-error.js View File

@@ -8,7 +8,7 @@
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

import { isError, isString } from 'lodash'
import { api } from 'electron-utils'
import { app, dialog } from 'electron'
import { rollbar } from './services/rollbar'

const logger = require('logplease').create('electron:scripts:error')
@@ -26,6 +26,7 @@ export class AppError extends Error {
title: null,
error: null,
level: 'error',
fatal: false,
}

/**
@@ -87,19 +88,21 @@ export class AppError extends Error {
}

show() {
api.dialog.showErrorBox(
dialog.showErrorBox(
this.options.title || 'A problem has occurred.',
this.message,
)

api.app.quit()
if (this.options.fatal) {
app.quit()
}
}

static handle(error) {
let appError = error

if (!(appError instanceof AppError)) {
appError = new AppError(
if (!(appError instanceof this)) {
appError = new this(
isError(appError) ? error : 'The program has encountered an unexpected error.',
{
error: isError(appError) ? appError : new Error(appError),

+ 1
- 1
src/electron/src/modules/services/base.js View File

@@ -12,7 +12,7 @@ import {
} from 'lodash'
import fs from 'fs'

const logger = require('logplease').create('electron:scripts:services')
const logger = require('logplease').create('services')

export class BaseService {
/**

+ 2
- 2
src/electron/src/modules/services/nucleus.js View File

@@ -14,7 +14,7 @@ import { BaseService } from './base'
import { system } from '../tools'
import { settings } from './settings'

const logger = require('logplease').create('electron:scripts:services:nucleus')
const logger = require('logplease').create('services:nucleus')

/**
* https://nucleus.sh
@@ -67,7 +67,7 @@ class NucleusService extends BaseService {
logger.info('Nucleus enabled!')
logger.debug(this.appId)
} catch (err) {
logger.warn('๐Ÿ’” Error trying to start Nucleus!', err)
logger.warn('Nucleus setup failed!', err)
}
}


+ 2
- 2
src/electron/src/modules/services/rollbar.js View File

@@ -14,7 +14,7 @@ import { BaseService } from './base'
import { settings } from './settings'
import { nucleus } from './nucleus'

const logger = require('logplease').create('electron:scripts:services:rollbar')
const logger = require('logplease').create('services:rollbar')

/**
* https://rollbar.com
@@ -89,7 +89,7 @@ class RollbarService extends BaseService {
logger.info('Rollbar enabled!')
logger.debug(this.accessToken)
} catch (err) {
logger.warn('๐Ÿ’” Error trying to start Rollbar!', err)
logger.warn('Rollbar setup failed!', err)
}
}


+ 5
- 5
src/electron/src/modules/services/settings.js View File

@@ -27,7 +27,7 @@ class SettingsService extends BaseService {
* @type {string}
*/
get path() {
return memoize(() => paths.get('userData', 'settings.json'))('settings.path')
return memoize(() => paths.getPath('userData', 'settings.json'))('settings.path')
}

/**
@@ -118,10 +118,10 @@ class SettingsService extends BaseService {
},

folders: {
cropped: paths.get('temp'),
models: paths.get('userData', 'models'),
masks: paths.get('userData', 'masks'),
cli: paths.get('userData', 'dreampower'),
cropped: paths.getPath('temp'),
models: paths.getPath('userData', 'models'),
masks: paths.getPath('userData', 'masks'),
cli: paths.getPath('userData', 'dreampower'),
},

telemetry: {

+ 210
- 192
src/electron/src/modules/tools/fs.js View File

@@ -1,5 +1,8 @@
import path from 'path'
import fs from 'fs-extra'
import { basename, join } from 'path'
import {
statSync, readFileSync, writeFileSync, existsSync,
unlinkSync, createWriteStream, createReadStream,
} from 'fs-extra'
import { isNil } from 'lodash'
import mime from 'mime-types'
import EventBus from 'js-event-bus'
@@ -10,241 +13,256 @@ import unzipper from 'unzipper'
import deferred from 'deferred'
import sevenBin from '7zip-bin'
import { extractFull } from 'node-7z'
import { getAppResources } from './paths'
import { getAppResourcesPath } from './paths'
import { AppError } from '../app-error'

export default {
/**
* Returns the base64 of a dataURL
* @param {*} dataURL
*/
getBase64Data: (dataURL) => {
let encoded = dataURL.replace(/^data:(.*;base64,)?/, '')
const logger = require('logplease').create('electron:modules:tools:fs')

if (encoded.length % 4 > 0) {
encoded += '='.repeat(4 - (encoded.length % 4))
}
// eslint-disable-next-line node/no-deprecated-api
export * from 'fs-extra'

return encoded
},
/**
* Returns the base64 of a dataURL
* @param {*} dataURL
*/
export function getBase64Data(dataURL) {
let encoded = dataURL.replace(/^data:(.*;base64,)?/, '')

getInfo: (path) => {
const exists = this.exists(path)
const mimetype = mime.lookup(path)
const { name, ext, dir } = path.parse(path)
if (encoded.length % 4 > 0) {
encoded += '='.repeat(4 - (encoded.length % 4))
}

let size
return encoded
}

if (exists) {
const stats = fs.statSync(path)
size = stats.size / 1000000.0
}
/**
*
* @param {string} path
*/
export function getInfo(path) {
const exists = this.exists(path)
const mimetype = mime.lookup(path)
const { name, ext, dir } = path.parse(path)

let size

if (exists) {
const stats = statSync(path)
size = stats.size / 1000000.0
}

return {
exists,
name,
ext,
dir,
mimetype,
size,
}
}

return {
exists,
name,
ext,
dir,
mimetype,
size,
}
},
/**
*
* @param {string} path
* @param {string} encoding
*/
export function read(path, encoding = 'utf-8') {
return readFileSync(path, { encoding })
}

read: (path, encoding = 'utf-8') => fs.readFileSync(path, { encoding }),
/**
*
* @param {string} path
* @param {string} dataURL
*/
export function writeDataUrl(path, dataURL) {
const data = this.getBase64Data(dataURL)
return writeFileSync(path, data, 'base64')
}

writeDataUrl: (path, dataURL) => {
const data = this.getBase64Data(dataURL)
return fs.writeFileSync(path, data, 'base64')
},
/**
*
* @param {string} path
* @param {string} destinationPath
*/
export function extractZip(path, destinationPath) {
const def = deferred()

extractZip: (path, destinationPath) => {
const def = deferred()
const stream = createReadStream(path).pipe(unzipper.Extract({ path: destinationPath }))

const stream = fs
.createReadStream(path)
.pipe(unzipper.Extract({ path: destinationPath }))
stream.on('close', () => {
def.resolve()
})

stream.on('close', () => {
def.resolve()
})
stream.on('error', (err) => {
def.reject(err)
})

stream.on('error', (err) => {
def.reject(err)
return def.promise
}

/**
*
* @param {string} path
* @param {string} destinationPath
*/
export function extractSeven(path, destinationPath) {
const def = deferred()

let pathTo7zip

if (is.development) {
pathTo7zip = sevenBin.path7za
} else {
const binName = platform({
macos: '7za',
linux: '7za',
windows: '7za.exe',
})

return def.promise
},
pathTo7zip = getAppResourcesPath('7zip-bin', binName)
}

extractSeven: (path, destinationPath) => {
const def = deferred()
const seven = extractFull(path, destinationPath, {
$bin: pathTo7zip,
recursive: true,
})

let pathTo7zip
seven.on('end', () => {
def.resolve()
})

if (is.development) {
pathTo7zip = sevenBin.path7za
} else {
const binName = platform({
macos: '7za',
linux: '7za',
windows: '7za.exe',
})
seven.on('error', (err) => {
def.reject(err)
})

pathTo7zip = getAppResources('7zip-bin', binName)
}
return def.promise
}

const seven = extractFull(path, destinationPath, {
$bin: pathTo7zip,
recursive: true,
})
/**
*
* @param {string} url
* @param {Object} options
*/
export function download(url, options = {}) {
const bus = new EventBus()

seven.on('end', () => {
def.resolve()
})
// eslint-disable-next-line no-param-reassign
options = {
showSaveAs: false,
directory: api.app.getPath('downloads'),
filename: basename(url).split('?')[0].split('#')[0],
...options,
}

seven.on('error', (err) => {
def.reject(err)
})
let filepath = join(options.directory, options.filename)

return def.promise
},
/**
* @type {ReadStream}
*/
let stream

download: (url, options = {}) => {
const bus = new EventBus()
if (options.showSaveAs) {
filepath = api.dialog.showSaveDialogSync({
defaultPath: filepath,
})
}

// eslint-disable-next-line no-param-reassign
options = {
// showSaveAs: false,
directory: api.app.getPath('downloads'),
fileName: undefined,
...options,
const deleteFile = () => {
if (existsSync(filepath)) {
unlinkSync(filepath)
}
}

const fileName = options.fileName
|| path
.basename(url)
.split('?')[0]
.split('#')[0]
let filePath = path.join(options.directory, fileName)

const deleteFile = () => {
if (fs.existsSync(filePath)) {
// debug(`Deleting file ${filePath}`)
fs.unlinkSync(filePath)
}
}
axios.request({
url,
timeout: 5000,
responseType: 'stream',
maxContentLength: -1,
}).then((response) => {
const contentLength = response.data.headers['content-length'] || -1
const totalSize = filesize(contentLength, { exponent: 2, output: 'object' }).value

deleteFile()
const output = createWriteStream(filepath)

axios
.request({
url,
timeout: 5000,
responseType: 'stream',
maxContentLength: -1,
})
.then((response) => {
const contentLength = response.data.headers['content-length'] || -1
const mbTotal = filesize(contentLength, {
exponent: 2,
output: 'object',
}).value

const output = fs.createWriteStream(filePath)
const stream = response.data

const cancel = (err) => {
stream.destroy(err)
deleteFile()

if (!isNil(err)) {
console.warn('Download canceled due to an error', err)
bus.emit('error', null, err)
}
}

/*
debug('Downloading file and placing it in a writeStream', {
url,
fileName,
filePath,
contentLength,
mbTotal,
exists: fs.existsSync(filePath),
})
*/
stream = response.data

output.on('error', (err) => {
cancel(err)
})
stream.on('data', (chunk) => {
output.write(Buffer.from(chunk))

stream.on('data', (chunk) => {
output.write(Buffer.from(chunk))

if (contentLength > 0) {
const progress = output.bytesWritten / contentLength
const mbWritten = filesize(output.bytesWritten, {
exponent: 2,
output: 'object',
}).value

bus.emit('progress', null, {
progress,
mbWritten,
mbTotal,
})
} else {
const mbWritten = filesize(output.bytesWritten, {
exponent: 2,
output: 'object',
}).value

bus.emit('progress', null, {
progress: -1,
mbWritten,
mbTotal,
})
}
const written = filesize(output.bytesWritten, { exponent: 2, output: 'object' }).value

if (contentLength > 0) {
const progress = output.bytesWritten / contentLength

bus.emit('progress', null, {
progress,
written,
total: totalSize,
})
} else {
bus.emit('progress', null, {
progress: -1,
written,
total: -1,
})
}
})

stream.on('end', () => {
output.end()
stream.destroy()
stream.on('end', () => {
output.end()

if (!fs.existsSync(filePath)) {
filePath = undefined
}
if (!existsSync(filepath)) {
throw new AppError('The file was not saved correctly.', { title: 'Download failed.' })
}

bus.emit('end', null, filePath)
})
bus.emit('end', null, filepath)
})

stream.on('error', (err) => {
cancel(err)
})
stream.on('error', (err) => {
throw new AppError(err, { title: 'Download failed.' })
})

bus.on('cancel', () => {
// debug('Download canceled!')
cancel()
})
output.on('error', (err) => {
throw new AppError(err, { title: 'Download failed.' })
})

return true
})
.catch((err) => {
bus.emit('error', null, err)
})
bus.on('cancel', () => {
output.destroy()
stream.destroy()
deleteFile()

return bus
},
logger.info('Download canceled by user.')
bus.emit('end')
})

downloadAsync: (url, options = {}) => new Promise((resolve, reject) => {
return true
}).catch((err) => {
stream.destroy(err)
deleteFile()

logger.warn('Download canceled due to an error.', err)
bus.emit('error', null, err)
})

return bus
}

/**
*
* @param {string} url
* @param {Object} options
*/
export function downloadAsync(url, options = {}) {
return new Promise((resolve, reject) => {
const bus = this.download(url, options)

bus.on('end', (filePath) => {
resolve(filePath)
bus.on('end', (filepath) => {
resolve(filepath)
})

bus.on('error', (err) => {
reject(err)
})
}),

...fs,
})
}

+ 1
- 0
src/electron/src/modules/tools/index.js View File

@@ -11,6 +11,7 @@ import * as paths from './paths'
import * as shell from './shell'
import * as power from './power'

// eslint-disable-next-line import/no-cycle
export fs from './fs'
export { shell }
export { paths }

+ 20
- 20
src/electron/src/modules/tools/paths.js View File

@@ -16,77 +16,77 @@ import { settings } from '../services'
* Returns an absolute path depending on the parameters
*
* @param {string} name Name of the base path: https://electronjs.org/docs/all#appgetpathname
* @param {string} args Series of path segments to join into one path
* @param {...string} args Series of path segments to join into one path
*/
export const get = (name, ...args) => path.join(api.app.getPath(name), ...args)
export const getPath = (name, ...args) => path.join(api.app.getPath(name), ...args)

/**
*
* @param {...any} args
* @param {...string} args
*/
export const getApp = (...args) => {
export const getAppPath = (...args) => {
if (process.platform === 'darwin') {
// /Applications/DreamTime.app/Contents/MacOS/DreamTime
// /Applications/DreamTime.app/Contents
return get('exe', '..', '..', ...args)
return getPath('exe', '..', '..', ...args)
}

return get('exe', '..', ...args)
return getPath('exe', '..', ...args)
}

export const getAppResources = (...args) => {
export const getAppResourcesPath = (...args) => {
if (process.platform === 'darwin') {
return getApp('Resources', ...args)
return getAppPath('Resources', ...args)
}

return getApp('resources', ...args)
return getAppPath('resources', ...args)
}

export const getPower = (...args) => {
export const getPowerPath = (...args) => {
let folder = settings.folders.cli

if (!fs.existsSync(folder)) {
folder = get('userData', 'dreampower')
folder = getPath('userData', 'dreampower')
}

return path.join(folder, ...args)
}

export const getPowerCheckpoints = (...args) => getPower('checkpoints', ...args)
export const getCheckpointsPath = (...args) => getPowerPath('checkpoints', ...args)

export const getCrop = (...args) => {
export const getCropPath = (...args) => {
let folder = settings.folders.cropped

if (!fs.existsSync(folder)) {
folder = get('temp')
folder = getPath('temp')
}

return path.join(folder, ...args)
}

export const getModels = (...args) => {
export const getModelsPath = (...args) => {
let folder = settings.folders.models

if (!fs.existsSync(folder)) {
folder = get('userData', 'models')
folder = getPath('userData', 'models')
}

if (!fs.existsSync(folder)) {
folder = get('temp')
folder = getPath('temp')
}

return path.join(folder, ...args)
}

export const getMasks = (...args) => {
export const getMasksPath = (...args) => {
let folder = settings.folders.masks

if (!fs.existsSync(folder)) {
folder = get('userData', 'masks')
folder = getPath('userData', 'masks')
}

if (!fs.existsSync(folder)) {
folder = get('temp')
folder = getPath('temp')
}

return path.join(folder, ...args)

+ 7
- 7
src/electron/src/modules/tools/power.js View File

@@ -11,7 +11,7 @@ import { spawn } from 'child_process'
import EventBus from 'js-event-bus'
import deferred from 'deferred'
import semverRegex from 'semver-regex'
import { getPower } from './paths'
import { getPowerPath } from './paths'
import { settings } from '../services'

/**
@@ -82,11 +82,11 @@ export const transform = (job) => {
if (settings.processing.usePython) {
// python script
process = spawn('python3', args, {
cwd: getPower(),
cwd: getPowerPath(),
})
} else {
process = spawn(getPower('dreampower'), args, {
cwd: getPower(),
process = spawn(getPowerPath('dreampower'), args, {
cwd: getPowerPath(),
})
}

@@ -130,14 +130,14 @@ export const getVersion = () => {
if (settings.processing.usePython) {
// python script
process = spawn('python3', ['main.py', '--version'], {
cwd: getPower(),
cwd: getPowerPath(),
})
} else {
process = spawn(getPower('dreampower'), ['--version'])
process = spawn(getPowerPath('dreampower'), ['--version'])
}

process.on('error', () => {
def.resolve('')
def.resolve()
})

process.stdout.on('data', (data) => {

+ 2
- 2
src/electron/src/modules/tools/shell.js View File

@@ -10,12 +10,12 @@
import { isNil } from 'lodash'
import { is } from 'electron-utils'
import regedit from 'regedit'
import { getAppResources } from './paths'
import { getAppResourcesPath } from './paths'

export const hasWindowsMedia = () => {
if (is.windows && !is.development) {
regedit.setExternalVBSLocation(
getAppResources('vbs'),
getAppResourcesPath('vbs'),
)
}


+ 28
- 17
src/electron/src/modules/tools/system.js View File

@@ -18,10 +18,10 @@ import filesize from 'filesize'
import { is } from 'electron-utils'
import regedit from 'regedit'
import { nucleus } from '../services'
import { getAppResources, getPower, getPowerCheckpoints } from './paths'
import { getAppResourcesPath, getPowerPath, getCheckpointsPath } from './paths'
import { getVersion } from './power'

const logger = require('logplease').create('electron:modules:tools:system')
const logger = require('logplease').create('system')

class System {
/**
@@ -53,7 +53,6 @@ class System {
* @type {Object}
*/
requirements = {
all: false,
power: {
installed: false,
compatible: false,
@@ -102,11 +101,11 @@ class System {
*
*/
async scan() {
this.requirements.power.installed = this.hasPower
this.requirements.power.compatible = await this.hasCompatiblePower()
this.requirements.power.checkpoints = this.hasCheckpoints
this.requirements.power.installed = this._hasPower
this.requirements.power.compatible = await this._hasCompatiblePower()
this.requirements.power.checkpoints = this._hasCheckpoints

this.requirements.windows.media = await this.hasWindowsMedia()
this.requirements.windows.media = await this._hasWindowsMedia()

this.requirements.ram.recommended = this.memory.total >= 8589934592 // 8 GB
this.requirements.ram.minimum = this.memory.total >= 6442450944 // 6 GB
@@ -115,14 +114,17 @@ class System {
}

/**
* @return {Array}
* @type {Array}
*/
get graphics() {
return filter(this._graphics.controllers, { vendor: 'NVIDIA' })
}

get hasPower() {
const dirpath = getPower()
/**
* @type {boolean}
*/
get _hasPower() {
const dirpath = getPowerPath()

if (!isString(dirpath)) {
// how the fuck?
@@ -140,7 +142,7 @@ class System {
]

for (const bin of binaries) {
if (existsSync(getPower(bin))) {
if (existsSync(getPowerPath(bin))) {
return true
}
}
@@ -148,7 +150,10 @@ class System {
return false
}

async hasCompatiblePower() {
/**
* @return {boolean}
*/
async _hasCompatiblePower() {
if (!this.requirements.power.installed) {
return false
}
@@ -171,8 +176,11 @@ class System {
return true
}

get hasCheckpoints() {
const dirpath = getPowerCheckpoints()
/**
* @type {boolean}
*/
get _hasCheckpoints() {
const dirpath = getCheckpointsPath()

if (!existsSync(dirpath)) {
return false
@@ -182,7 +190,7 @@ class System {
const files = ['cm.lib', 'mm.lib', 'mn.lib']

for (const file of files) {
const filepath = getPowerCheckpoints(file)
const filepath = getCheckpointsPath(file)

if (!existsSync(filepath)) {
return false
@@ -199,7 +207,10 @@ class System {
return true
}

async hasWindowsMedia() {
/**
* @return {boolean}
*/
async _hasWindowsMedia() {
if (!is.windows) {
return true
}
@@ -214,7 +225,7 @@ class System {
if (!is.development) {
// regedit commands
regedit.setExternalVBSLocation(
getAppResources('vbs'),
getAppResourcesPath('vbs'),
)
}


+ 457
- 0
src/electron/src/modules/updater/base.js View File

@@ -0,0 +1,457 @@
// DreamTime.
// Copyright (C) DreamNet. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License 3.0 as published by
// the Free Software Foundation. See <https://www.gnu.org/licenses/gpl-3.0.html>
//
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

import {
isNil, isArray, isPlainObject, clone, find,
startsWith, filter, get, isEmpty,
} from 'lodash'
import axios from 'axios'
import compareVersions from 'compare-versions'
import deferred from 'deferred'
import filesize from 'filesize'
import delay from 'delay'
import { dialog } from 'electron'
import { platform } from 'electron-utils'
import { basename } from 'path'
import { nucleus } from '../services'
import { system } from '../tools'
import { getPath } from '../tools/paths'
import { existsSync, statSync, download } from '../tools/fs'
import { AppError } from '../app-error'

const logplease = require('logplease')

const extRegex = /(?:\.([^.]+))?$/

/**
* todo: don't just depend on github
* @type {string}
*/
const GITHUB_API = 'https://api.github.com/repos'

export class BaseUpdater {
/**
* @type {boolean}
*/
enabled = false

/**
* @type {logplease.Logger}
*/
_logger

/**
* @type {axios.AxiosInstance}
*/
_http

/**
* @type {Object}
*/
latest = {}

/**
* @type {Object}
*/
latestCompatible = {}

/**
* @type {string}
*/
_currentVersion

/**
* @type {Array}
*/
downloadUrls = []

/**
* @type {import('js-event-bus')}
*/
_downloadBus

/**
* @type {Object}
*/
update = {
active: false,
status: null,
progress: 0,
written: -1,
total: -1,
}

/**
* @type {string}
*/
get can() {
return !isNil(this.name) && !isNil(this.githubRepo)
}

/**
* @type {string}
*/
get name() {
return null
}

/**
* @type {string}
*/
get latestVersion() {
// eslint-disable-next-line camelcase
return this.latest ?.tag_name || 'v0.0.0'
}

/**
* @type {string}
*/
get latestCompatibleVersion() {
// eslint-disable-next-line camelcase
return this.latestCompatible ?.tag_name || 'v0.0.0'
}

/**
* @type {string}
*/
get currentVersion() {
return this._currentVersion
}

/**
* @type {boolean}
*/
get available() {
return compareVersions.compare(this.latestCompatibleVersion, this.currentVersion, '>')
}

/**
* @type {string}
*/
get githubRepo() {
return get(nucleus, `projects.${this.name}.repository.github`)
}

/**
* @type {string}
*/
get filename() {
if (this.downloadUrls.length === 0) {
return null
}

for (const url of this.downloadUrls) {
const filename = basename(url).split('?')[0].split('#')[0]

if (isEmpty(filename) || isNil(extRegex.exec(filename)[1])) {
// empty or no filename in url
continue
}

return filename
}

return null
}

/**
* @type {string}
*/
get platform() {
return platform({
macos: 'macos',
windows: 'windows',
linux: 'linux',
})
}

constructor() {
this._logger = logplease.create(`updater:${this.name}`)
}

/**
*
*/
async setup() {
this.enabled = false

if (!system.online) {
this._logger.warn('Updater disabled due of Internet connection.')
return
}

if (!nucleus.enabled) {
this._logger.warn('Updater disabled due of nucleus service.')
return
}

if (!this.can) {
this._logger.warn('Updater disabled due of requirements.')
return
}

try {
this._http = axios.create({
baseURL: `${GITHUB_API}/${this.githubRepo}`,
timeout: 3000,
})

await this._fetchReleases()

this.downloadUrls = this._getDownloadUrls()

this._logger.info(`Current: ${this.currentVersion} - Latest Compatible: ${this.latestCompatibleVersion}`)
this.enabled = true
} catch (err) {
this._logger.warn('Fetching releases failed!', err)
}

if (this.available) {
this.sendNotification()
}
}

/**
*
* @param {*} releases
*/
_getLatestCompatible(releases) {
return releases[0]
}

/**
*
*/
_getDownloadUrls() {
let urls
let asset

try {
urls = clone(nucleus.releases[this.name][this.latestVersion])
} catch (err) {
// not the best way, but it works
urls = []
}

if (isPlainObject(urls)) {
urls = urls[this.platform]
}

if (!isArray(urls)) {
urls = []
}

if (this.latest.assets.length === 1) {
[asset] = this.latest.assets
} else {
asset = find(this.latest.assets, (asset) => asset.name.includes(platform))
}

if (!isNil(asset)) {
// github download url at the end, it doesn't always work.
urls.push(asset.browser_download_url)
}

// for now we use only the http/https protocol
// todo: ipfs
urls = urls.filter((item) => startsWith(item, 'http'))

return urls
}

/**
*
* @param {string} status
* @param {number} progress
*/
_setUpdateProgress(status) {
this.update.active = true
this.update.status = status
this.update.progress = -1
}

/**
*
*/
_stopUpdateProgress() {
this.update = {
active: false,
status: null,
progress: 0,
written: 0,
total: 0,
}
}

/**
*
*/
async _fetchReleases() {
const response = await this._http.get('/releases')

// only final releases
const releases = filter(response.data, {
draft: false,
prerelease: false,
})

if (releases.length === 0) {
throw new AppError('No releases found!', { level: 'warning' })
}

[this.latest] = releases
this.latestCompatible = this._getLatestCompatible(releases)

if (isNil(this.latestCompatible)) {
throw new AppError('No compatible release found!', { level: 'warning ' })
}
}

/**
*
*/
async start() {
try {
let filepath = getPath('downloads', this.filename)

if (existsSync(filepath)) {
const useLocal = dialog.showMessageBoxSync({
type: 'question',
buttons: ['Yes', 'No, download it again'],
defaultId: 0,
title: 'Update.',
message: 'The update file was found on your computer. Do you want to use it?',
})

if (useLocal === 0) {
await this._install(filepath)
return
}
}

filepath = await this._download()

await this._install(filepath)
} finally {
this._stopUpdateProgress()
}
}

/**
*
*/
async _install(filepath) {
try {
this._setUpdateProgress('Installing...')

// avoid opening it while it is in use
await delay(1500)

await this.install(filepath)
} catch (err) {
this._logger.warn(`Error installing update from: ${filepath}`, err)
throw new AppError(err, { title: 'Update installation failed.', level: 'warning' })
}
}

/**
*
*/
async _download() {
if (!system.online) {
throw new AppError('You need to be connected to the Internet to download the updates.', { title: 'Update download failed.', level: 'warning' })
}

let filepath

for (const url of this.downloadUrls) {
this._setUpdateProgress('Downloading...')

try {
// eslint-disable-next-line no-await-in-loop
filepath = await this._downloadFrom(url)

if (isNil(filepath)) {
// cancelled by user
this._stopUpdateProgress()
return null
}

return filepath
} catch (err) {
this._logger.warn(`Error downloading update from: ${url}`, err)
continue
}
}

throw new AppError('Please download the update manually or verify the configuration of your VPN/Firewall.', { title: 'Update download failed.', level: 'warning' })
}

/**
*
* @param {string} url
*/
_downloadFrom(url) {
this._logger.info(`Downloading update from: ${url}`)
const def = deferred()

this._downloadBus = download(url, {
filename: this.filename,
})

this._downloadBus.on('progress', (payload) => {
this.update.progress = payload.progress
this.update.total = payload.mbTotal
this.update.written = payload.mbWritten
})

this._downloadBus.on('error', (err) => {
this._downloadBus = null
def.reject(err)
})

this._downloadBus.on('end', (filepath) => {
const stats = statSync(filepath)
const size = filesize(stats.size, { exponent: 2, output: 'object' })

if (size.value < 20) {
// todo: better corrupt detection
def.reject(new AppError('The file is corrupt.', { title: 'Update download failed.', level: 'warning' }))
}

this._downloadBus = null
def.resolve(filepath)
})

return def.promise
}

/**
*
*/
cancel() {
if (isNil(this._download)) {
return
}

this._downloadBus.emit('cancel')
}

/**
*
* @param {string} filepath
*/
// eslint-disable-next-line no-empty-function
async install(filepath) { }

/**
*
*/
sendNotification() { }
}

+ 77
- 0
src/electron/src/modules/updater/checkpoints.js View File

@@ -0,0 +1,77 @@
// DreamTime.
// Copyright (C) DreamNet. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License 3.0 as published by
// the Free Software Foundation. See <https://www.gnu.org/licenses/gpl-3.0.html>
//
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

import { app, Notification } from 'electron'
import { activeWindow } from 'electron-utils'
import { BaseUpdater } from './base'
import { AppError } from '../app-error'
import { system } from '../tools/system'
import { getCheckpointsPath, getPowerPath } from '../tools/paths'
import { existsSync, read, extractZip } from '../tools/fs'

class CheckpointsUpdater extends BaseUpdater {
/**
* @type {string}
*/
get name() {
return 'checkpoints'
}

/**
* @type {string}
*/
get currentVersion() {
if (!system.requirements.power.checkpoints) {
return 'v0.0.0'
}

const filepath = getCheckpointsPath('version')

if (!existsSync(filepath)) {
return 'v0.0.1'
}

const version = read(filepath) || 'v0.0.1'

return version.trim()
}

/**
*
* @param {string} filepath
*/
async install(filepath) {
await extractZip(filepath, getPowerPath())

// restart!
app.relaunch()
app.quit()
}

/**
*
*/
sendNotification() {
const notification = new Notification(
{
title: `๐ŸŽ‰ Checkpoints ${this.latestCompatibleVersion} available!`,
body: 'A new version of the Checkpoints is available.',
},
)

notification.show()

notification.on('click', () => {
// window.$redirect('/system/about')
activeWindow().focus()
})
}
}

export const checkpoints = new CheckpointsUpdater()

+ 127
- 0
src/electron/src/modules/updater/dreampower.js View File

@@ -0,0 +1,127 @@
// DreamTime.
// Copyright (C) DreamNet. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License 3.0 as published by
// the Free Software Foundation. See <https://www.gnu.org/licenses/gpl-3.0.html>
//
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

import { isNil, get } from 'lodash'
import compareVersions from 'compare-versions'
import { app, Notification } from 'electron'
import { activeWindow } from 'electron-utils'
import { BaseUpdater } from './base'
import { AppError } from '../app-error'
import { settings } from '../services/settings'
import { nucleus } from '../services/nucleus'
import { system } from '../tools/system'
import { getVersion } from '../tools/power'
import { extractSeven } from '../tools/fs'
import { getPowerPath } from '../tools/paths'

class DreamPowerUpdater extends BaseUpdater {
/**
* @type {string}
*/
get name() {
return 'dreampower'
}

/**
* @type {string}
*/
get platform() {
let platform = super.platform

if (platform === 'macos' || settings.processing.device === 'CPU') {
platform = `${platform}-cpuonly`
} else {
platform = `${platform}-any`
}

return platform
}

/**
* @return {string}
*/
async _getCurrentVersion() {
if (!system.requirements.power.installed) {
return 'v0.0.0'
}

const version = await getVersion()

if (isNil(version)) {
return 'v1.1.0'
}

return version
}

/**
*
* @param {*} releases
*/
_getLatestCompatible(releases) {
const minimum = get(nucleus, `projects.dreamtime.releases.v${process.env.npm_package_version}.dreampower.minimum`, 'v1.2.3')
const maximum = get(nucleus, `projects.dreamtime.releases.v${process.env.npm_package_version}.dreampower.maximum`)

for (const release of releases) {
if (compareVersions.compare(release.tag_name, minimum, '<')) {
continue
}

if (!isNil(maximum) && compareVersions.compare(release.tag_name, maximum, '>')) {
continue
}

return release
}

return null
}

/**
*
*/
async setup() {
this._currentVersion = await this._getCurrentVersion()

await super.setup()
}

/**
*
* @param {string} filepath
*/
async install(filepath) {
await extractSeven(filepath, getPowerPath())

// restart!
app.relaunch()
app.quit()
}

/**
*
*/
sendNotification() {
const notification = new Notification(
{
title: `๐ŸŽ‰ DreamPower ${this.latestCompatibleVersion} available!`,
body: 'A new version of DreamPower is available.',
},
)

notification.show()

notification.on('click', () => {
// window.$redirect('/system/about')
activeWindow().focus()
})
}
}

export const dreampower = new DreamPowerUpdater()

+ 70
- 0
src/electron/src/modules/updater/dreamtime.js View File

@@ -0,0 +1,70 @@
// DreamTime.
// Copyright (C) DreamNet. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License 3.0 as published by
// the Free Software Foundation. See <https://www.gnu.org/licenses/gpl-3.0.html>
//
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

import { shell, app, Notification } from 'electron'
import { dirname } from 'path'
import delay from 'delay'
import { activeWindow } from 'electron-utils'
import { BaseUpdater } from './base'
import { AppError } from '../app-error'

class DreamTimeUpdater extends BaseUpdater {
/**
* @type {string}
*/
get name() {
return 'dreamtime'
}

/**
* @type {string}
*/
get currentVersion() {
return `v${process.env.npm_package_version}`
}

/**
*
* @param {string} filepath
*/
async install(filepath) {
try {
shell.openExternal(filepath)

await delay(1500)

// close the program to update correctly
app.quit()
} catch (error) {
shell.openItem(dirname(filepath))
throw new AppError('Update installation failed. The folder where the update is located will open.', { error })
}
}

/**
*
*/
sendNotification() {
const notification = new Notification(
{
title: `๐ŸŽ‰ DreamTime ${this.latestCompatibleVersion} available!`,
body: 'A new version of DreamTime is available.',
},
)

notification.show()

notification.on('click', () => {
// window.$redirect('/system/about')
activeWindow().focus()
})
}
}

export const dreamtime = new DreamTimeUpdater()

src/modules/errors/index.js → src/electron/src/modules/updater/index.js View File

@@ -7,4 +7,6 @@
//
// Written by Ivan Bravo Bravo <ivan@dreamnet.tech>, 2019.

export { AppError } from './app-error'
export { dreamtime } from './dreamtime'
export { dreampower } from './dreampower'
export { checkpoints } from './checkpoints'

+ 5
- 4
src/middleware/checks.js View File

@@ -9,7 +9,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { platform } from '~/modules'
const { settings } = $provider.services
const { system } = $provider.tools

/**
* Detects if the user has what it takes to run the program,
@@ -18,7 +19,7 @@ import { platform } from '~/modules'
export default function ({ route, redirect }) {
window.$redirect = redirect

if ($settings.welcome) {
if (settings.welcome) {
// First time execution!
if (route.path !== '/system/welcome') {
redirect('/system/welcome')
@@ -27,7 +28,7 @@ export default function ({ route, redirect }) {
return
}

if (!platform.requirements.cli) {
if (!system.requirements.power.installed) {
// DreamPower is missing
if (
!route.path.includes('/system/settings')
@@ -39,7 +40,7 @@ export default function ({ route, redirect }) {
return
}

if (!platform.requirements.checkpoints) {
if (!system.requirements.power.checkpoints) {
// Checkpoints are missing
if (route.path !== '/system/about') {
redirect('/system/about#checkpoints')

+ 2
- 5
src/mixins/BaseMixin.js View File

@@ -1,6 +1,6 @@
import _ from 'lodash'
import tippy from 'tippy.js'
import { updater, nudify } from '~/modules'
import { nudify } from '~/modules'

export default {
directives: {
@@ -22,10 +22,7 @@ export default {
filters: {},

data: () => ({
// $_dream: dream,

$nudify: nudify,
$updater: updater,
$settings,
$settings: $provider.services.settings,
}),
}

+ 4
- 4
src/modules/dream.js View File

@@ -6,9 +6,9 @@ export default {
*
*/
init() {
this.name = process.env.APP_NAME
this.version = process.env.APP_VERSION
this.status = process.env.APP_STATUS
this.settings = $nucleus
this.name = process.env.npm_package_displayName
this.version = `v${process.env.npm_package_version}`
this.status = 'stable'
this.settings = $provider.services.nucleus
},
}

+ 15
- 8
src/modules/file.js View File

@@ -5,6 +5,13 @@ import path from 'path'
/* eslint-disable-next-line */
const debug = require('debug').default('app:modules:file')

const {
writeDataUrl, downloadAsync, getInfo, unlinkSync,
read, copySync,
} = $provider.tools.fs

const { getPath } = $provider.tools.paths

export default class File {
constructor(path) {
this.reload(path)
@@ -16,7 +23,7 @@ export default class File {
* @param {*} dataURL
*/
static async fromDataURL(path, dataURL) {
await $tools.fs.write(path, dataURL)
await writeDataUrl(path, dataURL)
return new this(path)
}

@@ -32,8 +39,8 @@ export default class File {
*
*/
static async fromURL(url) {
const filePath = await $tools.fs.downloadAsync(url, {
directory: $tools.paths.get('temp'),
const filePath = await downloadAsync(url, {
directory: getPath('temp'),
})

return new this(filePath)
@@ -58,7 +65,7 @@ export default class File {
filePath = this.getPath()
}

const info = $tools.fs.getInfo(filePath)
const info = getInfo(filePath)

this.name = info.name
this.ext = info.ext
@@ -125,7 +132,7 @@ export default class File {
return
}

$tools.fs.unlink(this.getPath())
unlinkSync(this.getPath())
this.reload()
}

@@ -137,7 +144,7 @@ export default class File {
return undefined
}

const data = await $tools.fs.read(this.getPath(), 'base64')
const data = await read(this.getPath(), 'base64')
return `data:${this.getMimetype()};base64,${data}`
}

@@ -145,7 +152,7 @@ export default class File {
*
*/
async writeDataURL(dataURL) {
await $tools.fs.writeDataURL(this.getPath(), dataURL)
await writeDataUrl(this.getPath(), dataURL)
this.reload()
}

@@ -154,6 +161,6 @@ export default class File {
* @param {*} targetPath
*/
async copy(targetPath) {
await $tools.fs.copy(this.getPath(), targetPath)
await copySync(this.getPath(), targetPath)
}
}

+ 2
- 4
src/modules/index.js View File

@@ -1,8 +1,6 @@
export { WebError } from './web-error'

export { default as File } from './file'
export { default as Timer } from './timer'
export { default as WebError } from './web-error'

export { default as nudify } from './nudify'
export { default as platform } from './platform'