Browse Source

A lot of improvements.

tags/v1.4.4
Ivan Bravo Bravo 7 months ago
parent
commit
89bfbeb3ec
93 changed files with 1699 additions and 1774 deletions
  1. 1
    2
      src/.babelrc
  2. 3
    5
      src/.eslintrc.js
  3. 1
    1
      src/assets/css/components/_box.scss
  4. 1
    1
      src/assets/css/components/_form.scss
  5. 1
    1
      src/assets/css/components/_notification.scss
  6. 66
    0
      src/assets/css/components/_wizard.scss
  7. 1
    0
      src/assets/css/components/all.scss
  8. 28
    1
      src/assets/css/reset/_libs.scss
  9. 0
    1
      src/assets/css/reset/fonts.scss
  10. 34
    8
      src/components/Layout/Navbar.vue
  11. 0
    158
      src/components/Layout/Navigation.vue
  12. 16
    12
      src/components/Layout/Queuebar.vue
  13. 4
    4
      src/components/Layout/Topbar.vue
  14. 4
    4
      src/components/Layout/index.js
  15. 60
    107
      src/components/Nudity/PhotoRun.vue
  16. 15
    12
      src/components/Nudity/Upload.vue
  17. 1
    2
      src/components/Settings/Preference.vue
  18. 2
    2
      src/components/Settings/SettingsPreferences.vue
  19. 0
    4
      src/components/UI/AppUpdate.vue
  20. 1
    1
      src/components/UI/BoxItem.vue
  21. 5
    11
      src/components/UI/ProjectUpdate.vue
  22. 1
    7
      src/electron-builder.js
  23. 14
    9
      src/electron/src/index.js
  24. 1
    1
      src/electron/src/modules/app-error.js
  25. 1
    1
      src/electron/src/modules/services/base.js
  26. 29
    55
      src/electron/src/modules/settings.js
  27. 1
    1
      src/electron/src/modules/tools/fs.js
  28. 3
    1
      src/electron/src/modules/tools/paths.js
  29. 58
    51
      src/electron/src/modules/tools/power.js
  30. 1
    1
      src/electron/src/modules/tools/system.js
  31. 2
    3
      src/electron/src/provider.js
  32. 7
    5
      src/layouts/default.vue
  33. 3
    1
      src/layouts/wizard.vue
  34. 0
    40
      src/middleware/checks.js
  35. 2
    14
      src/middleware/wizard.js
  36. 15
    14
      src/mixins/BaseMixin.js
  37. 17
    40
      src/mixins/VModel.js
  38. 0
    219
      src/modules/app-error.js
  39. 28
    36
      src/modules/config/cli-errors.json
  40. 6
    67
      src/modules/consola/consola.js
  41. 84
    0
      src/modules/consola/errors.js
  42. 9
    12
      src/modules/consola/index.js
  43. 262
    0
      src/modules/consola/log.js
  44. 16
    6
      src/modules/dream.js
  45. 93
    36
      src/modules/file.js
  46. 0
    45
      src/modules/helpers.js
  47. 1
    0
      src/modules/index.js
  48. 12
    8
      src/modules/nudify/nudify-store.js
  49. 25
    15
      src/modules/nudify/nudify.js
  50. 30
    26
      src/modules/nudify/photo-run.js
  51. 14
    26
      src/modules/nudify/photo.js
  52. 17
    19
      src/modules/services/logrocket.js
  53. 7
    5
      src/modules/services/nucleus.js
  54. 9
    8
      src/modules/services/rollbar.js
  55. 54
    0
      src/modules/system/achievements.js
  56. 0
    147
      src/modules/system/errors.js
  57. 2
    4
      src/modules/system/index.js
  58. 0
    214
      src/modules/system/log.js
  59. 14
    13
      src/modules/system/requirements.js
  60. 94
    0
      src/modules/system/settings.js
  61. 10
    7
      src/modules/timer.js
  62. 86
    0
      src/modules/tutorial.js
  63. 16
    13
      src/modules/updater/base.js
  64. 2
    3
      src/modules/updater/dreampower.js
  65. 5
    3
      src/modules/updater/dreamtime.js
  66. 151
    30
      src/nuxt.config.js
  67. 9
    14
      src/package.json
  68. 1
    1
      src/package.min.json
  69. 10
    2
      src/pages/games/badtime.vue
  70. 17
    5
      src/pages/index.vue
  71. 2
    2
      src/pages/nudify/_id.vue
  72. 1
    1
      src/pages/nudify/_id/crop.vue
  73. 1
    1
      src/pages/nudify/_id/editor.vue
  74. 1
    1
      src/pages/nudify/_id/overlay.vue
  75. 11
    13
      src/pages/settings.vue
  76. 16
    16
      src/pages/settings/app.vue
  77. 6
    3
      src/pages/settings/preferences.vue
  78. 1
    1
      src/pages/welcome.vue
  79. 2
    2
      src/pages/wizard/checkpoints.vue
  80. 47
    0
      src/pages/wizard/dreamtime.vue
  81. 22
    62
      src/pages/wizard/power.vue
  82. 14
    16
      src/pages/wizard/telemetry.vue
  83. 0
    2
      src/pages/wizard/tos.vue
  84. 0
    2
      src/pages/wizard/welcome.vue
  85. 38
    0
      src/plugins/binds.js
  86. 6
    28
      src/plugins/boot.js
  87. 1
    0
      src/plugins/fontawesome.js
  88. 15
    27
      src/plugins/setup.js
  89. 1
    0
      src/scripts/release.js
  90. 22
    22
      src/tailwind.config.js
  91. 2
    0
      src/test/feature/nudify.js
  92. 1
    0
      src/workers/fs/index.js
  93. 6
    10
      src/workers/fs/worker.js

+ 1
- 2
src/.babelrc View File

@@ -4,8 +4,7 @@
"@babel/preset-env",
{
"targets": {
"node": "10",
"electron": "7"
"node": "10"
}
}
]

+ 3
- 5
src/.eslintrc.js View File

@@ -18,11 +18,10 @@ module.exports = {
globals: {
$provider: false,
AppError: false,
LogError: false,
LogEvent: false,
Warning: false,
Exception: false,
consola: false,
Consola: false,
consola: false
},
parserOptions: {
parser: "babel-eslint",
@@ -43,7 +42,7 @@ module.exports = {
"comma-dangle": "warn",
"global-require": "off",
"import/default": "warn",
"import/no-webpack-loader-syntax": "warn",
"import/no-webpack-loader-syntax": "off",
"import/order": ['error'],
"import/prefer-default-export": "off",
"import/no-extraneous-dependencies": "off",
@@ -72,7 +71,6 @@ module.exports = {
"no-continue": "off",
"no-debugger": "error",
"no-lone-blocks": "error",
"no-param-reassign": "off",
"no-restricted-globals": "warn",
"no-restricted-syntax": "off",
"no-shadow": "off",

+ 1
- 1
src/assets/css/components/_box.scss View File

@@ -27,7 +27,7 @@
@apply px-4 pt-4;

.title {
@apply text-lg font-bold text-white;
@apply text-lg font-semibold text-generic-200;
}

.subtitle {

+ 1
- 1
src/assets/css/components/_form.scss View File

@@ -32,7 +32,7 @@
}

&::placeholder {
@apply text-generic-700;
@apply text-generic-900;
}

&[disabled] {

+ 1
- 1
src/assets/css/components/_notification.scss View File

@@ -11,7 +11,7 @@

.notification {
@apply mb-4 py-2 px-4 border-2 border-dark-100 rounded-sm;
@apply bg-transparent text-generic-100 font-bold;
@apply bg-transparent text-generic-100;

a {
@apply underline;

+ 66
- 0
src/assets/css/components/_wizard.scss View File

@@ -0,0 +1,66 @@
/*
* 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>, 2020.
*/
.wizard-project {
.project__content {
@apply flex mb-6 pb-6 border-b border-dark-500;

.project__overview {
@apply flex-1 flex flex-col justify-center items-center;

figure {
@apply mb-6 text-6xl;

img {
height: 100px;
}
}

h1 {
@apply text-2xl text-white font-bold;
}

h2 {
@apply text-lg;
}

.project__navigation {
@apply mt-6;

.button {
&:not(:last-child) {
@apply mr-2;
}
}
}
}

.project__description {
@apply flex-1 flex flex-col justify-center;

p {
@apply text-xl mb-6;
}
}
}

.project__installation {
@apply flex;

.project__update {
@apply flex-1;
}

.project__settings {
@apply flex-1;
}
}
}

+ 1
- 0
src/assets/css/components/all.scss View File

@@ -5,3 +5,4 @@
@import './form';
@import './notification';
@import './markdown';
@import './wizard';

+ 28
- 1
src/assets/css/reset/_libs.scss View File

@@ -23,21 +23,48 @@

.swal2-html-container {
pre {
@apply text-xs overflow-auto bg-gray-300 p-2;
@apply text-xs overflow-auto bg-black p-2;
max-height: 100px;
}
}

.swal2-container.swal2-backdrop-show {
backdrop-filter: blur(6px);
transition: all 0.1s;
}

.swal2-footer {
code {
@apply text-sm text-center;
}
}

.swal2-popup {
@apply bg-dark-600 border border-dark-100 border-solid shadow-lg;
}

.vue-slider {
@apply w-full #{!important};
}

.vue-slider-process {
@apply bg-primary-500 #{!important};
}

.introjs-tooltip {
@apply bg-dark-500-90 #{!important};
min-width: 350px !important;
max-width: 400px !important;
}

.introjs-arrow {
//@apply bg-dark-500-90 #{!important};
}

.introjs-helperLayer {
background-color: transparent !important;
}

.introjs-overlay {
backdrop-filter: blur(10px);
}

+ 0
- 1
src/assets/css/reset/fonts.scss View File

@@ -1 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700|Roboto+Slab:300,400,500,600,700');

+ 34
- 8
src/components/Layout/Navbar.vue View File

@@ -5,16 +5,28 @@
Nudify
</nuxt-link>

<nuxt-link class="navbar__item" to="/settings">
<nuxt-link id="settings" class="navbar__item" to="/settings">
Settings
</nuxt-link>

<a class="navbar__item" :href="manualURL" target="_blank">
<a id="guide" class="navbar__item" :href="manualURL" target="_blank">
Help
</a>

<nuxt-link v-if="unlockedBadTime" class="navbar__item" to="/games/badtime">
Bad Time
</nuxt-link>

<a v-if="isDev" class="navbar__item" @click.prevent="createError">
Error
Force Error
</a>

<a v-if="isDev" href="https://google.com" class="navbar__item">
External Page
</a>

<a v-if="isDev" href="https://google.com" target="_blank" class="navbar__item">
Popup
</a>
</div>

@@ -35,10 +47,15 @@
</template>

<script>
import { requirements } from '~/modules/system'
import { requirements, settings } from '~/modules/system'
import { nucleus } from '~/modules/services'
import { events } from '~/modules'

export default {
data: () => ({
unlockedBadTime: settings.achievements.badtime,
}),

computed: {
canNudify() {
return requirements.canNudify
@@ -49,7 +66,7 @@ export default {
},

manualURL() {
return nucleus.urls?.docs?.manual || 'https://forum.dreamnet.tech/d/32-dreamtime-manual'
return nucleus.urls?.docs?.manual || 'https://time.dreamnet.tech/docs/guide/upload'
},

isDev() {
@@ -57,10 +74,15 @@ export default {
},
},

mounted() {
events.on('achievements.badtime', () => {
this.unlockedBadTime = true
})
},

methods: {
createError() {
// throw new Error('User Interface test error.')
throw new Warning('Warning Test')
throw new Error('UI TEST ERROR')
},
},
}
@@ -74,7 +96,11 @@ export default {

.navbar__left,
.navbar__right {
@apply flex-1 flex items-center;
@apply flex items-center;
}

.navbar__left {
@apply flex-1 mr-2;
}

.navbar__right {

+ 0
- 158
src/components/Layout/Navigation.vue View File

@@ -1,158 +0,0 @@
<template>
<div class="layout-menu">
<div :class="{ 'is-active': isActive }" class="navbar">
<!-- App Navigation -->
<section class="menu-section">
<nav class="menu-items">
<nuxt-link v-if="canNudify" to="/" class="menu-item">
<span class="icon">๐Ÿ“ท</span>
<span>Nudify</span>
</nuxt-link>

<nuxt-link to="/system/about" class="menu-item">
<span class="icon">๐ŸŒŒ</span>
<span>About</span>
</nuxt-link>

<nuxt-link to="/system/settings/processing" class="menu-item">
<span class="icon">๐Ÿ”ง</span>
<span>Settings</span>
</nuxt-link>
</nav>
</section>

<!-- Developer Navigation -->
<section v-if="isDev" class="menu-section">
<nav class="menu-items" />
</section>
</div>
</div>
</template>

<script>
import { requirements } from '~/modules/system'

const { settings } = $provider

export default {
computed: {
canNudify() {
return requirements.canNudify
},

isDev() {
return process.env.NODE_ENV === 'development'
},

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

methods: {
testBug() {
throw new Error('wow much error')
},
},
}
</script>

<style lang="scss" scoped>
@keyframes navShowAnim {
0% {
left: -200px;
}

100% {
left: 0;
}
}

.layout-menu {
@apply pb-6 shadow h-screen bg-dark-500 relative;
@apply border-r border-dark-300;
width: 200px;

.menu {
@apply absolute top-0 bottom-0;
left: -200px;
width: inherit;

&.is-active {
animation-name: navShowAnim;
animation-fill-mode: forwards;
animation-duration: 0.5s;
animation-timing-function: ease-in-out;
}
}

.menu-header {
@apply mb-4 text-gray-300 flex flex-col items-center justify-center;
animation: 20s ease-in-out infinite bgAnim;
height: 70px;

background: rgb(99, 66, 245);

background: linear-gradient(
40deg,
rgba(99, 66, 245, 1) 0%,
rgba(239, 125, 199, 1) 100%
);

background-size: 200% 100%;

/*
clip-path: polygon(
50% 0%,
100% 0,
100% 85%,
75% 100%,
25% 100%,
0 85%,
0 0
);
*/

.header-title {
@apply text-white text-xl font-bold;
}

.header-greetings {
@apply text-sm;
}
}

.menu-section {
@apply mb-4;
}

.section-title {
@apply text-center font-bold;
}

.menu-items {
.menu-item {
@apply border-l-4 border-transparent pl-4 font-semibold flex items-center;
height: 50px;
transition: all 0.1s ease-in-out;

.icon {
@apply text-center mr-2;
filter: grayscale(100%);
width: 22px;
transition: all 0.1s ease-in-out;
}

&:hover,
&.nuxt-link-exact-active {
@apply text-primary-500 border-primary-500;

.icon {
filter: unset;
}
}
}
}
}
</style>

src/components/Layout/Jobbar.vue → src/components/Layout/Queuebar.vue View File

@@ -1,6 +1,6 @@
<template>
<div class="layout__jobbar">
<section>
<div id="queuebar" class="layout__jobbar">
<section id="queuebar-running">
<div class="section__header">
<div class="section__title">
<span class="icon"><font-awesome-icon icon="running" /></span>
@@ -31,12 +31,12 @@
class="job"
:class="{ 'job--running': photo.running }"
@click.prevent="openJob(photo.id)">
<img :src="photo.file.dataURL">
<img :src="photo.file.path" data-private>
</figure>
</div>
</section>

<section>
<section id="queuebar-pending">
<div class="section__header">
<div class="section__title">
<span class="icon"><font-awesome-icon icon="clipboard-list" /></span>
@@ -66,12 +66,12 @@
:key="index"
class="job"
@click.prevent="openJob(photo.id)">
<img :src="photo.file.dataURL">
<img :src="photo.file.path" data-private>
</figure>
</div>
</section>

<section>
<section id="queuebar-finished">
<div class="section__header">
<div class="section__title">
<span class="icon"><font-awesome-icon icon="clipboard-check" /></span>
@@ -102,7 +102,7 @@
class="job"
:class="{ 'job--failed': photo.failed }"
@click.prevent="openJob(photo.id)">
<img :src="photo.file.dataURL">
<img :src="photo.file.path" data-private>
</figure>
</div>
</section>
@@ -167,7 +167,7 @@ section {
}

.section__actions {
@apply flex flex-1 justify-end ml-2;
@apply flex flex-1 justify-end ml-2 z-10 bg-dark-500;

.button {
@apply ml-2;
@@ -180,11 +180,15 @@ section {
@apply px-4 py-2 overflow-y-auto max-h-full;

.job {
@apply inline-block mb-2 mr-2 cursor-pointer;
width: 48px;
height: 48px;
@apply inline-block mb-2 cursor-pointer;
width: 47px;
height: 47px;
transition: all .1s ease-in-out;

&:not(:nth-child(3n)) {
@apply mr-2;
}

&.job--running {
img {
@apply border-primary-500;
@@ -199,7 +203,7 @@ section {

&:hover {
@apply z-30;
transform: scale(1.5)
transform: scale(1.3)
}

img {

+ 4
- 4
src/components/Layout/Topbar.vue View File

@@ -11,7 +11,7 @@

<div v-show="badTime" class="topbar__badtime">
<img src="~/assets/images/games/sans.png">
here we go.
i don't like what you are doing.
</div>
</div>

@@ -32,7 +32,7 @@
</template>

<script>
import moment from 'moment'
import dayjs from 'dayjs'

const { activeWindow, api } = $provider.util

@@ -43,7 +43,7 @@ export default {

computed: {
greetings() {
const hours = moment().hours()
const hours = dayjs().hour()

if (hours >= 6 && hours <= 11) {
return 'โ˜• Good morning'
@@ -62,7 +62,7 @@ export default {
},

mounted() {
this.$router.afterEach((to, from) => {
this.$router.afterEach((to) => {
if (to.path === '/games/badtime') {
this.$dream.name = 'BadDreamTime'
this.badTime = true

+ 4
- 4
src/components/Layout/index.js View File

@@ -2,8 +2,8 @@ import Vue from 'vue'

import LayoutTopbar from './Topbar'
import LayoutNavbar from './Navbar'
import LayoutJobbar from './Jobbar'
import LayoutQueuebar from './Queuebar'

Vue.component('layout-topbar', LayoutTopbar)
Vue.component('layout-navbar', LayoutNavbar)
Vue.component('layout-jobbar', LayoutJobbar)
Vue.component('LayoutTopbar', LayoutTopbar)
Vue.component('LayoutNavbar', LayoutNavbar)
Vue.component('LayoutQueuebar', LayoutQueuebar)

+ 60
- 107
src/components/Nudity/PhotoRun.vue View File

@@ -1,23 +1,32 @@
<template>
<div class="c-photo-run" :style="previewStyle">
<div v-if="run.preferences.body.randomize || run.preferences.body.progressive.enabled" class="run__details">
<table class="table">
<tr>
<th>Boobs size</th>
<th>Areola size</th>
<th>Nipple size</th>
<th>Vagina size</th>
<th>Pubic hair</th>
</tr>
<tr>
<td>{{ Number(run.preferences.body.boobs.size).toFixed(2) }}</td>
<td>{{ Number(run.preferences.body.areola.size).toFixed(2) }}</td>
<td>{{ Number(run.preferences.body.nipple.size).toFixed(2) }}</td>
<td>{{ Number(run.preferences.body.vagina.size).toFixed(2) }}</td>
<td>{{ Number(run.preferences.body.pubicHair.size).toFixed(2) }}</td>
</tr>
</table>
<div class="c-photo-run" :style="previewStyle" data-private>
<div v-if="run.preferences.body.randomize || run.preferences.body.progressive.enabled" class="run__preferences">
<div class="preference">
<span>Boobs</span>
<span>{{ run.preferences.body.boobs.size | fixedValue }}</span>
</div>

<div class="preference">
<span>Areola</span>
<span>{{ run.preferences.body.areola.size | fixedValue }}</span>
</div>

<div class="preference">
<span>Nipple</span>
<span>{{ run.preferences.body.nipple.size | fixedValue }}</span>
</div>

<div class="preference">
<span>Vagina</span>
<span>{{ run.preferences.body.vagina.size | fixedValue }}</span>
</div>

<div class="preference">
<span>Pubic hair</span>
<span>{{ run.preferences.body.pubicHair.size | fixedValue }}</span>
</div>
</div>

<div class="run__content">
<div v-if="run.running" class="content__item">
<p class="text-white">
@@ -70,12 +79,6 @@
</button>
</div>

<div v-if="run.preferences.body.randomize || run.preferences.body.progressive.enabled" class="content__item">
<button v-tooltip="'View preferences'" class="button button--info button--sm" @click.prevent="$refs.preferencesDialog.showModal()">
<font-awesome-icon icon="sliders-h" />
</button>
</div>

<div class="content__item">
<button v-tooltip="'View terminal'" class="button button--sm" @click.prevent="$refs.terminalDialog.showModal()">
<font-awesome-icon icon="terminal" />
@@ -87,13 +90,13 @@
<dialog ref="maskfinDialog">
<div class="dialog__content dialog__maskfin">
<div class="maskfin__preview">
<img :src="run.maskfinFile.dataURL">
<img :src="run.maskfinFile.path">
</div>

<div class="maskfin__description">
<p>This is the Maskfin, a mask that represents in layers the areas that the algorithm will replace with the fake nude.</p>
<p>Click on the "Add to queue" button to add it as an additional photo, edit the layers and continue with the nudification. You can also save it to your computer, edit it with an external program and continue the nudification manually.</p>
<p>For more information please consult the <a :href="manualURL" target="_blank">manual</a>.</p>
<p>For more information please consult the <a :href="manualURL" target="_blank">guide</a>.</p>
</div>

<div class="dialog__buttons">
@@ -128,39 +131,6 @@
</div>
</div>
</dialog>

<!-- Preferences Dialog -->
<dialog ref="preferencesDialog">
<div class="dialog__content">
<table class="table mb-2">
<tr>
<th>Boobs size</th>
<td>{{ Number(run.preferences.body.boobs.size).toFixed(2) }}</td>
</tr>
<tr>
<th>Areola size</th>
<td>{{ Number(run.preferences.body.areola.size).toFixed(2) }}</td>
</tr>
<tr>
<th>Nipple size</th>
<td>{{ Number(run.preferences.body.nipple.size).toFixed(2) }}</td>
</tr>
<tr>
<th>Vagina size</th>
<td>{{ Number(run.preferences.body.vagina.size).toFixed(2) }}</td>
</tr>
<tr>
<th>Pubic hair</th>
<td>{{ Number(run.preferences.body.pubicHair.size).toFixed(2) }}</td>
</tr>
</table>
<div class="dialog__buttons">
<button class="button button--danger" @click.prevent="$refs.preferencesDialog.close()">
Close
</button>
</div>
</div>
</dialog>
</div>
</template>

@@ -176,6 +146,10 @@ export default {
size(value) {
return Number.parseFloat(value).toFixed(2)
},

fixedValue(value) {
return Number(value).toFixed(2)
},
},

props: {
@@ -185,21 +159,13 @@ export default {
},
},

data: () => ({
outputDataURL: undefined,
}),

computed: {
previewDataURL() {
return this.run.outputFile.dataURL
},

previewStyle() {
if (!this.previewDataURL) {
if (!this.run.outputFile.exists) {
return {}
}

return { backgroundImage: `url(${this.previewDataURL})` }
return { backgroundImage: `url(${this.run.outputFile.path})` }
},

hasMaskfin() {
@@ -207,15 +173,7 @@ export default {
},

manualURL() {
return nucleus.urls?.docs?.manual || 'https://forum.dreamnet.tech/d/32-dreamtime-manual'
},
},

watch: {
'run.finished'(value) {
if (value) {
this.outputDataURL = this.run.outputFile.dataURL
}
return nucleus.urls?.docs?.manual || 'https://time.dreamnet.tech/docs/guide/upload'
},
},

@@ -265,14 +223,6 @@ export default {

this.run.maskfinFile.copy(savePath)
},

viewPreferences() {
//$refs.preferencesDialog.showModal()
},

viewTerminal() {
//$refs.terminalDialog.showModal()
},
},
}
</script>
@@ -285,39 +235,42 @@ export default {
height: 512px;

&:hover {
.run__content {
@apply opacity-100;
}
.run__details {
.run__content,
.run__preferences {
@apply opacity-100;
}
}
}

.run__details {
@apply opacity-0 bg-dark-500-90 w-full;
@apply absolute top-0;
.run__content,
.run__preferences {
@apply absolute opacity-0 bg-dark-500-80 w-full;
@apply flex;
transition: all 0.1s linear;
backdrop-filter: blur(6px);
transition: all .1s linear;
}

.run__preferences {
@apply flex top-0;
height: 80px;
table{
margin-left:auto;
margin-right:auto;
th{
padding:4px;
}
td{
@apply text-center;

.preference {
@apply flex flex-col flex-1 items-center justify-center;

span {
&:first-child {
@apply text-xs;
}

&:last-child {
@apply text-sm text-white font-bold;
}
}
}
}

.run__content {
@apply opacity-0 bg-dark-500-80 w-full;
@apply absolute bottom-0;
@apply flex;
backdrop-filter: blur(5px);
transition: all .1s linear;
@apply bottom-0;
height: 100px;

.content__item {

+ 15
- 12
src/components/Nudity/Upload.vue View File

@@ -1,19 +1,19 @@
<template>
<div class="c-uploader">
<div class="uploader__settings box box--items">
<div id="uploader" class="c-uploader">
<div id="uploader-settings" class="uploader__settings box box--items">
<div class="box__content">
<box-item
label="Upload mode"
description="What will happen when uploading a photo.">
<select v-model="$settings.app.uploadMode" class="input">
<option value="none">
Stay
Put in Pending
</option>
<option value="add-queue">
Start transformation
Put in Queue
</option>
<option value="go-preferences">
Change preferences
Put in Pending and open preferences
</option>
</select>
</box-item>
@@ -22,6 +22,7 @@

<!-- Dropzone -->
<div
id="uploader-dropzone"
class="uploader__dropzone"
:class="{'is-dragging': isDragging}"
@dragenter="onDragEnter"
@@ -30,11 +31,11 @@
@drop="openDrop">
<p class="dropzone-hint">
<font-awesome-icon icon="camera" />
Drop the photos here!
Drop the dream here!
</p>
</div>

<div class="uploader__alt">
<div id="uploader-alternatives" class="uploader__alt">
<!-- File -->
<div class="box">
<div class="box__header">
@@ -94,7 +95,7 @@
</div>

<div class="box__content">
<input v-model="webAddress" type="url" class="input mb-2" placeholder="https://">
<input v-model="webAddress" type="url" class="input mb-2" placeholder="https://" data-private="lipsum">

<button class="button" @click="openUrl">
Submit
@@ -115,7 +116,7 @@
</div>

<div class="box__content">
<input v-model="instagramPhoto" type="url" class="input mb-2" placeholder="https://www.instagram.com/p/dU4fHDw-Ho/">
<input v-model="instagramPhoto" type="url" class="input mb-2" placeholder="https://www.instagram.com/p/dU4fHDw-Ho/" data-private="lipsum">

<button class="button" @click="openInstagramPhoto">
Submit
@@ -127,14 +128,13 @@
</template>

<script>
/* eslint-disable no-param-reassign */
import {
isNil, isEmpty, startsWith,
map, isArray,
} from 'lodash'
import Swal from 'sweetalert2'
import { nucleus } from '~/modules/services'
import { Nudify } from '~/modules/nudify'
import { Consola } from '~/modules/consola'
import { tutorial } from '~/modules'

const consola = Consola.create('upload')

@@ -155,6 +155,9 @@ export default {
isDragging: false,
}),

mounted() {
tutorial.upload()
},

methods: {
/**

+ 1
- 2
src/components/Settings/Preference.vue View File

@@ -38,8 +38,7 @@
:description="`Min: ${currentValue.randomize.min} - Max: ${currentValue.randomize.max}`">
<VueSlider
v-model="randomizeRange"
:min-range="minRange"
:max-range="maxRange"
:min-range="0.05"
:min="minRange"
:max="maxRange"
:interval="0.05" />

+ 2
- 2
src/components/Settings/SettingsPreferences.vue View File

@@ -100,7 +100,7 @@
Overlay
</option>
<option value="cropjs">
Manual crop (Not recommended)
Manual crop
</option>
</select>
</box-item>
@@ -123,7 +123,7 @@

<box-item
label="Color transfer."
description="Use a experimental color transfer algorithm to try to recover the original colors of the photo.">
description="Use a experimental algorithm to try to recover the original colors of the photo.">
<select v-model="currentValue.advanced.useColorTransfer" class="input">
<option :value="true">
Enabled

+ 0
- 4
src/components/UI/AppUpdate.vue View File

@@ -26,9 +26,6 @@
/* eslint import/namespace: ['error', { allowComputed: true }] */
import * as providers from '~/modules/updater'

const { shell } = $provider.api
const { getPath } = $provider.paths

export default {
props: {
project: {
@@ -63,7 +60,6 @@ export default {

methods: {
next() {
console.log(this.href)
this.$router.push(this.href)
},
},

+ 1
- 1
src/components/UI/BoxItem.vue View File

@@ -155,7 +155,7 @@ export default {
@apply flex-1 flex flex-col justify-center;

.item__label {
@apply block font-semibold;
@apply block font-semibold text-generic-400;
}

.item__description {

+ 5
- 11
src/components/UI/ProjectUpdate.vue View File

@@ -55,25 +55,19 @@
</template>

<script>
import { isString, toNumber } from 'lodash'
import { toNumber } from 'lodash'
import * as providers from '~/modules/updater'

export default {
filters: {
progress(value) {
if (isString(value)) {
value = toNumber(value)
}

value = toNumber(value).toFixed(2)
return `${value}%`
},

size(value) {
if (isString(value)) {
value = toNumber(value)
}

return value.toFixed(2)
value = toNumber(value).toFixed(2)
return value
},

domain(value) {
@@ -136,7 +130,7 @@ export default {
border-radius: 9px;

&::-webkit-progress-bar {
@apply bg-dark-800;
@apply bg-dark-500;
border-radius: 9px;
}


+ 1
- 7
src/electron-builder.js View File

@@ -58,12 +58,6 @@ const macos = {
to: '7zip-bin',
},
],
extraFiles: [
{
from: '.env',
to: 'MacOS/.env',
},
],
},
dmg: {
title: '${productName}',
@@ -94,7 +88,7 @@ module.exports = {
'!**/{jsconfig.json,electron-builder.js,.eslintrc.js,.env-cmdrc.js,.codeclimate.yml,.babelrc,tailwind.config.js,nucleus.json}',
'!{components,cli,layouts,middleware,mixins,pages,patches,plugins,scripts,store,third,coverage,.nuxt,test,workers}',
'!{static,assets}',
'!**/electron/src',
'!electron/src',
],
extraFiles: [
{

+ 14
- 9
src/electron/src/index.js View File

@@ -10,7 +10,7 @@
import { startsWith } from 'lodash'
import { app, BrowserWindow, shell } from 'electron'
import { dirname, resolve } from 'path'
import Logger from 'logplease'
import Logger from '@dreamnet/logplease'
import fs from 'fs-extra'
import { AppError } from './modules/app-error'
import { system } from './modules/tools/system'
@@ -18,12 +18,6 @@ import { getPath } from './modules/tools/paths'
import { settings, ngrok } from './modules'
import config from '~/nuxt.config'

// logger setup
Logger.setOptions({
filename: getPath('userData', 'dreamtime.main.log'),
logLevel: process.env.LOG || 'debug',
})

const logger = Logger.create('electron')

// NuxtJS root directory
@@ -44,6 +38,15 @@ class DreamApp {
*
*/
static async boot() {
const logDir = getPath('userData', 'logs', new Date().toJSON().slice(0, 10))
fs.ensureDirSync(logDir)

// logger setup
Logger.setOptions({
filename: resolve(logDir, 'main.log'),
logLevel: process.env.LOG || 'debug',
})

logger.info('Booting...')

logger.debug(`Enviroment: ${process.env.name}`)
@@ -137,7 +140,6 @@ class DreamApp {
event.preventDefault()

logger.warn('Illegal page load blocked!', {
event,
url,
})
})
@@ -172,10 +174,12 @@ class DreamApp {
//
this.createDirs()

/*
if (process.env.name === 'development') {
const address = await ngrok.connect()
logger.debug(`Proxy for debugging: ${address}`)
}
*/
}

/**
@@ -207,12 +211,13 @@ class DreamApp {
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true,
webSecurity: false, // Necessary to load local photos and not put them in memory.
preload: resolve(app.getAppPath(), 'electron', 'dist', 'provider.js'),
},
})

// maximize
// todo: custom preferences
// TODO: custom preferences
this.window.maximize()

// disable menu

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

@@ -12,7 +12,7 @@ import {
} from 'lodash'
import { app, dialog } from 'electron'

const logger = require('logplease').create('error:main')
const logger = require('@dreamnet/logplease').create('error:main')

/**
* @typedef {Object} ErrorOptions

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

@@ -12,7 +12,7 @@ import {
} from 'lodash'
import { existsSync, readJsonSync, writeJsonSync } from 'fs-extra'

const logger = require('logplease').create('services')
const logger = require('@dreamnet/logplease').create('services')

export function makeServiceProxy(obj) {
return new Proxy(obj, {

+ 29
- 55
src/electron/src/modules/settings.js View File

@@ -14,7 +14,7 @@ import {
import { AppError } from './app-error'
import { paths, system } from './tools'

const logger = require('logplease').create('settings')
const logger = require('@dreamnet/logplease').create('settings')

/**
* User settings.
@@ -43,7 +43,7 @@ class Settings {
}

/**
* Load the service file.
* Load the settings.
*/
async load() {
if (isNil(this.path)) {
@@ -54,13 +54,14 @@ class Settings {
this.payload = fs.readJsonSync(this.path)
logger.debug('Settings:', this.payload)
} catch (error) {
// eslint-disable-next-line no-console
console.error(error)
}
}

/**
* Save the service file.
* This function is called automatically if you set a first level variable.
* Save the settings file.
* This function is called automatically.
*/
async save() {
fs.writeJsonSync(this.path, this.payload, { spaces: 2 })
@@ -88,8 +89,6 @@ class Settings {
} else {
this.payload = set(this.payload, path, payload)
}

this.save()
}

/**
@@ -127,8 +126,12 @@ class Settings {
telemetry: false,
},

achievements: {
badtime: false,
},

app: {
disableHardwareAcceleration: true,
disableHardwareAcceleration: false,
uploadMode: 'none',
},

@@ -347,6 +350,10 @@ class Settings {
dom: true,
}

this.payload.achievements = {
badtime: false,
}

const { body } = this.payload.preferences

body.boobs.randomize = {
@@ -384,7 +391,7 @@ class Settings {
}
}

export const settingsRaw = new Settings
export const theSettings = new Settings

const saveHandler = {
get(target, property, receiver) {
@@ -394,13 +401,19 @@ const saveHandler = {
return Reflect.get(target, property, receiver)
}
},
set(target, property, value, receiver) {
const response = Reflect.set(target, property, value, receiver)
theSettings.save()
return response
},
defineProperty(target, property, descriptor) {
settingsRaw.save()
return Reflect.defineProperty(target, property, descriptor)
const response = Reflect.defineProperty(target, property, descriptor)
theSettings.save()
return response
},
}

const settingsHandler = {
const handler = {
get(target, property, receiver) {
try {
if (property in target) {
@@ -413,51 +426,12 @@ const settingsHandler = {
// eslint-disable-next-line no-empty
} catch (err) { }

if (property in target.payload) {
return target.payload[property]
}

return Reflect.get(target, property, receiver)
},
}

/**
* Create a new instance with a Proxy.
*
* @return {Proxy}
*/
export function make(obj) {
return new Proxy(obj, settingsHandler)
/*
return new Proxy(obj, {
get: (obj, prop) => {
if (prop in obj) {
return obj[prop]
}

if (prop in obj.payload) {
return obj.payload[prop]
}

return undefined
},

set: (obj, prop, value) => {
console.log({
prop,
value,
})

if (!isNil(obj.payload)) {
if (prop in obj.payload) {
obj.payload[prop] = value
obj.save()

return true
}
}

obj[prop] = value
return true
},
})
*/
}

export const settings = make(settingsRaw)
export const settings = new Proxy(theSettings, handler)

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

@@ -7,7 +7,7 @@ import deferred from 'deferred'
import { getAppResourcesPath } from './paths'
import { AppError } from '../app-error'

const logger = require('logplease').create('electron:modules:tools:fs')
const logger = require('@dreamnet/logplease').create('electron:modules:tools:fs')

// eslint-disable-next-line node/no-deprecated-api
export * from 'fs-extra'

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

@@ -19,7 +19,9 @@ import { settings } from '../settings'
* @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
*/
export const getPath = (name, ...args) => join(app.getPath(name), ...args)
export function getPath(name, ...args) {
return join(app.getPath(name), ...args)
}

/**
*

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

@@ -16,7 +16,7 @@ import * as fs from 'fs-extra'
import { getPowerPath } from './paths'
import { settings } from '../settings'

const logger = require('logplease').create('power')
const logger = require('@dreamnet/logplease').create('power')

export function exec(args, options = {}) {
args.push('--debug')
@@ -25,7 +25,7 @@ export function exec(args, options = {}) {
// python script
args.unshift('main.py')

logger.debug('Spawning Python script.', {
logger.debug('[Python] Running:', {
args,
options,
})
@@ -36,10 +36,7 @@ export function exec(args, options = {}) {
})
}

logger.debug('Spawning executable.', {
args,
options,
})
logger.debug('Running:', args)

return spawn(getPowerPath('dreampower'), args, {
cwd: getPowerPath(),
@@ -47,12 +44,60 @@ export function exec(args, options = {}) {
})
}

/**
*
* @param {Array} args
* @param {EventBus} events
*/
export function nudify(args, events, outputFile) {
const process = exec(args)
let cancelled = false

process.on('error', (error) => {
logger.error(error)
events.emit('error', null, error)
})

process.stdout.on('data', (output) => {
const stdout = output.toString().trim().split('\n')
events.emit('stdout', null, stdout)
})

process.stderr.on('data', (output) => {
logger.warn(`stderr: ${output}`)
events.emit('stderr', null, output)
})

process.on('close', (code) => {
logger.info(`DreamPower exited with code ${code}`)
events.emit('close', null, code)

if (cancelled) {
events.emit('cancelled')
} else if (code === 0 || isNil(code)) {
if (fs.existsSync(outputFile.path)) {
events.emit('success')
} else {
events.emit('fail', null, true)
}
} else {
events.emit('fail', null, false)
}
})

events.on('cancel', () => {
cancelled = true
process.stdin.pause()
process.kill()
})
}

/**
*
* @param {PhotoRun} run
*/
export const transform = (run) => {
// Independent preferences for the photo
// Preferences for the photo
const { preferences } = run
const { fileFinal, scaleMode, overlay } = run.photo

@@ -100,52 +145,14 @@ export const transform = (run) => {
args.push('--vsize', preferences.body.vagina.size)
args.push('--hsize', preferences.body.pubicHair.size)

logger.info('Spawning DreamPower.', {
input: inputFilepath,
output: outputFilepath,
args,
})

const process = exec(args)

const bus = (new EventBus)

process.on('error', (error) => {
logger.error(error)
bus.emit('error', null, error)
})

process.stdout.on('data', (output) => {
const stdout = output.toString().trim().split('\n')
bus.emit('stdout', null, stdout)
})

process.stderr.on('data', (output) => {
logger.warn(`stderr: ${output}`)
bus.emit('stderr', null, output)
})

process.on('close', (code) => {
logger.info(`DreamPower exited with code ${code}`)
bus.emit('close', null, code)
const events = (new EventBus)

if (code === 0 || isNil(code)) {
if (fs.existsSync(run.outputFile.path)) {
bus.emit('success')
} else {
bus.emit('fail', null, true)
}
} else {
bus.emit('fail', null, false)
}
})

bus.on('kill', () => {
process.stdin.pause()
process.kill()
})
setTimeout(() => {
// Give time for the renderer to receive the events object.
nudify(args, events, run.outputFile)
}, 10)

return bus
return events
}

/**

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

@@ -13,7 +13,7 @@ import {
import si from 'systeminformation'
import isOnline from 'is-online'

const logger = require('logplease').create('system')
const logger = require('@dreamnet/logplease').create('system')

class System {
/**

+ 2
- 3
src/electron/src/provider.js View File

@@ -1,8 +1,7 @@
const { remote } = require('electron')
const { make } = require('./modules/settings')

const util = remote.require('electron-util')
const { settingsRaw } = remote.require('./modules/settings')
const { settings } = remote.require('./modules/settings')
const tools = remote.require('./modules/tools')
const ngrok = remote.require('./modules/ngrok')

@@ -10,7 +9,7 @@ const ngrok = remote.require('./modules/ngrok')
window.$provider = {
...tools,

settings: make(settingsRaw),
settings,
ngrok,

api: util.api,

+ 7
- 5
src/layouts/default.vue View File

@@ -1,13 +1,15 @@
<template>
<div class="layout">
<layout-topbar />
<!-- Window Buttons -->
<LayoutTopbar />

<layout-navbar />
<!-- Navigation -->
<LayoutNavbar />

<layout-navigation v-if="false" />

<layout-jobbar />
<!-- Queue -->
<LayoutQueuebar />

<!-- Content -->
<div id="layout-content" class="layout__content">
<nuxt />
</div>

+ 3
- 1
src/layouts/wizard.vue View File

@@ -1,7 +1,9 @@
<template>
<div class="layout">
<layout-topbar />
<!-- Window Buttons -->
<LayoutTopbar />

<!-- Content -->
<div id="layout-content" class="layout__content">
<nuxt />
</div>

+ 0
- 40
src/middleware/checks.js View File

@@ -1,40 +0,0 @@
// 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 { requirements } from '~/modules/system'

/**
* Detects if the user has what it takes to run the program,
* otherwise redirects him to the appropriate page.
*/
export default function ({ route, redirect }) {
/*
window.$redirect = redirect


if (!requirements.power.installed || !requirements.power.compatible) {
// DreamPower is missing
if (
!route.path.includes('/settings')
&& route.path !== '/about'
) {
redirect('/about')
}

return
}

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

+ 2
- 14
src/middleware/wizard.js View File

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

import { requirements } from '~/modules/system'

const { wizard } = $provider.settings
import { settings, requirements } from '~/modules/system'

export default function ({ route, redirect }) {
window.$redirect = redirect
const { wizard } = settings

if (!wizard.welcome) {
if (route.path !== '/wizard/welcome') {
@@ -51,14 +49,4 @@ export default function ({ route, redirect }) {
redirect('/wizard/telemetry')
}
}

/*
if (!wizard.user) {
if (route.path !== '/wizard/user') {
redirect('/wizard/user')
}

return
}
*/
}

+ 15
- 14
src/mixins/BaseMixin.js View File

@@ -1,33 +1,34 @@
import _ from 'lodash'
import { isString } from 'lodash'
import tippy from 'tippy.js'
import { NudifyStore } from '~/modules/nudify'
import { settings } from '~/modules/system'

/**
* @mixin
*/
export default {
directives: {
/**
* v-tooltip.
* Tooltip creation.
*/
tooltip: {
inserted(el, binding) {
let settings = {}
let options = {}

if (_.isString(binding.value)) {
settings.content = binding.value
if (isString(binding.value)) {
options.content = binding.value
} else {
settings = binding.value
options = binding.value
}

tippy(el, settings)
tippy(el, options)
},

},
},

created() {
window.$router = this.$router
},

filters: {},

data: () => ({
$nudify: NudifyStore,
$settings: $provider.settings,
$settings: settings,
}),
}

+ 17
- 40
src/mixins/VModel.js View File

@@ -1,8 +1,7 @@
import _ from 'lodash'

const debug = require('debug').default('app:mixins:vmodel')
import { cloneDeep, isEqual, isNative } from 'lodash'

/**
* Helper to handle custom v-model
* @mixin
*/
export default {
@@ -17,66 +16,44 @@ export default {

data: () => ({
/**
* Contains the current value, this variable must be changed within the component.
* Current value, this is the variable that must be changed.
*/
currentValue: null,
}),

created() {
// Initial value
this.currentValue = _.cloneDeep(this.value)
},

methods: {
onChange() {
// nothing
},

$forceCurrentValueUpdate() {
debug('$currentValue has changed, updating the v-model', {
oldValue: this.value,
newValue: this.currentValue,
})

this.$emit('input', this.currentValue)
this.onChange(this.currentValue)
},
// initial value.
if (!isNative(this.value)) {
this.currentValue = this.value
} else {
this.currentValue = cloneDeep(this.value)
}
},

watch: {
// The local value has changed, update the v-model
/**
* Local value changed, update the v-model.
*/
currentValue: {
handler(value) {
if (_.isEqual(this.value, value)) {
if (isEqual(this.value, value)) {
return
}

// this.$forceCurrentValueUpdate()

debug('$currentValue has changed, updating the v-model', {
oldValue: this.value,
newValue: value,
})

this.$emit('input', value)
this.onChange(value)
},
deep: true,
},

// The v-model value has changed, update the local value
/**
* v-model value changed, update the local value.
*/
value(value) {
if (_.isEqual(this.currentValue, value)) {
if (isEqual(this.currentValue, value)) {
return
}

debug('v-model value has changed, updating currentValue', {
oldValue: this.currentValue,
newValue: value,
})

this.currentValue = value
this.onChange(value)
},
},
}

+ 0
- 219
src/modules/app-error.js View File

@@ -1,219 +0,0 @@
// 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 {
isError, isString, isObject, isArray, attempt,
} from 'lodash'
import { mapStackTrace } from 'sourcemapped-stacktrace'
import Swal from 'sweetalert2'
import { logrocket, rollbar } from '~/modules/services'

const logger = require('logplease').create('error:renderer')

const { app } = $provider.api

/**
* @typedef {Object} ErrorOptions
* @property {string} title
* @property {string} level
* @property {Error} error
* @property {boolean} fatal
* @property {boolean} quiet
*/

export class AppError extends Error {
/**
* @type {ErrorOptions}
*/
options = {
title: null,
message: null,
level: 'error',
error: null,
fatal: false,
quiet: false,
}

/**
* @type {boolean}
*/
reported = false

/**
*
* @param {string} message
* @param {ErrorOptions} options
*/
constructor(message, options = {}) {
if (isError(message)) {
// that's better.
options.error = message
message = message.message
}

const { error } = options

if (isError(error)) {
// we want this error to be the closest to the original
super(error.message)

if (error.options) {
// inherit error options.
this.options = error.options
}
} else if (isString(message)) {
super(message)
} else {
super()
}

this.options = {
...this.options,
...options,
message,
}

if (this.options.level === 'warning') {
// warning does not exist in logger.
this.options.level = 'warn'
}
}

/**
* Copy the original error information.
*/
async copyError() {
const { error } = this.options

if (!isError(error)) {
return
}

// transform the original stack to the source-map stack.
const getStack = () => new Promise((resolve) => {
mapStackTrace(error.stack, (stack) => {
resolve(`${error.message}\n${stack.join('\n')}`)
}, { cacheGlobally: true })
})

// copy pasta
this.name = error.name
this.stack = await getStack()
}

/**
* Report the error to the logger, bug and session tracking services.
*/
report() {
const { level, error } = this.options
let rollbarResponse

// logger.
logger[level](this)

// bug tracking.
if (rollbar.enabled && level === 'error') {
try {
rollbarResponse = rollbar[level](this, {
...this.options,
sessionURL: logrocket.sessionURL,
})

this.reported = true
} catch (err) {
logger.warn('Rollbar report fail!', err)
}
}

// session tracking.
if (logrocket.enabled && level === 'error') {
try {
logrocket.captureException(error || this, {
extra: {
...this.options,
rollbarURL: `https://rollbar.com/occurrence/uuid/?uuid=${rollbarResponse?.uuid}`,
},
})

this.reported = true
} catch (err) {
logger.warn('LogRocket report fail!', err)
}
}
}

/**
* Show the error to the user.
*/
show() {
let icon = 'error'

if (this.level === 'warning' || this.level === 'warn') {
icon = 'warning'
}

if (this.level === 'info') {
icon = 'info'
}

Swal.fire({
title: this.options.title,
html: `${this.options.message}<br><br><pre>${this.message}</pre>`,
icon,
footer: this.reported ? `<code>๐Ÿž This problem has been reported to DreamNet.<br>It will be fixed as soon as possible.</code>` : null,
})
}

/**
*
*/
async handle() {
const { quiet, fatal, error } = this.options

await this.copyError(error)

attempt(() => {
this.report()

if (!quiet) {
this.show()
}
})

if (fatal) {
app.quit()
}
}

/**
*
*/
static handle(error) {
let appError = error

if (!(error instanceof AppError)) {
let exception

if (isError(error)) {
exception = error
} else if (isObject(error) || isArray(error)) {
exception = new Error(JSON.stringify(error))
} else {
exception = new Error(error)
}

appError = new AppError(`Woah! An error has occurred and we do not know why.<br>Please try again.`, {
error: exception,
title: 'Unexpected error!',
})
}

appError.handle()
}
}

+ 28
- 36
src/modules/config/cli-errors.json View File

@@ -1,62 +1,54 @@
[
{
"error": "Found no NVIDIA driver on your system",
"message": "Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed a driver from [here](http://www.nvidia.com/Download/index.aspx). If you don't have an NVIDIA GPU please change the Device option in **Settings** to **CPU**.",
"level": "debug"
"query": "Found no NVIDIA driver on your system",
"message": "Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed the latest driver."
},
{
"error": "The NVIDIA driver on your system is too old",
"message": "The NVIDIA driver installed on your system is too old! If the drivers are up to date then your GPU may not be compatible. You can also change the device option in **Settings** to **CPU**.",
"level": "debug"
"query": "The NVIDIA driver on your system is too old",
"message": "The NVIDIA driver installed on your system is too old! If the drivers are up to date then your GPU is not compatible."
},
{
"error": "no longer supports this GPU",
"message": "DreamTime does not have support for your GPU. Please change the device option in **Settings** to **CPU**.",
"level": "debug"
"query": "no longer supports this GPU",
"message": "DreamTime no longer supports your GPU."
},
{
"error": "Buy new RAM!",
"message": "You have run out of RAM on your system! Try a photo of smaller size or free all possible memory.",
"level": "debug"
"query": "Buy new RAM!",
"message": "You have run out of RAM on your system! Try a photo of smaller size or close all the programs you can."
},
{
"error": "CUDA out of memory",
"message": "You have run out of VRAM on your GPU! Try a photo of smaller size or free all possible GPU use.",
"level": "debug"
"query": "CUDA out of memory",
"message": "You have run out of VRAM on your GPU! Try a photo of smaller size or close all the programs you can."