@@ -239,8 +239,7 @@ export default { | |||
<style lang="scss" scoped> | |||
.photo-run { | |||
@apply relative; | |||
@apply bg-cover bg-center border-2 border-dark-100; | |||
@apply relative border-2 border-dark-100; | |||
background-image: url('~@/assets/images/curls.png'); /* Background pattern from Toptal Subtle Patterns */ | |||
min-height: 512px; | |||
transition: all .15s linear; | |||
@@ -268,6 +267,7 @@ export default { | |||
.run__preview { | |||
@apply absolute opacity-0 left-0 right-0 top-0 bottom-0 z-10; | |||
@apply bg-cover bg-center; | |||
transition: all .3s linear; | |||
} | |||
} |
@@ -2,7 +2,7 @@ | |||
<section class="box box--items"> | |||
<div class="box__content"> | |||
<box-item :description="`Value: ${currentValue.size}`" :label="`${label} size`"> | |||
<VueSlider v-model="currentValue.size" :min="0.3" :max="2" :interval="0.05" /> | |||
<VueSlider v-model="currentValue.size" :min="min" :max="max" :interval="0.05" /> | |||
</box-item> | |||
<box-item | |||
@@ -39,8 +39,8 @@ | |||
<VueSlider | |||
v-model="randomizeRange" | |||
:min-range="0.05" | |||
:min="minRange" | |||
:max="maxRange" | |||
:min="min" | |||
:max="max" | |||
:interval="0.05" /> | |||
</box-item> | |||
</div> | |||
@@ -59,11 +59,11 @@ export default { | |||
type: String, | |||
required: true, | |||
}, | |||
minRange: { | |||
min: { | |||
type: Number, | |||
default: 0.3, | |||
}, | |||
maxRange: { | |||
max: { | |||
type: Number, | |||
default: 2, | |||
}, |
@@ -1,25 +1,25 @@ | |||
<template> | |||
<div class="c-preferences"> | |||
<section v-show="currentValue.advanced.transformMode !== 'import-maskfin'" class="box box--items"> | |||
<section v-show="currentValue.advanced.transformMode !== 'import-maskfin'" id="preferences-runs" class="box box--items"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
Per run. | |||
</h2> | |||
<h3 class="subtitle"> | |||
Customize what will happen in each transformation. | |||
Customize what will happen when you nudify. | |||
</h3> | |||
</div> | |||
<div class="box__content"> | |||
<box-item | |||
label="Runs." | |||
description="Number of times the photo will be transformed."> | |||
description="Number of times the photo will be nudified."> | |||
<input v-model="currentValue.body.executions" type="number" min="1" class="input"> | |||
</box-item> | |||
<box-item | |||
label="Randomize." | |||
description="Random body preferences will be set at each run."> | |||
description="Set random body preferences at each run."> | |||
<select v-model="currentValue.body.randomize" class="input"> | |||
<option :value="true"> | |||
Enabled | |||
@@ -33,7 +33,7 @@ | |||
<box-item | |||
v-show="!currentValue.body.randomize" | |||
label="Progressive." | |||
:description="`Body preferences will increase their value ${currentValue.body.progressive.rate} at each run.`"> | |||
:description="`Body preferences will increase ${currentValue.body.progressive.rate} at each run.`"> | |||
<select v-model="currentValue.body.progressive.enabled" class="input"> | |||
<option :value="true"> | |||
Enabled | |||
@@ -45,8 +45,8 @@ | |||
</box-item> | |||
<box-item | |||
v-show="!currentValue.body.randomize" | |||
label="Progressive Rate." | |||
v-show="!currentValue.body.randomize && currentValue.body.progressive.enabled" | |||
label="Progressive rate." | |||
:description="`Value: ${currentValue.body.progressive.rate}`"> | |||
<VueSlider v-model="currentValue.body.progressive.rate" :min="0.1" :max="0.9" :interval="0.05" /> | |||
</box-item> | |||
@@ -54,7 +54,7 @@ | |||
</section> | |||
<!-- Boobs --> | |||
<Preference v-model="currentValue.body.boobs" label="Boobs" /> | |||
<Preference id="preferences-body" v-model="currentValue.body.boobs" label="Boobs" /> | |||
<!-- Areola --> | |||
<Preference v-model="currentValue.body.areola" label="Areola" /> | |||
@@ -63,13 +63,13 @@ | |||
<Preference v-model="currentValue.body.nipple" label="Nipple" /> | |||
<!-- Vagina --> | |||
<Preference v-model="currentValue.body.vagina" label="Vagina" :max-range="1.5" /> | |||
<Preference v-model="currentValue.body.vagina" label="Vagina" :max="1.5" /> | |||
<!-- Pubic Hair --> | |||
<Preference v-model="currentValue.body.pubicHair" label="Pubic Hair" :min-range="0" /> | |||
<Preference v-model="currentValue.body.pubicHair" label="Pubic Hair" :min="0" /> | |||
<!-- Advanced --> | |||
<section class="box box--items"> | |||
<section id="preferences-advanced" class="box box--items"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
Advanced. | |||
@@ -81,6 +81,7 @@ | |||
<div class="box__content"> | |||
<box-item | |||
id="preferences-advanced-scale" | |||
label="Scale method." | |||
description="Method to scale the photo to 512x512"> | |||
<select v-model="currentValue.advanced.scaleMode" class="input"> | |||
@@ -106,8 +107,22 @@ | |||
</box-item> | |||
<box-item | |||
label="Transform method." | |||
description="Transformation method, only recommended for advanced users."> | |||
id="preferences-advanced-color" | |||
label="Color transfer." | |||
description="Use a experimental algorithm to try to recover the original colors of the photo."> | |||
<select v-model="currentValue.advanced.useColorTransfer" class="input"> | |||
<option :value="true"> | |||
Enabled | |||
</option> | |||
<option :value="false"> | |||
Disabled | |||
</option> | |||
</select> | |||
</box-item> | |||
<box-item | |||
label="Transformation method." | |||
description="Advanced users. Indicates additional options for transformation."> | |||
<select v-model="currentValue.advanced.transformMode" class="input"> | |||
<option value="normal"> | |||
Nudify | |||
@@ -120,28 +135,20 @@ | |||
</option> | |||
</select> | |||
</box-item> | |||
<box-item | |||
label="Color transfer." | |||
description="Use a experimental algorithm to try to recover the original colors of the photo."> | |||
<select v-model="currentValue.advanced.useColorTransfer" class="input"> | |||
<option :value="true"> | |||
Enabled | |||
</option> | |||
<option :value="false"> | |||
Disabled | |||
</option> | |||
</select> | |||
</box-item> | |||
</div> | |||
</section> | |||
</div> | |||
</template> | |||
<script> | |||
import { tutorial } from '~/modules' | |||
import { VModel } from '~/mixins' | |||
export default { | |||
mixins: [VModel], | |||
mounted() { | |||
tutorial.preferences() | |||
}, | |||
} | |||
</script> |
@@ -152,14 +152,18 @@ export class Photo { | |||
get scaleMode() { | |||
const { scaleMode } = this.preferences.advanced | |||
if (scaleMode === 'cropjs' && !this.fileCrop.exists) { | |||
// no crop, automatically rescale for convenience | |||
return 'auto-rescale' | |||
} | |||
if (scaleMode === 'cropjs') { | |||
if (!this.canModify) { | |||
this.consola.debug('Wanted to use the cropper but we cannot modify.') | |||
return 'auto-rescale' | |||
} | |||
if ((scaleMode === 'cropjs' || scaleMode === 'overlay') && !this.canModify) { | |||
// this file can't be modified | |||
return 'auto-rescale' | |||
if (!this.fileCrop.exists) { | |||
this.consola.debug('Wanted to use the cropper but the file does not exist.') | |||
// no crop, automatically rescale for convenience | |||
return 'auto-rescale' | |||
} | |||
} | |||
return scaleMode |
@@ -71,7 +71,7 @@ class LogRocketService extends BaseService { | |||
}, | |||
}, | |||
dom: { | |||
isEnabled: settings.telemetry?.dom || true, | |||
isEnabled: settings.telemetry?.dom, | |||
baseHref: $provider.ngrok.getAddress() || nucleus.urls?.internal?.cdn, | |||
}, | |||
} | |||
@@ -85,7 +85,7 @@ class LogRocketService extends BaseService { | |||
try { | |||
LogRocket.init(this.accessToken, this.config) | |||
LogRocket.identify(settings.payload.user, { | |||
LogRocket.identify(settings.user, { | |||
settings: settings.payload, | |||
}) | |||
@@ -94,6 +94,7 @@ class LogRocketService extends BaseService { | |||
consola.info('LogRocket enabled!') | |||
consola.debug(`Access Token: ${this.accessToken}`) | |||
consola.debug(this.config) | |||
} catch (err) { | |||
consola.warn('LogRocket setup failed!', err) | |||
} |
@@ -10,7 +10,7 @@ | |||
import { isNil } from 'lodash' | |||
import axios from 'axios' | |||
import { BaseService } from './base' | |||
import { settings } from '../system' | |||
import { settings } from '../system/settings' | |||
import { Consola } from '../consola' | |||
const { system } = $provider | |||
@@ -36,6 +36,19 @@ export class NucleusService extends BaseService { | |||
return !isNil(this.appId) | |||
} | |||
/** | |||
* @type {Object} | |||
*/ | |||
get config() { | |||
return { | |||
disableTracking: false, | |||
disableErrorReports: true, | |||
userId: settings.user, | |||
version: process.env.npm_package_version, | |||
persist: true, | |||
} | |||
} | |||
/** | |||
* Setup service | |||
*/ | |||
@@ -47,28 +60,19 @@ export class NucleusService extends BaseService { | |||
try { | |||
const Nucleus = require('nucleus-nodejs') | |||
// nucleus configuration | |||
const config = { | |||
disableTracking: settings.telemetry.enabled === false, | |||
disableErrorReports: true, | |||
userId: settings.user, | |||
version: process.env.npm_package_version, | |||
persist: true, | |||
} | |||
Nucleus.init(this.appId, config) | |||
Nucleus.init(this.appId, this.config) | |||
Nucleus.appStarted() | |||
this.service = Nucleus | |||
this.enabled = true | |||
await this.fetchData() | |||
setInterval(this.fetchData.bind(this), 15 * 60 * 1000) | |||
this.enabled = true | |||
consola.info('Nucleus enabled!') | |||
consola.debug(`App ID: ${this.appId}`) | |||
consola.debug(this.config) | |||
} catch (err) { | |||
consola.warn('Nucleus setup failed!', err) | |||
} |
@@ -104,6 +104,7 @@ class RollbarService extends BaseService { | |||
consola.info('Rollbar started!') | |||
consola.debug(`Access Token: ${this.accessToken}`) | |||
consola.debug(this.config) | |||
} catch (err) { | |||
consola.warn('Rollbar setup failed!', err) | |||
} |
@@ -33,7 +33,7 @@ export const achievements = { | |||
html: 'You\'re gonna have a bad time.', | |||
toast: true, | |||
position: 'bottom-end', | |||
timer: 6000, | |||
timer: 15000, | |||
timerProgressBar: true, | |||
}) | |||
@@ -83,4 +83,77 @@ export const tutorial = { | |||
localStorage.setItem('tutorial.upload', 'true') | |||
}, | |||
badtime() { | |||
const seen = localStorage.getItem('tutorial.badtime') | |||
if (!isNil(seen)) { | |||
return | |||
} | |||
const intro = introJs() | |||
intro.setOptions({ | |||
showBullets: false, | |||
overlayOpacity: 0.7, | |||
steps: [ | |||
{ | |||
element: '#badtime', | |||
intro: 'You have unlocked the BadTime easter-egg! Use the arrows on your keyboard to play while your photos are nudified in the background.', | |||
}, | |||
], | |||
}) | |||
intro.start() | |||
localStorage.setItem('tutorial.badtime', 'true') | |||
}, | |||
preferences() { | |||
const seen = localStorage.getItem('tutorial.preferences') | |||
if (!isNil(seen)) { | |||
return | |||
} | |||
const intro = introJs() | |||
intro.setOptions({ | |||
showBullets: false, | |||
overlayOpacity: 0.7, | |||
steps: [ | |||
{ | |||
intro: 'Photo preferences are an important part of DreamTime, each photo has its set of preferences with which it works best. Let me give you some information.', | |||
}, | |||
{ | |||
element: '#preferences-runs', | |||
intro: 'In this section you can find the options to execute several transformations in the same photo. The best way to take advantage of them is to increase the number of runs and activate the Randomize or Progressive option so that each run has different preferences and you can save the result that you like best.', | |||
}, | |||
{ | |||
element: '#preferences-body', | |||
intro: 'In this section you can customize the size of the body parts, this depends entirely on your tastes!', | |||
}, | |||
{ | |||
element: '#preferences-advanced-scale', | |||
intro: 'This option can dramatically increase or decrease the quality of the result. If you come from DeepNude, the Manual Crop option will be the one you feel most comfortable with, but we recommend you experiment with the other options and find the ideal one for your photo.', | |||
}, | |||
{ | |||
element: '#preferences-advanced-color', | |||
intro: 'Activating this option will apply an algorithm that could restore the original colors of the photo, it does not always work but it is worth trying.', | |||
}, | |||
{ | |||
intro: 'That\'s all for now, as we said before we recommend you experiment with these preferences, with a little practice you will start creating amazing nudes!', | |||
}, | |||
], | |||
}) | |||
intro.start() | |||
localStorage.setItem('tutorial.preferences', 'true') | |||
}, | |||
} |
@@ -106,6 +106,7 @@ export default { | |||
@apply absolute h-full w-full; | |||
@apply flex items-center justify-center; | |||
@apply px-6 bg-black-80 opacity-0; | |||
backdrop-filter: blur(6px); | |||
} | |||
.header__content { |
@@ -1,6 +1,7 @@ | |||
<template> | |||
<div class="badtime"> | |||
<iframe | |||
id="badtime" | |||
src="https://badtime.dreamnet.tech" | |||
name="badtime" | |||
scrolling="no" | |||
@@ -12,11 +13,12 @@ | |||
</template> | |||
<script> | |||
import { events } from '~/modules' | |||
import { events, tutorial } from '~/modules' | |||
export default { | |||
mounted() { | |||
this.unlock() | |||
tutorial.badtime() | |||
}, | |||
methods: { |
@@ -159,6 +159,6 @@ export default { | |||
} | |||
.nudify__content { | |||
@apply flex-1; | |||
@apply flex-1 overflow-x-auto; | |||
} | |||
</style> |
@@ -19,11 +19,7 @@ | |||
<div class="box__content"> | |||
<p> | |||
This tool allows you to manually crop the photo so that the selected area is resized to 512x512 | |||
</p> | |||
<p> | |||
<font-awesome-icon icon="mouse-pointer" /> Move the photo by dragging it with the mouse, you can zoom in or out using the mouse wheel. | |||
This tool allows you to manually select the area you want to be cropped from the photo and resized. | |||
</p> | |||
</div> | |||
</section> | |||
@@ -31,19 +27,25 @@ | |||
<section class="box"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
<font-awesome-icon icon="question-circle" /> How to obtain better results? | |||
<font-awesome-icon icon="mouse-pointer" /> Commands | |||
</h2> | |||
</div> | |||
<div class="box__content"> | |||
<p> | |||
<ul> | |||
<li>Only one person should appear in the photo.</li> | |||
<li>The person is standing in a straight position without crossing arms or legs.</li> | |||
<li>The person is looking towards the camera.</li> | |||
<li>The person wears light clothes. Bikinis work better.</li> | |||
<li>The person's body is visible and unobstructed.</li> | |||
</ul> | |||
- Increase or decrease the zoom with the mouse wheel. | |||
</p> | |||
<p> | |||
- Click and drag somewhere in the photo to create the crop box. | |||
</p> | |||
<p> | |||
- You can move the crop box by dragging it. | |||
</p> | |||
<p> | |||
- You can increase or decrease the size of the cropbox by dragging any of the anchor points in the corners. | |||
</p> | |||
</div> | |||
</section> | |||
@@ -51,13 +53,13 @@ | |||
<section class="box"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
<font-awesome-icon icon="exclamation-triangle" /> Use at your own risk. | |||
<font-awesome-icon icon="exclamation-triangle" /> Warning. | |||
</h2> | |||
</div> | |||
<div class="box__content"> | |||
<p> | |||
This tool can dramatically decrease the quality of the photo, its use is not recommended. | |||
This tool can dramatically decrease the quality of some photos. (blurry photos) | |||
</p> | |||
</div> | |||
</section> | |||
@@ -66,8 +68,6 @@ | |||
</template> | |||
<script> | |||
import Cropper from 'cropperjs' | |||
export default { | |||
computed: { | |||
photo() { | |||
@@ -87,28 +87,20 @@ export default { | |||
/** | |||
* | |||
*/ | |||
create() { | |||
async create() { | |||
const Cropper = require('cropperjs') | |||
this.photo.cropper = new Cropper(this.$refs.cropCanvas, { | |||
viewMode: 0, | |||
dragMode: 'move', | |||
cropBoxMovable: false, | |||
cropBoxResizable: false, | |||
toggleDragModeOnDblclick: false, | |||
minCropBoxWidth: 512, | |||
minCropBoxHeight: 512, | |||
maxCropBoxWidth: 512, | |||
maxCropBoxHeight: 512, | |||
aspectRatio: 1, | |||
modal: true, | |||
guides: true, | |||
highlight: true, | |||
autoCropArea: 1, | |||
wheelZoomRatio: 0.03, | |||
wheelZoomRatio: 0.05, | |||
}) | |||
this.reload() | |||
}, | |||
/** | |||
* | |||
*/ | |||
async reload() { | |||
await this.photo.syncEditor() | |||
this.cropper.replace(this.photo.fileInput.path) | |||
@@ -122,6 +114,10 @@ export default { | |||
@apply flex h-full; | |||
} | |||
.cropper__crop { | |||
@apply w-3/4 h-full; | |||
} | |||
.cropper__help { | |||
@apply w-1/4 ml-4; | |||
@@ -142,7 +138,5 @@ export default { | |||
} | |||
} | |||
.cropper__crop { | |||
@apply flex-1 h-full; | |||
} | |||
</style> |
@@ -5,8 +5,7 @@ | |||
</template> | |||
<script> | |||
import ImageEditor from 'tui-image-editor' | |||
import { blackTheme } from '~/modules/editor.theme' | |||
export default { | |||
computed: { | |||
@@ -24,6 +23,9 @@ export default { | |||
* | |||
*/ | |||
async create() { | |||
const ImageEditor = require('tui-image-editor') | |||
const { blackTheme } = require('~/modules/editor.theme') | |||
this.photo.editor = new ImageEditor(this.$refs.imageEditor, { | |||
includeUI: { | |||
loadImage: { |
@@ -19,15 +19,37 @@ | |||
<div class="box__content"> | |||
<p> | |||
This tool allows you to select which area of the photo you want to cut, transform and then restore to the original photo. | |||
This tool allows you to manually select the area you want to be cropped, nudified and then restored to the original photo. | |||
</p> | |||
<p> | |||
It is perfect for big photos where you just want to transform a specific area but you don't want to lose everything else. | |||
</p> | |||
</div> | |||
</section> | |||
<section class="box"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
<font-awesome-icon icon="mouse-pointer" /> Commands | |||
</h2> | |||
</div> | |||
<div class="box__content"> | |||
<p> | |||
- Increase or decrease the zoom with the mouse wheel. | |||
</p> | |||
<p> | |||
- Click and drag somewhere in the photo to create the crop box. | |||
</p> | |||
<p> | |||
<font-awesome-icon icon="mouse-pointer" /> Move the photo by dragging it with the mouse, you can zoom in or out using the mouse wheel. | |||
- You can move the crop box by dragging it. | |||
</p> | |||
<p> | |||
- You can increase or decrease the size of the cropbox by dragging any of the anchor points in the corners. | |||
</p> | |||
</div> | |||
</section> | |||
@@ -35,18 +57,13 @@ | |||
<section class="box"> | |||
<div class="box__header"> | |||
<h2 class="title"> | |||
<font-awesome-icon icon="question-circle" /> How to obtain better results? | |||
<font-awesome-icon icon="exclamation-triangle" /> Warning. | |||
</h2> | |||
</div> | |||
<div class="box__content"> | |||
<p> | |||
<ul> | |||
<li>The person is standing in a straight position without crossing arms or legs.</li> | |||
<li>The person is looking towards the camera.</li> | |||
<li>The person wears light clothes. Bikinis work better.</li> | |||
<li>The person's body is visible and unobstructed.</li> | |||
</ul> | |||
This tool can dramatically decrease the quality of some photos. (blurry photos) | |||
</p> | |||
</div> | |||
</section> | |||
@@ -56,7 +73,6 @@ | |||
<script> | |||
import { round } from 'lodash' | |||
import Cropper from 'cropperjs' | |||
export default { | |||
data: () => ({ | |||
@@ -78,6 +94,8 @@ export default { | |||
* | |||
*/ | |||
async create() { | |||
const Cropper = require('cropperjs') | |||
this.$refs.cropCanvas.addEventListener('crop', () => { | |||
const data = this.cropper.getData() | |||
@@ -91,25 +109,16 @@ export default { | |||
this.cropper = new Cropper(this.$refs.cropCanvas, { | |||
viewMode: 1, | |||
dragMode: 'move', | |||
cropBoxMovable: false, | |||
cropBoxResizable: false, | |||
toggleDragModeOnDblclick: false, | |||
minCropBoxWidth: 512, | |||
minCropBoxHeight: 512, | |||
maxCropBoxWidth: 512, | |||
maxCropBoxHeight: 512, | |||
aspectRatio: 1, | |||
modal: true, | |||
guides: true, | |||
highlight: true, | |||
autoCropArea: 1, | |||
wheelZoomRatio: 0.05, | |||
}) | |||
this.reload() | |||
}, | |||
/** | |||
* | |||
*/ | |||
async reload() { | |||
await this.photo.syncEditor() | |||
this.cropper.replace(this.photo.fileInput.path) |
@@ -13,7 +13,7 @@ | |||
Put in Queue | |||
</option> | |||
<option value="go-preferences"> | |||
Put in Pending and open preferences | |||
Put in Pending and Open preferences | |||
</option> | |||
</select> | |||
</box-item> |
@@ -8,25 +8,25 @@ | |||
<div class="box__content"> | |||
<box-item | |||
label="DreamPower" | |||
description="Location of DreamPower (also known as CLI)"> | |||
description="Algorithm location."> | |||
<input v-model="currentValue.folders.cli" readonly class="input" title="Change" @click.prevent="changePower"> | |||
</box-item> | |||
<box-item | |||
label="Models" | |||
description="Location where the transformed photos will be saved."> | |||
description="Location where all nudified photos will be saved."> | |||
<input v-model="currentValue.folders.models" class="input" readonly title="Change" @click.prevent="changeModels"> | |||
</box-item> | |||
<box-item | |||
label="Cropped" | |||
description="Location where the cropped photos will be saved. We recommend selecting a temporary folder."> | |||
description="Location where the cropped and editor photos will be saved before nudifying."> | |||
<input v-model="currentValue.folders.cropped" class="input" readonly title="Change" @click.prevent="changeCropped"> | |||
</box-item> | |||
<box-item | |||
label="Masks" | |||
description="Location where the algorithm masks photos will be saved. We recommend selecting a temporary folder."> | |||
description="Location where the algorithm masks photos will be saved."> | |||
<input v-model="currentValue.folders.masks" class="input" readonly title="Change" @click.prevent="changeMasks"> | |||
</box-item> | |||
</div> |
@@ -5,7 +5,7 @@ | |||
<box-item | |||
v-if="!isMacOS" | |||
label="Device." | |||
description="Device that will be used to transform photos. GPU is faster."> | |||
description="Device that will be used to nudify. GPU is faster."> | |||
<select v-model="currentValue.processing.device" class="input"> | |||
<option value="CPU"> | |||
CPU | |||
@@ -30,7 +30,7 @@ | |||
<box-item | |||
v-if="currentValue.processing.device === 'GPU'" | |||
label="GPU." | |||
description="Graphics card that will be used to transform the photos."> | |||
description="Graphics card used."> | |||
<select v-model="currentValue.processing.gpus[0]" class="input"> | |||
<option v-for="(device, index) in $provider.system.graphics" :key="index" :value="index"> | |||
{{ device.model }} |