@@ -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/" |
@@ -1,10 +0,0 @@ | |||
{ | |||
"systemParams": "win32-x64-72", | |||
"modulesFolders": [], | |||
"flags": [], | |||
"linkedModules": [], | |||
"topLevelPatterns": [], | |||
"lockfileEntries": {}, | |||
"files": [], | |||
"artifacts": {} | |||
} |
@@ -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 |
@@ -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', |
@@ -88,10 +88,7 @@ sw.* | |||
# Mac OSX | |||
.DS_Store | |||
# lock file | |||
*.lock | |||
# | |||
*.tgz | |||
scripts/decrypt.js | |||
scripts/decrypt.js |
@@ -0,0 +1,4 @@ | |||
/* purgecss start ignore */ | |||
@import "./reset/all.scss"; | |||
@import "./components/all.scss"; | |||
/* purgecss end ignore */ |
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 { |
@@ -2,4 +2,8 @@ | |||
transition-property: #{$property}; | |||
transition-duration: $duration; | |||
transition-timing-function: $timing; | |||
} | |||
} | |||
@mixin centered() { | |||
@apply flex items-center justify-center; | |||
} |
@@ -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 */ |
@@ -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,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> |
@@ -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> |
@@ -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> |
@@ -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; | |||
} | |||
} | |||
} | |||
@@ -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> |
@@ -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> |
@@ -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> |
@@ -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> |
@@ -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, | |||
) | |||
} |
@@ -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> |
@@ -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; | |||
} | |||
} | |||
/* |
@@ -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; | |||
} | |||
@@ -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> |
@@ -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') | |||
}, | |||
}, | |||
@@ -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() | |||
}, |
@@ -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> |
@@ -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> |
@@ -9,7 +9,7 @@ export default { | |||
props: { | |||
icon: { | |||
type: [String, Object], | |||
default: 'info-circle', | |||
default: 'question-circle', | |||
}, | |||
tooltip: { | |||
type: [String, Object], |
@@ -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() { |
@@ -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, | |||