Browse Source

A lot of changes.

v1.5 RC 1
tags/v1.5.0-rc2.2
Ivan Bravo Bravo 4 weeks ago
parent
commit
6cf7714221
100 changed files with 3602 additions and 1229 deletions
  1. 23
    14
      .github/workflows/ci.yml
  2. 0
    10
      node_modules/.yarn-integrity
  3. 2
    3
      src/.env-cmdrc.js
  4. 1
    1
      src/.eslintrc.js
  5. 1
    4
      src/.gitignore
  6. 4
    0
      src/assets/css/app.scss
  7. 11
    5
      src/assets/css/components/_box.scss
  8. 8
    9
      src/assets/css/components/_wizard.scss
  9. 5
    5
      src/assets/css/reset/_dialog.scss
  10. 3
    4
      src/assets/css/reset/_libs.scss
  11. 5
    1
      src/assets/css/utilities/all.scss
  12. 14
    0
      src/assets/css/vendor.scss
  13. BIN
      src/assets/images/double-bubble-dark.png
  14. BIN
      src/assets/images/masks/1.jpg
  15. BIN
      src/assets/images/masks/2.jpg
  16. BIN
      src/assets/images/repeated-square-dark.png
  17. 1
    0
      src/assets/images/undraw/undraw_Appreciation_sjc1.svg
  18. 1
    0
      src/assets/images/undraw/undraw_blank_canvas_3rbb.svg
  19. 1
    0
      src/assets/images/undraw/undraw_cancel_u1it.svg
  20. 1
    0
      src/assets/images/undraw/undraw_certification_aif8.svg
  21. 1
    0
      src/assets/images/undraw/undraw_elements_cipa.svg
  22. 1
    0
      src/assets/images/undraw/undraw_energizer_2224.svg
  23. 1
    0
      src/assets/images/undraw/undraw_judge_katerina_limpitsouni_ny1q.svg
  24. 1
    0
      src/assets/images/undraw/undraw_making_art_759c.svg
  25. 1
    0
      src/assets/images/undraw/undraw_open_source_1qxw.svg
  26. 1
    0
      src/assets/images/undraw/undraw_selected_options_42hx.svg
  27. 1
    0
      src/assets/images/undraw/undraw_terms_lso0.svg
  28. 36
    28
      src/components/Help/HelpLesson.vue
  29. 10
    3
      src/components/Layout/Menubar.vue
  30. 1
    1
      src/components/Layout/Navbar.vue
  31. 11
    3
      src/components/Layout/Titlebar.vue
  32. 177
    30
      src/components/Nudify/NudifyMaskPhoto.vue
  33. 36
    0
      src/components/Nudify/NudifyPhotoBadge.vue
  34. 59
    0
      src/components/Nudify/NudifyPhotoPreview.vue
  35. 152
    179
      src/components/Nudify/NudifyPhotoRun.vue
  36. 2
    3
      src/components/Nudify/NudifyUpload.vue
  37. 44
    0
      src/components/Photo.vue
  38. 15
    11
      src/components/Queue/QueueBar.vue
  39. 26
    50
      src/components/Queue/QueuePhoto.vue
  40. 3
    1
      src/components/Settings/Preference.vue
  41. 8
    1
      src/components/Settings/SettingsField.vue
  42. 56
    4
      src/components/Settings/SettingsPreferences.vue
  43. 38
    34
      src/components/UI/AppAds.vue
  44. 80
    0
      src/components/UI/AppBox.vue
  45. 1
    1
      src/components/UI/AppTip.vue
  46. 21
    17
      src/components/UI/ProjectUpdate.vue
  47. 11
    12
      src/electron/src/index.js
  48. 51
    4
      src/electron/src/modules/settings.js
  49. 3
    1
      src/electron/src/modules/tools/fs.js
  50. 2
    2
      src/electron/src/modules/tools/index.js
  51. 12
    0
      src/electron/src/modules/tools/paths.js
  52. 129
    69
      src/electron/src/modules/tools/power.js
  53. 4
    2
      src/electron/src/modules/tools/system.js
  54. 213
    0
      src/electron/src/modules/tools/waifu.js
  55. 64
    13
      src/layouts/default.vue
  56. 6
    32
      src/layouts/wizard.vue
  57. 10
    0
      src/middleware/wizard.js
  58. 8
    1
      src/mixins/BaseMixin.js
  59. 93
    0
      src/mixins/DragDropMixin.js
  60. 9
    63
      src/mixins/UploadMixin.js
  61. 2
    2
      src/mixins/VModel.js
  62. 1
    0
      src/mixins/index.js
  63. 11
    7
      src/modules/config/cli-errors.json
  64. 71
    9
      src/modules/config/help.yml
  65. 105
    18
      src/modules/config/settings.yml
  66. 29
    0
      src/modules/config/tos.yml
  67. 6
    4
      src/modules/consola/errors.js
  68. 1
    1
      src/modules/consola/log.js
  69. 176
    37
      src/modules/file.js
  70. 0
    4
      src/modules/help.js
  71. 117
    0
      src/modules/imagemagick.js
  72. 1
    0
      src/modules/index.js
  73. 1
    1
      src/modules/nudify/nudify.js
  74. 209
    3
      src/modules/nudify/photo-mask.js
  75. 223
    75
      src/modules/nudify/photo-run.js
  76. 402
    127
      src/modules/nudify/photo.js
  77. 63
    0
      src/modules/photos.js
  78. 5
    0
      src/modules/projects/dreamtime.js
  79. 1
    0
      src/modules/projects/index.js
  80. 57
    0
      src/modules/projects/waifu.js
  81. 1
    2
      src/modules/services/dreamtrack.js
  82. 5
    18
      src/modules/services/logrocket.js
  83. 53
    7
      src/modules/system/requirements.js
  84. 1
    0
      src/modules/updater/index.js
  85. 122
    0
      src/modules/updater/waifu.js
  86. 24
    28
      src/nuxt.config.js
  87. 9
    10
      src/package.json
  88. 7
    2
      src/pages/about.vue
  89. 80
    0
      src/pages/about/waifu.vue
  90. 2
    0
      src/pages/games/badtime.vue
  91. 0
    1
      src/pages/index.vue
  92. 64
    66
      src/pages/nudify/_id.vue
  93. 8
    3
      src/pages/nudify/_id/crop.vue
  94. 7
    12
      src/pages/nudify/_id/overlay.vue
  95. 129
    0
      src/pages/nudify/_id/padding.vue
  96. 1
    1
      src/pages/nudify/_id/preferences.vue
  97. 0
    152
      src/pages/nudify/_id/results.legacy.vue
  98. 64
    18
      src/pages/nudify/_id/results.vue
  99. 65
    0
      src/pages/photos.vue
  100. 0
    0
      src/pages/settings.vue

+ 23
- 14
.github/workflows/ci.yml View File

@@ -2,26 +2,32 @@ name: CI/CD

on:
push:
paths:
- src/**
- .github/**
branches:
- release/*
- hotfix/*
- canary
tags:
- v*

pull_request:
paths:
- src/**
branches:
- canary
paths:
- .github/workflows/*
- src/*

jobs:
build:
name: Build (${{ matrix.platform }})
name: ${{ matrix.platform }}
runs-on: ${{ matrix.os }}

# Strategy
# (variables for multiple platforms)
# https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategy
strategy:
fail-fast: false
fail-fast: true
max-parallel: 1
matrix:
os:
@@ -61,19 +67,24 @@ jobs:
working-directory: src/
run: yarn run lint

- name: Build (Installer)
- name: Build Installer
working-directory: src/
env:
GITHUB_SHA: ${{ github.sha }}
run: yarn run build

- name: Build (Portable)
- name: Build Portable
working-directory: src/
env:
GITHUB_SHA: ${{ github.sha }}
BUILD_PORTABLE: true
run: yarn run build

- uses: actions/upload-artifact@v2
with:
name: dreamtime-${{ matrix.platform }}
path: dist/[abc]-unpacked/

- name: Deploy
working-directory: src/
continue-on-error: true
@@ -83,15 +94,13 @@ jobs:
GITHUB_REF: ${{ github.ref }}
BUILD_PLATFORM: ${{ matrix.platform }}
BUILD_EXTENSION: ${{ matrix.extension }}
DEPLOY_ENCRYPT_KEY: ${{ secrets.SECRET_KEY }}
DEPLOY_GITHUB_TOKEN: ${{ secrets.TOKEN }}
DEPLOY_ENCRYPT_KEY: ${{ secrets.DEPLOY_ENCRYPT_KEY }}
DEPLOY_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEPLOY_GITHUB_OWNER: dreamnettech
DEPLOY_TEKNIK_TOKEN: ${{ secrets.TEKNIK_TOKEN }}
DEPLOY_TEKNIK_TOKEN: ${{ secrets.DEPLOY_TEKNIK_TOKEN }}
DEPLOY_TEKNIK_OWNER: dreamnet
DEPLOY_DREAMLINKCLUSTER_USERNAME: ${{ secrets.DEPLOY_DREAMLINKCLUSTER_USERNAME }}
DEPLOY_DREAMLINKCLUSTER_PASSWORD: ${{ secrets.DEPLOY_DREAMLINKCLUSTER_PASSWORD }}
DEPLOY_PINATA_KEY: ${{ secrets.PINATA_KEY }}
DEPLOY_PINATA_SECRET: ${{ secrets.PINATA_SECRET }}
DEPLOY_PINATA_KEY: ${{ secrets.DEPLOY_PINATA_KEY }}
DEPLOY_PINATA_SECRET: ${{ secrets.DEPLOY_PINATA_SECRET }}
DEPLOY_MEGA_EMAIL: ${{ secrets.DEPLOY_MEGA_EMAIL }}
DEPLOY_MEGA_PASSWORD: ${{ secrets.DEPLOY_MEGA_PASSWORD }}
DEPLOY_MEGA_FOLDER: "/Projects/DreamTime/Releases/"

+ 0
- 10
node_modules/.yarn-integrity View File

@@ -1,10 +0,0 @@
{
"systemParams": "win32-x64-72",
"modulesFolders": [],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [],
"lockfileEntries": {},
"files": [],
"artifacts": {}
}

+ 2
- 3
src/.env-cmdrc.js View File

@@ -10,19 +10,18 @@ module.exports = {
},
"development": {
"NODE_ENV": "development",
"PUBLIC_URL": "http://45bbcde32f40.ngrok.io",
"ROLLBAR_ACCESS_TOKEN": "e62c909ec771492fa7f371dc61eea092",
"LOGROCKET_ACCESS_TOKEN": "of2lox/dreamtime",
"LOGROCKET_ACCESS_TOKEN": "5iqym0/dreamtime-development",
"DREAMTRACK_HOST": "localhost:3333",
...development
},
"production": {
"NODE_ENV": "production",
"LOG": "info",
"DREAMTRACK_HOST": "track.dreamnet.tech"
},
"test": {
"NODE_ENV": "test",
"LOG": "debug"
},
"preview": {
...development

+ 1
- 1
src/.eslintrc.js View File

@@ -66,7 +66,7 @@ module.exports = {
'nuxt/no-cjs-in-config': 'off',
'nuxt/no-globals-in-created': 'off',
'linebreak-style': 'error',
'max-len': ['warn', { code: 120 }],
'max-len': ['off', { code: 120 }],
'no-await-in-loop': 'warn',
'no-continue': 'off',
'no-param-reassign': 'off',

+ 1
- 4
src/.gitignore View File

@@ -88,10 +88,7 @@ sw.*
# Mac OSX
.DS_Store

# lock file
*.lock

#
*.tgz

scripts/decrypt.js
scripts/decrypt.js

+ 4
- 0
src/assets/css/app.scss View File

@@ -0,0 +1,4 @@
/* purgecss start ignore */
@import "./reset/all.scss";
@import "./components/all.scss";
/* purgecss end ignore */

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

@@ -20,7 +20,8 @@
.box__photo {
@apply relative;
@apply bg-cover bg-center bg-no-repeat;
min-height: 120px;
background-image: url('~@/assets/images/repeated-square-dark.png');
min-height: 130px;

&:first-child {
@apply rounded-t-lg;
@@ -30,6 +31,11 @@
@apply absolute w-full h-full;
@apply bg-black-70;
}

.box__photo__preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center m-6;
}
}

.box__header {
@@ -40,19 +46,19 @@
}

.title {
@apply font-serif font-semibold text-lg text-common-light;
@apply font-bold text-lg text-white;
}

.subtitle {
@apply text-sm font-light mb-2;
@apply text-sm font-semibold mb-2;
}
}

.box__content {
@apply flex-1 p-6;
@apply flex-1 px-6 py-3 text-sm;

p {
@apply text-sm mb-3;
@apply mb-3;
}
}


+ 8
- 9
src/assets/css/components/_wizard.scss View File

@@ -1,28 +1,27 @@
/*
* 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__footer {
@apply my-6 text-center;
}

.wizard-project {
.project__content {
@apply flex;

.project__update {
@apply flex-1;

&:not(:last-child) {
@apply mr-4;
}
}

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

+ 5
- 5
src/assets/css/reset/_dialog.scss View File

@@ -1,11 +1,11 @@
/*
* 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.
*/

@@ -15,12 +15,12 @@ dialog {
max-width: 100%;

.dialog__content {
@apply p-4 bg-dark-500 rounded;
@apply px-6 py-3 bg-menus rounded;
@apply flex flex-col justify-center;
}

.dialog__buttons {
@apply flex mt-4;
@apply flex mt-3;

.button {
@apply flex-1;
@@ -34,4 +34,4 @@ dialog {

dialog::backdrop {
background: rgba(25, 25, 26, 0.75);
}
}

+ 3
- 4
src/assets/css/reset/_libs.scss View File

@@ -34,11 +34,10 @@
@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;
code {
@apply bg-black px-2 text-sm rounded-sm break-words;
}
}

.swal2-footer {

+ 5
- 1
src/assets/css/utilities/all.scss View File

@@ -2,4 +2,8 @@
transition-property: #{$property};
transition-duration: $duration;
transition-timing-function: $timing;
}
}

@mixin centered() {
@apply flex items-center justify-center;
}

+ 14
- 0
src/assets/css/vendor.scss View File

@@ -0,0 +1,14 @@
/* purgecss start ignore */
@import "tippy.js/dist/tippy.css";
@import "cropperjs/dist/cropper.css";
@import "vue-slider-component/theme/default.css";

@import "sweetalert2/dist/sweetalert2.css";
@import "@sweetalert2/theme-dark/dark.css";

@import "tui-image-editor/dist/tui-image-editor.css";
@import "tui-color-picker/dist/tui-color-picker.css";

@import "intro.js/introjs.css";
@import "intro.js/themes/introjs-modern.css";
/* purgecss end ignore */

BIN
src/assets/images/double-bubble-dark.png View File


BIN
src/assets/images/masks/1.jpg View File


BIN
src/assets/images/masks/2.jpg View File


BIN
src/assets/images/repeated-square-dark.png View File


+ 1
- 0
src/assets/images/undraw/undraw_Appreciation_sjc1.svg View File

@@ -0,0 +1 @@
<svg id="a176bc44-7f51-41d5-a02f-4652bba7f458" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="933.0987" height="737.1609" viewBox="0 0 933.0987 737.1609"><defs><linearGradient id="b7ff1900-2a50-4d41-b005-c7dffc487981" x1="611.67067" y1="818.58045" x2="611.67067" y2="81.41955" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="gray" stop-opacity="0.25"/><stop offset="0.53514" stop-color="gray" stop-opacity="0.12"/><stop offset="1" stop-color="gray" stop-opacity="0.1"/></linearGradient><linearGradient id="a149f93e-460d-45ce-bffe-3c9ed674ad89" x1="872.96875" y1="716.16825" x2="872.96875" y2="344.72985" xlink:href="#b7ff1900-2a50-4d41-b005-c7dffc487981"/></defs><title>Appreciation</title><path d="M686.17536,512.33578c-32.02173-65.11085-6.40435-121.68257,38.42607-161.176,61.90868-28.81955,122.75-16.01086,167.58039,41.62825,29.25359-17.096,66.49943-20.79725,97.13258-13.87608,23.63633-89.02592,1.50335-195.76223-77.39108-253.304C809.3,50.75941,665.43087,73.27541,590.58241,175.89863,487.95912,101.05011,344.09,123.56611,269.24151,226.18927s-52.3326,246.49245,50.2907,321.341L691.16382,818.58045l98.54846-136.5295Z" transform="translate(-133.45065 -81.41955)" fill="url(#b7ff1900-2a50-4d41-b005-c7dffc487981)"/><path d="M893.59045,401.696A114.94392,114.94392,0,1,0,695.111,517.68876L811.10368,716.16825l198.47949-115.99272A114.94392,114.94392,0,1,0,893.59045,401.696Z" transform="translate(-133.45065 -81.41955)" fill="url(#a149f93e-460d-45ce-bffe-3c9ed674ad89)"/><path d="M892.63253,405.348A109.60453,109.60453,0,0,0,703.37284,515.95262l110.6046,189.25969,189.2597-110.60461A109.60453,109.60453,0,1,0,892.63253,405.348Z" transform="translate(-133.45065 -81.41955)" fill="#e53935"/><path d="M1001.23715,595.60767A109.60178,109.60178,0,0,0,891.10037,406.08246l108.97211,190.20587Z" transform="translate(-133.45065 -81.41955)" opacity="0.2"/><path d="M981.89322,374a122.4019,122.4019,0,0,0-89.02008,13.76,122.8312,122.8312,0,0,0-212.1,123.95l97.45,166.76-90.37,123.92-185.57-135.35,15.63-9.13a139.62694,139.62694,0,0,0-124.86-249.14,141.39542,141.39542,0,0,0-16.04,8.05,139.62161,139.62161,0,0,0-134.11-68.54,220.217,220.217,0,0,1,5.1-32.93c.28-1.2.58-2.41.88-3.62q1.8-7.125,4.07995-14.17c.12006-.36.23005-.73.36005-1.09.69-2.08,1.42-4.16,2.17-6.23.86-2.36,1.77-4.72,2.72-7.06.47-1.17.95-2.34,1.45-3.5q.72006-1.695,1.47-3.39a.91693.91693,0,0,1,.05-.1c.51-1.16,1.04-2.31,1.58-3.46.06-.14.12-.28.19-.41.48-1.02.96-2.03,1.46-3.04.56-1.15,1.13-2.29,1.71-3.43,1.23-2.43,2.52-4.83,3.86-7.23.48-.88.98-1.75,1.49-2.62.6-1.05,1.21-2.1,1.84-3.14.29-.48.58-.97.88-1.45q2.445-4.035,5.1-7.99.61506-.93,1.26-1.86c.58-.85,1.17-1.7,1.76-2.54.71-1,1.42-2,2.15-3,71.56-98.11,209.11005-119.64,307.22-48.08,71.56-98.11,209.11-119.64,307.23-48.08A219.96866,219.96866,0,0,1,981.89322,374Z" transform="translate(-133.45065 -81.41955)" fill="#d67411"/><path d="M364.18171,436.62953a123.81349,123.81349,0,0,0-213.795,124.94321l124.94322,213.795,213.795-124.94321a123.81349,123.81349,0,0,0-124.94322-213.795Z" transform="translate(-133.45065 -81.41955)" fill="#e53935"/><path d="M592.05313,188l-199,220.77a141.39542,141.39542,0,0,0-16.04,8.05,139.62161,139.62161,0,0,0-134.11-68.54,220.217,220.217,0,0,1,5.1-32.93c.28-1.2.58-2.41.88-3.62q1.785-7.125,4.07995-14.17c.12006-.36.23005-.73.36005-1.09q1.035-3.11994,2.17-6.23c.86-2.36,1.76-4.72,2.72-7.06.47-1.17.95-2.34,1.45-3.5q.72006-1.695,1.47-3.39a.91693.91693,0,0,1,.05-.1c.51-1.16,1.04-2.31,1.58-3.46.06-.14.12-.28.19-.41.48-1.02.96-2.03,1.46-3.04.56-1.15,1.13-2.29,1.71-3.43,1.23-2.43,2.52-4.83,3.86-7.23.48-.88.98-1.75,1.49-2.62.6-1.05,1.21-2.1,1.84-3.14.29-.48.58-.97.88-1.45q2.445-4.035,5.1-7.99.61506-.93,1.26-1.86c.58-.85,1.17-1.7,1.76-2.54.71-1,1.42-2,2.15-3,71.56-98.11,209.11005-119.64,307.22-48.08.1-.12.19-.25.29-.37Z" transform="translate(-133.45065 -81.41955)" opacity="0.2"/></svg>

+ 1
- 0
src/assets/images/undraw/undraw_blank_canvas_3rbb.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_cancel_u1it.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_certification_aif8.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_elements_cipa.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_energizer_2224.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_judge_katerina_limpitsouni_ny1q.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_making_art_759c.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_open_source_1qxw.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_selected_options_42hx.svg
File diff suppressed because it is too large
View File


+ 1
- 0
src/assets/images/undraw/undraw_terms_lso0.svg
File diff suppressed because it is too large
View File


+ 36
- 28
src/components/Help/HelpLesson.vue View File

@@ -1,19 +1,14 @@
<template>
<div class="box lesson"
:class="{ 'lesson--small': small }"
@click="$emit('click')">
<div class="box__photo"
:class="[`photo--${lesson.photo}`]" />
<div class="box lesson" :class="{ 'lesson--small': small }" @click="$emit('click')">
<div class="box__photo" :class="[`photo--${lesson.photo}`]" />

<div class="box__header">
<span class="title">{{ lesson.title }}</span>
</div>

<div class="box__content"
v-html="content" />
<div class="box__content" v-html="content" />

<div v-if="!small"
class="box__footer text-center">
<div v-if="!small" class="box__footer text-center">
<a v-for="(button,key) in lesson.buttons"
:key="key"
:href="button.href"
@@ -73,40 +68,53 @@ export default {

.lesson--small {
.title {
@apply text-sm;
@apply text-base;
}

.box__content {
&::v-deep p {
@apply text-xs #{!important};
}
}

.box__photo {
min-height: 80px !important;
&::v-deep .box__content {
@apply text-xs #{!important};
}
}

/* purgecss start ignore */
.box__photo {
@apply bg-contain;

&.photo--tips {
background-color: #e0719e;
background-image: url('~assets/images/undraw/undraw_depi_wexf.svg')
&.photo--drag {
@apply bg-menus-dark;
//background-color: #593C48;
background-image: url('~assets/images/undraw/undraw_throw_down_ub2l.svg')
}

&.photo--drag {
background-color: #778BB0;
background-image: url('~assets/images/undraw/undraw_logic_4ocy.svg')
&.photo--tips {
background-color: #C27091;
background-image: url('~assets/images/undraw/undraw_depi_wexf.svg')
}

&.photo--settings {
background-color: #46766B;
background-color: #C27091;
background-image: url('~assets/images/undraw/undraw_personal_settings_kihd.svg')
}
}

.box__content {
@apply text-sm;
&.photo--preferences {
background-color: #607AA9;
background-image: url('~assets/images/undraw/undraw_making_art_759c.svg')
}

&.photo--better-results {
background-color: #607AA9;
background-image: url('~assets/images/undraw/undraw_blank_canvas_3rbb.svg')
}

&.photo--tips-ads {
background-color: #506896;
background-image: url('~assets/images/undraw/undraw_elements_cipa.svg')
}

&.photo--preferences-mode {
background-color: #D9B6C4;
background-image: url('~assets/images/undraw/undraw_selected_options_42hx.svg')
}
}
/* purgecss end ignore */
</style>

+ 10
- 3
src/components/Layout/Menubar.vue View File

@@ -39,8 +39,7 @@ export default {

.menu {
@apply flex flex-col;
@apply bg-menus relative border-r border-menus-light;
grid-area: menu;
@apply bg-menus relative;

&::v-deep {
section {
@@ -54,6 +53,14 @@ export default {
}

.menu__content {
@apply flex-1 p-3 h-full overflow-y-auto;
@apply flex-1;
height: calc(100vh - 80px - 250px);
}

.menu__custom {
@apply p-3 overflow-y-auto h-full;
}

.menu__bottom {
}
</style>

+ 1
- 1
src/components/Layout/Navbar.vue View File

@@ -14,7 +14,7 @@
<font-awesome-icon icon="upload" />
</nuxt-link>

<nuxt-link v-tooltip="'Photos'" to="/" class="nav__item nav__item--link">
<nuxt-link v-tooltip="'Photos'" to="/photos" class="nav__item nav__item--link">
<font-awesome-icon icon="images" />
</nuxt-link>
</div>

+ 11
- 3
src/components/Layout/Titlebar.vue View File

@@ -4,12 +4,12 @@
<div class="titlebar__left">
<div class="logo">
<span>{{ $dream.name }}</span>
<span class="ml-2">{{ $dream.version }}</span>
<span class="ml-1">{{ $dream.version }}</span>
</div>

<div class="logo__greetings">
<span v-if="!isBadTime">{{ greetings }}</span>
<span v-else><img src="~/assets/images/games/sans.png"> i don't like what you are doing.</span>
<span v-else class="badtime"><img src="~/assets/images/games/sans.png"> i don't like what you are doing.</span>
</div>
</div>

@@ -168,7 +168,15 @@ export default {
@apply text-white text-sm font-light px-3 select-none;

img {
height: 30px;
height: 20px;
}

.badtime {
@apply flex items-center;

img {
@apply mr-1;
}
}
}


+ 177
- 30
src/components/Nudify/NudifyMaskPhoto.vue View File

@@ -1,70 +1,217 @@
<template>
<div class="box mask">
<div class="box__photo mask__photo" />
<div class="box mask"
:class="maskClass"
@dragenter="onDragEnter"
@dragover="onDragOver"
@dragleave="onDragLeave"
@drop="onDrop">
<!-- Dragging -->
<div class="mask__dropzone">
<h2>Drop the {{ mask.title }} here!</h2>
</div>

<div class="box__photo mask__photo" data-private>
<div v-if="file.exists"
class="mask__photo__preview"
:style="{ backgroundImage: `url('${file.url}')` }"
@click="openPreview" />
</div>

<div class="box__header">
<span class="title">{{ title }}</span>
<span class="title">{{ mask.title }} <AppTip :tooltip="mask.description" /></span>
</div>

<input
v-show="false"
ref="photo"
type="file"
accept="image/png"
@change="change">

<div class="box__footer buttons">
<button class="button button--sm">
<FontAwesomeIcon icon="undo" />
<!--
<button v-if="mask.canShowEdit"
key="edit"
v-tooltip="'Edit with the photo editor.'"
class="button button--sm">
<FontAwesomeIcon icon="paint-brush" />
</button>
-->

<button class="button button--sm">
<FontAwesomeIcon icon="file-download" />
<button v-if="mask.canShowUpload"
key="upload"
v-tooltip="'Upload mask.'"
class="button button--sm"
@click="$refs.photo.click()">
<FontAwesomeIcon icon="file-upload" />
</button>

<button class="button button--primary button--sm">
<FontAwesomeIcon icon="file-upload" />
<button v-if="mask.canShowSave"
key="save"
v-tooltip="'Save mask.'"
class="button button--sm button--info"
@click="mask.save()">
<FontAwesomeIcon icon="save" />
</button>

<button v-if="mask.canShowGenerate"
key="play"
v-tooltip="'Generate.'"
class="button button--success button--sm"
@click="generate()">
<FontAwesomeIcon icon="play" />
</button>
</div>
</div>
</template>

<script>
import { File } from '~/modules'
import { DragDropMixin } from '~/mixins'

export default {
mixins: [DragDropMixin],

props: {
photo: {
mask: {
type: Object,
required: true,
},
step: {
type: String,
required: true,
},
},

data: () => ({
renderPhoto: true,
}),

computed: {
title() {
switch (this.step) {
case 'correct':
return 'Corrected'
file() {
return this.mask.file
},

case 'mask':
return 'Mask'
maskClass() {
return {
'mask--dragging': this.isDragging,
}
},
},

case 'maskref':
return 'Maskref'
mounted() {
if (this.mask.isReadOnly) {
this.isDragEnabled = false
}

case 'maskdet':
return 'Maskdet'
this.file.on('loading', this.onLoadingPhoto, this)
this.file.on('loaded', this.onLoadedPhoto, this)
},

case 'maskfin':
return 'Maskfin'
beforeDestroy() {
this.file.off('loading', this.onLoadingPhoto, this)
this.file.off('loaded', this.onLoadedPhoto, this)
},

methods: {
async change(event) {
const { files } = event.target

default:
return this.step
if (files.length === 0) {
return
}

const file = await File.fromPath(files[0].path, { watch: false })

file.validateAs('image/png')

this.file.writeFile(file)

event.target.value = ''
},

generate() {
this.mask.photo.generateMask(this.mask.id)
},

openPreview() {
this.mask.file.openItem()
},

onLoadingPhoto() {
this.renderPhoto = false
},

onLoadedPhoto() {
this.$nextTick(() => {
this.renderPhoto = true
})
},

async onURL(url) {
const file = await File.fromUrl(url, { watch: false })

file.validateAs('image/png')

this.file.writeFile(file)
},

async onFiles(files) {
const file = await File.fromPath(files[0].path, { watch: false })

file.validateAs('image/png')

this.file.writeFile(file)
},
},
}
</script>

<style lang="scss" scoped>
.mask {
@apply mb-0 relative;

&.mask--dragging {
.mask__dropzone {
@apply flex opacity-100;
}
}
}

.mask__dropzone {
@apply absolute left-0 right-0 top-0 bottom-0 z-50;
@apply bg-menus-dark-80 items-center justify-center;
@apply hidden opacity-0 pointer-events-none;
backdrop-filter: blur(6px);
transition: opacity 0.2s ease-in-out;
will-change: opacity;

h2 {
@apply text-white font-bold text-xl;
}
}

.mask__photo {
background-image: url('~@/assets/images/curls.png');
background-image: url('~@/assets/images/repeated-square-dark.png');
will-change: transform;
height: 250px;
height: 350px;
}

.mask__photo__preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center;
cursor: zoom-in;
}

.box__header {
@apply pb-3;

.tip {
@apply ml-2;
}
}

.buttons {
@apply justify-end;

.button {
max-width: 90px;
}
}
</style>

+ 36
- 0
src/components/Nudify/NudifyPhotoBadge.vue View File

@@ -0,0 +1,36 @@
<template>
<div v-tooltip="photo.avatar.name" class="badge" :style="{ backgroundColor: color }">
{{ letter }}
</div>
</template>

<script>
export default {
props: {
photo: {
type: Object,
required: true,
},
},

computed: {
color() {
return this.photo.avatar.color
},

letter() {
return this.photo.avatar.name[0]
},
},
}
</script>

<style lang="scss" scoped>
.badge {
@apply flex justify-center items-center;
@apply rounded-full text-lg font-bold text-white;
-webkit-text-stroke: 1px black;
width: 30px;
height: 30px;
}
</style>

+ 59
- 0
src/components/Nudify/NudifyPhotoPreview.vue View File

@@ -0,0 +1,59 @@
<template>
<div class="preview" :style="photoURL" data-private>
<NudifyPhotoBadge v-if="badge" :photo="photo" />
</div>
</template>

<script>
export default {
props: {
photo: {
type: Object,
required: true,
},

badge: {
type: Boolean,
default: true,
},

live: {
type: Boolean,
default: false,
},
},

computed: {
photoURL() {
let { file } = this.photo

if (this.live && this.photo.finished && this.photo.runs.length > 0) {
const [run] = this.photo.runs

if (run.outputFile && run.outputFile.exists) {
file = run.outputFile
}
}

return {
backgroundImage: `url("${file.url}")`,
}
},
},
}
</script>

<style lang="scss" scoped>
.preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center;
}

.badge {
@apply absolute z-20;
top: 5px;
right: 5px;
width: 30px;
height: 30px;
}
</style>

+ 152
- 179
src/components/Nudify/NudifyPhotoRun.vue View File

@@ -1,9 +1,11 @@
<template>
<div class="photo-run"
:class="previewClass"
data-private>
<div class="run__preview"
:style="previewStyle" />
<div class="box run" :class="previewClass">
<div class="box__photo run__photo" data-private>
<div v-if="file.exists"
class="run__photo__preview"
:style="{ backgroundImage: `url('${file.url}')` }"
@click="openPreview" />
</div>

<div
v-if="run.preferences.body.randomize || run.preferences.body.progressive.enabled"
@@ -34,151 +36,78 @@
</div>
</div>

<div class="run__content">
<div v-if="run.running"
class="content__item">
<p class="text-white">
<span>
<font-awesome-icon icon="running" />
</span>
<span>{{ run.timer.duration }}s</span>
</p>
</div>

<div v-else-if="run.failed"
class="content__item">
<p class="text-danger-500">
<span>
<font-awesome-icon icon="exclamation-circle" />
</span>
<span>Error!</span>
</p>
<div class="box__footer buttons">
<div v-if="run.running" class="button button--sm">
<span class="icon">
<font-awesome-icon icon="running" />
</span>
<span>{{ run.timer.duration }}s</span>
</div>

<div v-else-if="run.finished"
class="content__item">
<p class="text-white">
<span>
<font-awesome-icon icon="heart" />
</span>
<span>{{ run.timer.duration }}s</span>
</p>
<div v-else-if="run.failed" class="button button--danger button--sm">
<span class="icon">
<font-awesome-icon icon="exclamation-circle" />
</span>
<span>Error!</span>
</div>

<div v-else
class="content__item">
<p class="text-white">
<span>
<font-awesome-icon icon="clock" />
</span>
</p>
<div v-else-if="run.finished" class="button button--sm">
<span class="icon">
<font-awesome-icon icon="heart" />
</span>
<span>{{ run.timer.duration }}s</span>
</div>

<div v-show="run.finished && run.outputFile.exists"
class="content__item">
<button
v-tooltip="'Open photo'"
class="button button--info button--sm"
@click.prevent="open">
<font-awesome-icon icon="image" />
</button>
<div v-else class="button button--sm">
<span>
<font-awesome-icon icon="clock" />
</span>
</div>

<div v-show="run.finished && run.outputFile.exists"
class="content__item">
<button
v-tooltip="'Save photo'"
class="button button--info button--sm"
@click.prevent="save">
<button
v-tooltip="'View terminal'"
class="button button--sm"
@click.prevent="$refs.terminalDialog.showModal()">
<font-awesome-icon icon="terminal" />
</button>

<!--
<button
v-if="run.finished && run.outputFile.exists"
v-tooltip="'Open photo'"
class="button button--info button--sm"
@click.prevent="open">
<font-awesome-icon icon="image" />
</button>
-->

<button
v-if="run.finished && run.outputFile.exists"
class="button button--success button--sm"
@click.prevent="save">
<span class="icon">
<font-awesome-icon icon="save" />
</button>
</div>

<div v-show="run.finished"
class="content__item">
<button v-tooltip="'Rerun'"
class="button button--success button--sm"
@click.prevent="rerun">
<font-awesome-icon icon="undo" />
</button>
</div>

<div v-show="run.running"
class="content__item">
<button v-tooltip="'Stop'"
class="button button--danger button--sm"
@click.prevent="cancel">
<font-awesome-icon icon="stop" />
</button>
</div>

<div v-show="hasMaskfin"
class="content__item">
<button
v-tooltip="'View Maskfin'"
class="button button--sm"
@click.prevent="$refs.maskfinDialog.showModal()">
<font-awesome-icon icon="mask" />
</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" />
</button>
</div>
</span>
<span>Save</span>
</button>

<button v-if="run.finished"
class="button button--info button--sm"
@click.prevent="rerun">
<span class="icon">
<font-awesome-icon icon="retweet" />
</span>
<span>Rerun</span>
</button>

<button v-if="run.running"
v-tooltip="'Stop'"
class="button button--danger button--sm"
@click.prevent="cancel">
<font-awesome-icon icon="stop" />
</button>
</div>

<!-- Maskfin Dialog -->
<dialog v-if="hasMaskfin"
ref="maskfinDialog">
<div class="dialog__content dialog__maskfin">
<div class="maskfin__preview">
<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 with the editor 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">guide</a>.
</p>
</div>

<div class="dialog__buttons">
<button class="button"
@click.prevent="addMaskToQueue">
Add to queue
</button>

<button class="button button--success"
@click.prevent="saveMask">
Save
</button>

<button class="button button--danger"
@click.prevent="$refs.maskfinDialog.close()">
Close
</button>
</div>
</div>
</dialog>

<!-- Terminal Dialog -->
<dialog ref="terminalDialog">
<div class="dialog__content">
@@ -192,8 +121,7 @@
</div>

<div class="dialog__buttons">
<button class="button button--danger"
@click.prevent="$refs.terminalDialog.close()">
<button class="button button--danger" @click="$refs.terminalDialog.close()">
Close
</button>
</div>
@@ -225,6 +153,10 @@ export default {
},

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

previewStyle() {
if (!this.run.finished) {
return {}
@@ -243,10 +175,6 @@ export default {
}
},

hasMaskfin() {
return this.run.maskfinFile.exists
},

manualURL() {
return dreamtrack.get(
'urls.docs.manual',
@@ -260,7 +188,7 @@ export default {
this.run.outputFile.save(this.run.outputName)
},

open() {
openPreview() {
this.run.outputFile.openItem()
},

@@ -284,9 +212,85 @@ export default {
</script>

<style lang="scss" scoped>
.run {
@apply mb-0 relative border border-transparent;

&.run--running {
@apply border-primary;
}

&.run--failed {
@apply border-danger;
}

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

.run__photo {
background-image: url('~@/assets/images/repeated-square-dark.png');
will-change: transform;
height: 500px;
}

.run__photo__preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center;
cursor: zoom-in;
}

.run__preferences {
@apply absolute top-0 z-20;
@apply flex opacity-0 bg-menus-default-80 w-full;
backdrop-filter: blur(6px);
transition: opacity 0.1s linear;
height: 80px;

.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;
}
}
}
}

.buttons {
@apply justify-end;

.button {
max-width: 100px;
}
}

.terminal {
@apply p-2 bg-black overflow-auto rounded;
height: 400px;

li {
@apply font-mono text-xs text-generic-100 mb-3 block;

&.text-danger {
@apply text-danger-500;
}
}
}
</style>

<style lang="scss" scoped>
/*
.photo-run {
@apply relative border-2 border-dark-500;
background-image: url('~@/assets/images/curls.png'); /* Background pattern from Toptal Subtle Patterns */
background-image: url('~@/assets/images/curls.png');
min-height: 512px;
transition: border-color 0.2s linear;

@@ -328,25 +332,6 @@ export default {
transition: opacity 0.1s linear;
}

.run__preferences {
@apply flex top-0;
height: 80px;

.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 bottom-0;
height: 100px;
@@ -408,17 +393,5 @@ export default {
}
}
}

.terminal {
@apply p-2 mb-2 bg-black overflow-auto rounded;
height: 400px;

li {
@apply font-mono text-xs text-generic-100 mb-2 block;

&.text-danger {
@apply text-danger-500;
}
}
}
*/
</style>

+ 2
- 3
src/components/Nudify/NudifyUpload.vue View File

@@ -1,6 +1,5 @@
<template>
<div id="uploader"
class="uploader">
<div id="uploader" class="uploader">
<!-- Uploader Selection -->
<div class="uploader__selection">
<div class="selection__content" />
@@ -99,7 +98,7 @@ export default {
} catch (error) {
throw new Warning(
'Upload failed.',
'Unable to download the photo, please verify that the address is correct and that you are connected to the Internet.',
'Unable to download the photo, please verify that the address is valid.',
error,
)
}

+ 44
- 0
src/components/Photo.vue View File

@@ -0,0 +1,44 @@
<template>
<div class="box photo">
<div class="box__photo">
<div class="photo__preview"
:style="{ backgroundImage: `url('${file.url}')` }"
@click="openPreview" />
</div>
</div>
</template>

<script>
export default {
props: {
file: {
type: Object,
required: true,
},
},

methods: {
openPreview() {
this.file.openItem()
},
},
}
</script>

<style lang="scss" scoped>
.photo {
&::v-deep {
.box__photo {
background-image: url('~@/assets/images/repeated-square-dark.png');
will-change: transform;
height: 300px;
}
}
}

.photo__preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center;
cursor: zoom-in;
}
</style>

+ 15
- 11
src/components/Queue/QueueBar.vue View File

@@ -14,12 +14,11 @@
<QueuePhoto
v-for="(photo, index) of $nudify.waiting"
:key="index"
:photo="photo"
data-private />
:photo="photo" />
</div>
</section>

<div class="queue__section queue__section--pending">
<section class="queue__section queue__section--pending">
<div class="queue__header">
<p class="title">
<span class="icon"><font-awesome-icon icon="clipboard-list" /></span>
@@ -36,9 +35,9 @@
:photo="photo"
data-private />
</div>
</div>
</section>

<div class="queue__section queue__section--finished">
<section class="queue__section queue__section--finished">
<div class="queue__header">
<p class="title">
<span class="icon"><font-awesome-icon icon="clipboard-check" /></span>
@@ -55,7 +54,7 @@
:photo="photo"
data-private />
</div>
</div>
</section>
</div>
</template>

@@ -67,13 +66,12 @@ export default {

<style lang="scss" scoped>
.queue {
@apply flex flex-col;
@apply bg-menus border-l border-menus-light relative;
grid-area: queue;
@apply bg-menus relative;
}

.queue__section {
@apply flex-1 flex flex-col;
@apply flex flex-col;
height: calc((100vh - 80px) / 3);

&.queue__section--running {
}
@@ -102,8 +100,14 @@ export default {
}

.queue__content {
@apply flex-1 grid grid-cols-2 grid-rows-2;
@apply flex-1;
@apply flex flex-wrap;
@apply overflow-y-auto whitespace-no-wrap;

.photo {
@apply w-1/2;
height: 200px;
}
}

/*

+ 26
- 50
src/components/Queue/QueuePhoto.vue View File

@@ -1,27 +1,27 @@
<template>
<div class="photo" :class="photoClass">
<div class="photo__preview" :style="previewStyle" />

<img v-tooltip="photo.avatar.name" :src="photo.avatar.image" class="photo__badge">
<NudifyPhotoPreview :photo="photo" :live="true" />

<div class="photo__content">
<span v-show="photo.running || photo.finished">{{ photo.timer.duration }}s</span>
<div class="photo__content__actions">
<span v-show="photo.running || photo.finished">{{ photo.timer.duration }}s</span>

<button v-tooltip="'Open'" @click="open">
<font-awesome-icon icon="external-link-square-alt" />
</button>
<button v-tooltip="'Open'" @click="open">
<font-awesome-icon icon="external-link-square-alt" />
</button>

<button v-show="photo.pending" v-tooltip="'Add to Queue'" @click="add">
<font-awesome-icon icon="play" />
</button>
<button v-show="photo.pending" v-tooltip="'Add to Queue'" @click="add">
<font-awesome-icon icon="play" />
</button>

<button v-show="photo.waiting" v-tooltip="'Remove from Queue'" @click="cancel">
<font-awesome-icon icon="sign-out-alt" />
</button>
<button v-show="photo.waiting" v-tooltip="'Remove from Queue'" @click="cancel">
<font-awesome-icon icon="sign-out-alt" />
</button>

<button v-show="photo.running" v-tooltip="'Stop'" @click="stop">
<font-awesome-icon icon="stop" />
</button>
<button v-show="photo.running" v-tooltip="'Stop'" @click="stop">
<font-awesome-icon icon="stop" />
</button>
</div>
</div>
</div>
</template>
@@ -36,22 +36,6 @@ export default {
},

computed: {
previewStyle() {
let photoPath = this.photo.file.path

if (this.photo.finished && this.photo.runs.length > 0) {
const [run] = this.photo.runs

if (run.outputFile.exists) {
photoPath = run.outputFile.path
}
}

return {
backgroundImage: `url("${photoPath}")`,
}
},

photoClass() {
return {
'photo--running': this.photo.running,
@@ -83,15 +67,15 @@ export default {
<style lang="scss" scoped>
.photo {
@apply relative border-2 border-transparent;
background-image: url('~@/assets/images/curls.png');
background-image: url('~@/assets/images/repeated-square-dark.png');
will-change: transform;

&.photo--running {
@apply border-primary-500;
@apply border-primary;
}

&.photo--failed {
@apply border-danger-500;
@apply border-danger;
}

&:hover {
@@ -101,24 +85,16 @@ export default {
}
}

.photo__preview {
@apply absolute top-0 bottom-0 left-0 right-0 z-10;
@apply bg-contain bg-no-repeat bg-center;
}

.photo__badge {
@apply absolute z-20;
top: 5px;
right: 5px;
width: 30px;
height: 30px;
}

.photo__content {
@apply absolute top-0 bottom-0 left-0 right-0 z-30;
@apply flex bg-dark-500-60 opacity-0;
@apply flex justify-center items-center bg-menus-dark-60 opacity-0;
backdrop-filter: blur(4px);
transition: opacity 0.1s linear;
}

.photo__content__actions {
@include centered();
@apply flex-1;

span,
button {
@@ -126,7 +102,7 @@ export default {
}

span {
@apply flex items-center justify-center;
@include centered();
@apply text-white font-semibold;
}


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

@@ -58,7 +58,9 @@
:label="label"
action-class="preference__list">
<span class="font-bold">{{ value$.size }}</span>
<span v-if="value$.randomize.enabled === true">Randomized ({{ value$.randomize.min }} - {{ value$.randomize.max }})</span>
<span v-if="value$.randomize.enabled === true">
Randomized ({{ value$.randomize.min }} - {{ value$.randomize.max }})
</span>
<span v-else-if="value$.progressive === true">Progresive</span>
</MenuItem>
</template>

+ 8
- 1
src/components/Settings/SettingsField.vue View File

@@ -55,6 +55,11 @@ export default {
default: null,
},

optionsField: {
type: String,
default: 'options',
},

attrs: {
type: Object,
default: null,
@@ -77,7 +82,7 @@ export default {
return this.options
}

return this.field.options
return this.field[this.optionsField]
},

valueLabel() {
@@ -132,6 +137,8 @@ export default {
} else {
this.$settings.set(this.field.id, value)
}

this.$emit('change')
},
},


+ 56
- 4
src/components/Settings/SettingsPreferences.vue View File

@@ -3,9 +3,12 @@
<!-- Basics -->
<section id="preferences-basics" class="box">
<div class="box__content">
<SettingsField v-model="value$" field-id="preferences.mode" />
<SettingsField v-model="value$" field-id="preferences.mode" :options-field="optionsField" />

<SettingsField v-if="value$.mode > 0" v-model="value$" field-id="preferences.advanced.scaleMode" />
<SettingsField v-if="value$.mode > 0"
v-model="value$"
field-id="preferences.advanced.scaleMode"
:options-field="optionsField" />
</div>
</section>

@@ -52,7 +55,9 @@

<SettingsField v-model="value$" field-id="preferences.body.randomize" />

<SettingsField v-model="value$" field-id="preferences.body.progressive.enabled" :description="`Body preferences will increase ${value$.body.progressive.rate} at each run.`" />
<SettingsField v-model="value$"
field-id="preferences.body.progressive.enabled"
:description="`Body preferences will increase ${value$.body.progressive.rate} at each run.`" />

<SettingsField v-if="!value$.body.randomize && value$.body.progressive.enabled"
v-model="value$"
@@ -73,9 +78,38 @@
</div>

<div class="box__content">
<SettingsField v-show="value$.advanced.scaleMode === 'padding'" v-model="value$" field-id="preferences.advanced.useColorPaddingStrip" />

<SettingsField v-model="value$" field-id="preferences.advanced.useColorTransfer" />
</div>
</section>

<SettingsField v-model="value$" field-id="preferences.advanced.useWaifu" />
<!-- Waifu2X -->
<section v-if="value$.mode > 1 && !animated" class="box">
<div class="box__header">
<h2 class="title">
Waifu2X.
</h2>
<h3 class="subtitle">
Settings for the upscale and denoise algorithm.
</h3>
</div>

<div v-if="requirements.canUseWaifu" class="box__content">
<SettingsField v-model="value$" field-id="preferences.advanced.waifu.enabled" />

<div v-if="value$.advanced.waifu.enabled">
<SettingsField v-model="value$" field-id="preferences.advanced.waifu.scale" />
<SettingsField v-model="value$" field-id="preferences.advanced.waifu.denoise" />
<SettingsField v-model="value$" field-id="preferences.advanced.waifu.tta" />
<SettingsField v-model="value$" field-id="preferences.advanced.waifu.arch" />
</div>
</div>

<div v-else class="box__content">
<nuxt-link to="/wizard/waifu" class="underline">
Install Waifu2X to use this feature.
</nuxt-link>
</div>
</section>
</div>
@@ -83,11 +117,29 @@

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

export default {
mixins: [VModel],

props: {
animated: {
type: Boolean,
default: false,
},
},

data: () => ({
requirements,
}),

computed: {
optionsField() {
return this.animated ? 'animated-options' : 'options'
},
},

mounted() {
tutorial.preferences()
},

+ 38
- 34
src/components/UI/AppAds.vue View File

@@ -1,10 +1,8 @@
<template>
<div v-if="show" class="ads">
<div v-if="showAd">
<ins data-revive-zoneid="3" data-revive-id="7e048c7f8d85676181a4b65ec87d61fe" />
</div>
<div v-show="ready" class="ads">
<div v-show="isAd" ref="adContainer" />

<HelpLesson v-if="showLesson"
<HelpLesson v-if="isLesson"
:lesson="lesson"
:small="true"
@click="$router.push('/help')" />
@@ -12,11 +10,12 @@
</template>

<script>
import { isNil, sample } from 'lodash'
import { sample } from 'lodash'
import { settings } from '~/modules/system'
import { Help } from '~/modules'
import { dreamtrack } from '~/modules/services'
import { Help, events } from '~/modules'

const CHANGE_INTERVAL = process.env.NODE_ENV === 'development' ? 1 * 60 * 1000 : 15 * 60 * 1000
const CHANGE_INTERVAL = process.env.NODE_ENV === 'development' ? 15 * 1000 : 15 * 60 * 1000

export default {
data: () => ({
@@ -27,30 +26,20 @@ export default {
}),

computed: {
show() {
return !isNil(this.type)
},

isAd() {
return this.type === 'ad'
},

showAd() {
return this.isAd && this.ready
},

isLesson() {
return this.type === 'lesson'
},

showLesson() {
return this.isLesson && this.ready
},
},

created() {
mounted() {
this.init()
this.interval = setInterval(this.init.bind(this), CHANGE_INTERVAL)

events.on('settings:ads', this.init.bind(this))
},

beforeDestroy() {
@@ -61,6 +50,18 @@ export default {

methods: {
init() {
this.ready = false

this.chooseType()

if (this.isAd) {
this.refreshAd()
} else if (this.isLesson) {
this.refreshLesson()
}
},

chooseType() {
const types = []

if (settings.app.showAds) {
@@ -79,14 +80,6 @@ export default {
} else {
this.type = sample(types)
}

this.ready = false

if (this.isAd) {
this.refreshAd()
} else if (this.isLesson) {
this.refreshLesson()
}
},

refreshAd() {
@@ -94,16 +87,22 @@ export default {
return
}

if (!window.reviveAsync['7e048c7f8d85676181a4b65ec87d61fe']) {
const id = dreamtrack.get('ads.id', '3fe087377ab3999f9bd455cef8976f0b')

if (!window.reviveAsync[id]) {
return
}

const ins = document.createElement('ins')
ins.setAttribute('data-revive-zoneid', dreamtrack.get('ads.zoneid', '1'))
ins.setAttribute('data-revive-id', id)

this.$refs.adContainer.innerHTML = ''
this.$refs.adContainer.appendChild(ins)

this.$nextTick(() => {
window.reviveAsync[id].refresh()
this.ready = true

this.$nextTick(() => {
window.reviveAsync['7e048c7f8d85676181a4b65ec87d61fe'].refresh()
})
})
},

@@ -118,6 +117,7 @@ export default {
<style lang="scss" scoped>
.ads {
@apply border-t border-menus-light;
height: 250px;

&::v-deep .lesson {
@apply rounded-none cursor-pointer;
@@ -131,5 +131,9 @@ export default {
@apply rounded-none;
}
}

.lesson {
height: inherit;
}
}
</style>

+ 80
- 0
src/components/UI/AppBox.vue View File

@@ -0,0 +1,80 @@
<template>
<div class="box">
<!-- Photo -->
<div v-if="showPhoto" class="box__photo">
<slot name="photo">
<div class="box__photo__preview" :class="photo" />
</slot>
</div>

<!-- Header -->
<div v-if="showHeader" class="box__header">
<slot name="header">
<h2 class="title">
{{ title }}
</h2>
<h3 v-if="subtitle" class="subtitle">
{{ subtitle }}
</h3>
</slot>
</div>

<!-- Content -->
<div v-if="content" class="box__content" v-html="prettyContent" />

<div v-else class="box__content">
<slot />
</div>

<!-- Footer -->
<slot name="footer" />
</div>
</template>

<script>
import MarkdownIt from 'markdown-it'

const md = new MarkdownIt()

export default {
props: {
photo: {
type: [String, Array],
default: null,
},

title: {
type: String,
default: null,
},

subtitle: {
type: String,
default: null,
},

content: {
type: String,
default: null,
},
},

computed: {
showPhoto() {
return this.photo || this.$slots.photo
},

showHeader() {
return this.title || this.$slots.header
},

prettyContent() {
return md.render(this.content)
},
},
}
</script>

<style lang="scss" scoped>

</style>

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

@@ -9,7 +9,7 @@ export default {
props: {
icon: {
type: [String, Object],
default: 'info-circle',
default: 'question-circle',
},
tooltip: {
type: [String, Object],

+ 21
- 17
src/components/UI/ProjectUpdate.vue View File

@@ -3,19 +3,18 @@
<div class="update__info">
<!-- Logo -->
<figure>
<img :src="info.logo">
<img :src="data.logo">
</figure>

<h1 class="title">
{{ info.title }} <span v-tooltip="'New version'">{{ updater.latest.tag_name }}</span>
{{ data.name }} <span v-tooltip="'New version'">{{ updater.latest.tag_name }}</span>
</h1>

<h2 v-if="!updater.update.active" class="subtitle">
{{ info.description }}
{{ data.description }}
</h2>
</div>


<!-- Downloading -->
<div v-if="isDownloading && updater.update.progress >= 0" class="update__status">
Downloading ~ <strong>{{ updater.update.progress }}%</strong> ~ {{ updater.update.written | size }}/{{ updater.update.total | size }} MB.
@@ -45,15 +44,20 @@
<button v-show="updater.update.active" class="button button--danger" @click.prevent="updater.cancel()">
Cancel
</button>

<button v-tooltip="'Show a list of links to download the update manually.'" class="button button--info" @click.prevent="$refs.mirrorsDialog.show()">
Mirrors
</button>
</div>

<!-- Project buttons -->
<div class="update__actions__extra">
<a v-for="(item, index) in info.navigation" :key="index" :href="item.href" target="_blank" class="button button--sm">{{ item.label }}</a>

<button v-tooltip="'Show a list of links to download the update manually.'" class="button button--info button--sm" @click.prevent="$refs.mirrorsDialog.show()">
Mirrors
</button>
<a v-for="(item, index) in data.data.navigation"
:key="index"
:href="item.
ref"
target="_blank"
class="button button--sm">{{ item.label }}</a>
</div>

<!-- Hint -->
@@ -87,8 +91,7 @@

<script>
import { toNumber } from 'lodash'
import { dreamtrack } from '~/modules/services'
import * as providers from '~/modules/updater'
import * as projects from '~/modules/projects'

export default {
filters: {
@@ -115,13 +118,16 @@ export default {
},

data: () => ({
updater: null,
info: null,
data: null,
}),

computed: {
updater() {
return this.data.updater
},

isReady() {
return this.updater && this.info
return this.updater
},

currentVersion() {
@@ -139,9 +145,7 @@ export default {

created() {
// eslint-disable-next-line import/namespace
this.updater = providers[this.project]

this.info = dreamtrack.get(['projects', this.project, 'about'], {})
this.data = projects[this.project]
},

beforeDestroy() {

+ 11
- 12
src/electron/src/index.js View File

@@ -205,8 +205,8 @@ class DreamApp {
const { default: installExtension, VUEJS_DEVTOOLS } = require('electron-devtools-installer')

installExtension(VUEJS_DEVTOOLS)
.then((extension) => console.log(`Added Extension: ${extension.name}`))
.catch((err) => console.log('An error occurred: ', err))
.then((extension) => logger.debug(`Added Extension: ${extension.name}`))
.catch((err) => logger.debug('An error occurred: ', err))
}

const contextMenu = require('electron-context-menu')
@@ -236,6 +236,8 @@ class DreamApp {
static createWindow() {
logger.info('Creating window...')

const iconPath = resolve(config.rootDir, 'dist', 'icon.ico')

// browser window.
this.window = new BrowserWindow({
width: 1200,
@@ -245,7 +247,7 @@ class DreamApp {
frame: false,
show: false,
backgroundColor: '#060709',
icon: resolve(config.rootDir, 'dist', 'icon.ico'),
icon: fs.existsSync(iconPath) ? iconPath : undefined,

webPreferences: {
nodeIntegration: true,