Browse Source

- Fixed: Videos don't open preview on click in photos page.

- Fixed: Weird error on startup.
- Fixed: Stop button don't work on custom masks.
- Fixed: Bad design on small screens.
- Added: Processing feedback in custom masks.
- Added: Queue bar forget/play buttons.
- Added: WebM and Instagram videos support.
tags/v1.5.2-early
Ivan Bravo Bravo 1 month ago
parent
commit
85347f0380

.github/workflows/ci.yml → .github/workflows/build.yml View File

@@ -1,4 +1,4 @@
name: CI/CD
name: Build

on:
push:
@@ -12,12 +12,6 @@ on:
tags:
- v*

pull_request:
paths:
- src/**
branches:
- canary

jobs:
build:
name: ${{ matrix.platform }} (${{ matrix.type }})

+ 35
- 0
.github/workflows/lint.yml View File

@@ -0,0 +1,35 @@
name: Lint

on:
pull_request:
paths:
- src/**
branches:
- canary
- master

jobs:
lint:
name: Lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
with:
submodules: true

- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x

- name: Use Yarn
run: npm install -g yarn

- name: Setup
working-directory: src/
run: yarn install

- name: Lint
working-directory: src/
run: yarn run lint

+ 11
- 9
README.md View File

@@ -3,19 +3,19 @@
<img src="assets/dreamtime.png" alt="DreamTime">
</a>
<p align="center" style="font-size: 2.0em;">DreamTime</p>
<h1 align="center">DreamTime</h1>

<p align="center" style="font-size: 1.6em;">
<h2 align="center">
🙈 Use artificial intelligence to create fake nudes.
</p>
</h2>

<p align="center">
Available for Windows, Linux and Mac.
Available for <strong>Windows, Linux and Mac</strong>.
</p>
</div>

<p align="center">
<a href="https://github.com/dreamnettech/dreamtime/actions"><img src="https://github.com/dreamnettech/dreamtime/workflows/CI/CD/badge.svg" /></a>
<a href="https://github.com/dreamnettech/dreamtime/actions"><img src="https://github.com/dreamnettech/dreamtime/workflows/Build/badge.svg" /></a>
<a href="https://github.com/dreamnettech/dreamtime/releases"><img src="https://img.shields.io/github/downloads/dreamnettech/dreamtime/total?logo=github&logoColor=white" /></a>
<a target="_blank" href="https://www.codacy.com/app/kolessios/dreamtime?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=dreamnettech/dreamtime&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/0ecb8ba6eeae42e7bfd0d414d1bacee1" /></a>
<a target="_blank" href="https://codeclimate.com/github/private-dreamnet/dreamtime/maintainability"><img src="https://api.codeclimate.com/v1/badges/8d325515768f221e235f/maintainability" /></a>
@@ -39,20 +39,22 @@ Visit the [Getting Started](https://time.dreamnet.tech/docs/development/getting-
## Community

- [Chat](https://chat.dreamnet.tech)
- [Forum](https://forum.dreamnet.tech)
- [Twitter](https://twitter.com/DreamNetTechno)
- [Facebook](https://web.facebook.com/DreamNetTechnology)

## Supporting DreamTime
## Supporting

DreamTime is an open-source project that will be **free forever**. The project is kept in development thanks to the support of our incredible backers.

These are the ways you can support us:

- [Patreon](https://patreon.com/dreamnet)
- [Ko-fi](https://ko-fi.com/dreamnet)
- 🌟 [Patreon](https://patreon.com/dreamnet)
- 🌟 [Buy Me A Coffe](https://www.buymeacoffee.com/dreamnettech)
- [Liberapay](https://liberapay.com/dreamnet)
- [Crypto](https://commerce.coinbase.com/checkout/24a8bcb6-22db-4166-9bea-fb24fe78f1cd)

🌟 = Get rewards like early access to the latest versions.

## Sponsors

🥰 Support this project by becoming a sponsor. Your logo will show up here and in the about section of our apps, with a link to your website.

+ 31
- 0
src/app/router.scrollBehavior.js View File

@@ -0,0 +1,31 @@
export default async function (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
}

const findEl = async (hash, x = 0) => (
document.querySelector(hash)
// eslint-disable-next-line consistent-return
|| new Promise((resolve) => {
if (x > 50) {
return resolve(document.querySelector('#app'))
}
setTimeout(() => {
resolve(findEl(hash, x += 1 || 1))
}, 100)
})
)

if (to.hash) {
const container = document.getElementById('layout-content')
const el = await findEl(to.hash)

if ('scrollBehavior' in document.documentElement.style) {
return container.scrollTo({ top: el.offsetTop, behavior: 'smooth' })
}

return container.scrollTo(0, el.offsetTop)
}

return { x: 0, y: 0 }
}

BIN
src/assets/images/curls.png View File


BIN
src/assets/images/d1hpv9d-e1c2c577-d272-41b0-bd73-a89209108efd.jpg View File


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


BIN
src/assets/images/etc/MvlZgXx.jpg View File


BIN
src/assets/images/ouch/blogging.png View File


BIN
src/assets/images/papyrus-dark.webp View File


+ 5
- 2
src/components/Help/HelpLesson.vue View File

@@ -124,10 +124,13 @@ export default {
}
}

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

/* purgecss end ignore */
.box__footer {
.button {
@apply mr-2;
}
}
</style>

+ 34
- 3
src/components/Nudify/NudifyMaskPhoto.vue View File

@@ -49,12 +49,28 @@
<button v-if="mask.canShowSave"
key="save"
v-tooltip="'Save mask.'"
class="button button--sm button--info"
class="button button--sm"
@click="mask.save()">
<FontAwesomeIcon icon="save" />
</button>

<button v-if="mask.canShowGenerate"
<button v-if="mask.canShowGenerate && mask.photo.running"
key="stop"
v-tooltip="'Stop Generation.'"
class="button button--danger button--sm"
@click="stop()">
<FontAwesomeIcon icon="stop" />
</button>

<button v-else-if="mask.canShowGenerate && mask.canShowSave"
key="rerun"
v-tooltip="'Rerun.'"
class="button button--info button--sm"
@click="generate()">
<FontAwesomeIcon icon="retweet" />
</button>

<button v-else-if="mask.canShowGenerate && !mask.photo.running"
key="play"
v-tooltip="'Generate.'"
class="button button--success button--sm"
@@ -91,6 +107,9 @@ export default {
maskClass() {
return {
'mask--dragging': this.isDragging,
'mask--failed': this.mask.run?.failed,
'mask--running': this.mask.run?.running,
'mask--finished': this.mask.run?.finished,
}
},
},
@@ -130,6 +149,10 @@ export default {
this.mask.photo.generateMask(this.mask.id)
},

stop() {
this.mask.photo.cancel()
},

openPreview() {
this.mask.file.openItem()
},
@@ -165,13 +188,21 @@ export default {

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

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

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

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

.mask__dropzone {

+ 0
- 110
src/components/Nudify/NudifyPhotoRun.vue View File

@@ -306,113 +306,3 @@ export default {
}
}
</style>

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

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

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

&.run--finished {
.run__preview {
@apply opacity-100;
}
}

&:hover {
@apply border-primary-300;

.run__content,
.run__preferences {
@apply opacity-100;
}
}

.run__preview {
@apply absolute opacity-0 left-0 right-0 top-0 bottom-0 z-10;
@apply bg-contain bg-center bg-no-repeat;
transition: opacity 0.3s linear;
}
}

.run__content,
.run__preferences {
@apply absolute z-20;
@apply flex opacity-0 bg-dark-800-80 w-full;
backdrop-filter: blur(6px);
transition: opacity 0.1s linear;
}

.run__content {
@apply bottom-0;
height: 100px;

.content__item {
@apply flex-1 flex justify-center items-center;

&:not(:first-child) {
@apply mr-2;
}

.button {
@apply w-full;
}

p {
@apply font-bold text-center;

span {
@apply block;
}
}
}
}

.dialog__maskfin {
a {
@apply text-primary-500 underline;
}

.maskfin__preview {
@apply mb-4 flex justify-center items-center;

img {
max-height: 350px;
}
}

.maskfin__description {
@apply mb-4 text-sm;

p {
@apply mb-2;
}
}
}

.section__preferences {
p {
@apply text-sm;

.preference__name {
@apply inline-block text-generic-300;
width: 150px;
}

.preference__value {
@apply inline-block font-bold text-generic-100;
}
}
}
*/
</style>

+ 10
- 1
src/components/Photo.vue View File

@@ -2,10 +2,12 @@
<div class="box photo">
<div class="box__photo">
<video v-if="file.isVideo"
class="photo__video"
:src="file.url"
autoplay
muted
loop />
loop
@click="openPreview" />

<div v-else
class="photo__preview"
@@ -34,6 +36,8 @@ export default {

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

&::v-deep {
.box__photo {
background-image: url('~@/assets/images/repeated-square-dark.png');
@@ -48,4 +52,9 @@ export default {
@apply bg-contain bg-no-repeat bg-center;
cursor: zoom-in;
}

.photo__video {
@apply h-full w-full overflow-hidden;
cursor: zoom-in;
}
</style>

+ 58
- 2
src/components/Queue/QueueMenu.vue View File

@@ -8,6 +8,22 @@
<span class="separator">·</span>
<span>{{ $nudify.waiting.length }}</span>
</p>

<div v-show="$nudify.waiting.length > 0" class="queue__section__actions">
<button
v-tooltip="{placement: 'bottom', content: 'Forget waiting'}"
class="button button--danger button--xs"
@click.prevent="$nudify.forgetAll('waiting')">
<font-awesome-icon icon="trash-alt" />
</button>

<button
v-tooltip="{placement: 'bottom', content: 'Cancel waiting' }"
class="button button--xs"
@click.prevent="$nudify.cancelAll('waiting')">
<font-awesome-icon icon="stop" />
</button>
</div>
</div>

<div class="queue__content">
@@ -26,6 +42,22 @@
<span class="separator">·</span>
<span>{{ $nudify.pending.length }}</span>
</p>

<div v-show="$nudify.pending.length > 0" class="queue__section__actions">
<button
v-tooltip="'Forget all'"
class="button button--danger button--xs"
@click.prevent="$nudify.forgetAll()">
<font-awesome-icon icon="trash-alt" />
</button>

<button
v-tooltip="'Start all'"
class="button button--success button--xs"
@click.prevent="$nudify.addAll()">
<font-awesome-icon icon="play" />
</button>
</div>
</div>

<div class="queue__content">
@@ -45,6 +77,22 @@
<span class="separator">·</span>
<span>{{ $nudify.finished.length }}</span>
</p>

<div v-show="$nudify.finished.length > 0" class="queue_section__actions">
<button
v-tooltip="'Forget all'"
class="button button--danger button--xs"
@click.prevent="$nudify.forgetAll('finished')">
<font-awesome-icon icon="trash-alt" />
</button>

<button
v-tooltip="'Rerun all'"
class="button button--info button--xs"
@click.prevent="$nudify.addAll('finished')">
<font-awesome-icon icon="undo" />
</button>
</div>
</div>

<div class="queue__content">
@@ -84,10 +132,10 @@ export default {
}

.queue__header {
@apply p-3;
@apply flex items-center p-3;

.title {
@apply text-sm font-bold;
@apply flex-1 text-sm font-bold;
}

.icon {
@@ -99,6 +147,14 @@ export default {
}
}

.queue__section__actions {
@apply flex justify-end ml-2 z-10;

.button {
@apply ml-2;
}
}

.queue__content {
@apply flex-1;
@apply flex flex-wrap;

+ 1
- 1
src/components/Queue/QueuePhoto.vue View File

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

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

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

@@ -5,7 +5,7 @@
<HelpLesson v-if="isLesson"
:lesson="lesson"
:small="true"
@click="$router.push('/help')" />
@click="$router.push({ path: '/help', hash: lesson.photo })" />
</div>
</template>


+ 2
- 1
src/electron/src/modules/settings.js View File

@@ -462,12 +462,13 @@ class Settings {
mode: 2,
},
})

// This throws on some Windows 10 systems.
try {
delete this.payload.advanced.useWaifu
delete this.payload.folders.masks
} catch (err) {
console.warn(err)
logger.warn(err)
}
}


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

@@ -32,10 +32,12 @@ export function exec(args, options = {}) {
})

// FIXME: Anaconda support.
/* return spawn('C:\\Users\\koles\\Anaconda3\\envs\\dreampower\\python', args, {
/*
return spawn('C:\\Users\\koles\\Anaconda3\\envs\\dreampower\\python', args, {
cwd: getPowerPath(),
...options,
}) */
})
*/

return spawn('python', args, {
cwd: getPowerPath(),
@@ -66,13 +68,13 @@ export async function nudify(args, events) {
})

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

process.stderr.on('data', (output) => {
logger.warn(output.toString())
// logger.warn(output.toString())
events.emit('stderr', null, output)
})


+ 16
- 14
src/modules/config/help.yml View File

@@ -2,7 +2,7 @@
photo: drag
buttons:
- text: Online Guide
href: https://time.dreamnet.tech/docs/guide
href: https://time.dreamnet.tech/docs/guide/upload
summary: |-
No matter where you are, you can always drag and drop your photos and folders.
content: |-
@@ -28,9 +28,9 @@
- text: Go to settings
href: /settings
summary: |-
Customize the behavior of DreamTime to your liking and make it a professional application to create fake nudes.
Customize the behavior of DreamTime and make it a professional application to create fake nudes.
content: |-
Customize the behavior of DreamTime to your liking and make it a professional application to create fake nudes.
Customize the behavior of DreamTime and make it a professional application to create fake nudes.

- Optimize application and algorithm performance.
- Change the behavior of the photo upload or the location of the queue bar.
@@ -61,7 +61,7 @@
summary: |-
Is your photo not giving good results? Changing and experimenting with the photo preferences can help a lot.
content: |-
Is your photo not giving good results? Changing and experimenting with the photo preferences can help a lot, these are the most important options:
Is your photo not giving good results? Changing and experimenting with the photo preferences can help a lot:

- **Scale method:** The `Crop` and `Overlay` options usually give the best results but each photo is unique and other options can help more.
- **Crop position:** If you are using `Crop`, `Overlay` or `Color Padding` the position of the crop tool can be the key to a good result, even moving it a few pixels can make a difference.
@@ -73,24 +73,26 @@
- text: Go to settings
href: /settings
summary: |-
Do you think there are too many preferences? Or few? Change the preferences mode!
Too many options? Or few? Adapt it to your style.
content: |-
Preferences mode allows you to increase or decrease the number of options depending on your mood or experience using the application.
Preferences mode allows you to increase or decrease the number of options depending on your style or experience using the application.

- **Minimal:** Only options for body personalization. Everything will be adjusted to make the process as automatic as possible.
- **Simple:** Allows you to change the scale mode.
- **Minimal:** Only options for body personalization. Everything will be adjusted to make the process totally automatic.
- **Simple:** Same as Minimal. Allows you to change the Scale mode.
- **Normal:** All options available, this is the original DreamTime experience.
- **Advanced:** The results interface changes to work with custom masks, this mode requires time and experience doing manual editing but can provide better results.
- **Advanced:** Mode to work with Custom masks. The results interface changes to show each mask, this mode requires time and experience making manual modifications to the photos but can improve the results dramatically.

- title: Tips? Ads? You decide.
photo: tips-ads
buttons:
- text: Go to settings
href: /settings
- text: Report ad
href: https://time.dreamnet.tech/docs/support/feedback#others
summary: |-
Now you can find help tips and advertising in this space. You can enable or disable this behavior in the settings.
Now you can find help tips and ads in this space. You can enable or disable this behavior in the settings.
content: |-
In this version of DreamTime you can find help tips and/or ads in the bottom right part of the application.
In this version of DreamTime you can find help tips and/or ads in the bottom part of the menu.

You can enable or disable this behavior in the settings.

@@ -99,8 +101,8 @@
- title: Create nudes of videos!
photo: videos
summary: |-
Don't just stay with static photos, you can also nudify gifs and mp4 videos!
Don't just stay with static photos, you can also nudify gifs, webm and mp4 videos!
content: |-
With DreamTime you can nudify gifs and mp4 videos, from the Internet or by uploading the files to the application.
With DreamTime you can nudify gifs, webm and mp4 videos, from the Internet or by uploading the files to the application.

Keep in mind that this process can consume more resources from your system!
**Be sure to use short videos, otherwise prepare to meet the RAM eating beast.**

+ 7
- 7
src/modules/config/settings.yml View File

@@ -117,16 +117,16 @@

- id: preferences.advanced.scaleMode
label: Scale method.
description: Indicates how the photo will be scaled.
description: Indicates how the photo will be scaled to 512x512.
input: select
options:
- label: None
value: none
- label: "Automatic: Fixed"
- label: "Automatic Resize"
value: auto-rescale
- label: "Automatic: Padding"
- label: "Automatic Padding"
value: auto-resize
- label: "Automatic: Crop"
- label: "Automatic Crop"
value: auto-resize-crop
- label: Overlay
value: overlay
@@ -137,11 +137,11 @@
animated-options:
- label: None
value: none
- label: "Automatic: Fixed"
- label: "Automatic Resize"
value: auto-rescale
- label: "Automatic: Padding"
- label: "Automatic Padding"
value: auto-resize
- label: "Automatic: Crop"
- label: "Automatic Crop"
value: auto-resize-crop

- id: preferences.body.executions

+ 9
- 2
src/modules/file.js View File

@@ -109,7 +109,7 @@ export class File extends EventEmitter {
* @readonly
*/
get isAnimated() {
return this.mimetype === 'image/gif' || this.mimetype === 'video/mp4'
return this.mimetype === 'image/gif' || this.mimetype === 'video/mp4' || this.mimetype === 'video/webm'
}

/**
@@ -118,7 +118,7 @@ export class File extends EventEmitter {
* @readonly
*/
get isVideo() {
return this.mimetype === 'video/mp4'
return this.mimetype === 'video/mp4' || this.mimetype === 'video/webm'
}

/**
@@ -292,6 +292,7 @@ export class File extends EventEmitter {
'image/png',
'image/gif',
'video/mp4',
'video/webm',
]

if (!validMimeTypes.includes(mimetype)) {
@@ -406,6 +407,12 @@ export class File extends EventEmitter {
]
}

if (this.mimetype === 'video/webm') {
filters = [
{ name: 'WEBM', extensions: ['webm'] },
]
}

const savePath = dialog.showSaveDialogSync({
defaultPath,
filters,

+ 19
- 0
src/modules/imagemagick.js View File

@@ -84,6 +84,14 @@ export class ImageMagick {
return this
}

async blur(radius, sigma) {
await this.init()

this.image.blur(radius, sigma)

return this
}

/**
*
*
@@ -114,4 +122,15 @@ export class ImageMagick {
}, MagickFormat.Png)
})
}

async getDataURL() {
await this.init()

return new Promise((resolve) => {
this.image.write((data) => {
const b64encoded = Buffer.from(data).toString('base64')
resolve(b64encoded)
}, MagickFormat.Png)
})
}
}

+ 10
- 5
src/modules/nudify/photo-mask.js View File

@@ -30,6 +30,11 @@ export class PhotoMask {
*/
photo

/**
* @type {import('./photo-run').PhotoRun}
*/
run

/**
* @type {import('../file').File}
*/
@@ -164,7 +169,7 @@ export class PhotoMask {
return 'Corrected'

case STEP.MASK:
return 'Mask'
return 'Maskcloth'

case STEP.MASKREF:
return 'Maskref'
@@ -195,19 +200,19 @@ export class PhotoMask {
get description() {
switch (this.id) {
case STEP.CORRECT:
return '[OPENCV] Color correction to make it easier for the algorithm to understand.<br><br><strong>NOTE:</strong> Editor changes and scaling are applied here.'
return '[OPENCV] The algorithm applies color correction to the photo to understand it more easily.<br><br><strong>NOTE:</strong> Scale and editor changes are applied here.'

case STEP.MASK:
return '[GAN] The algorithm recognizes and marks the clothes to be removed.'

case STEP.MASKREF:
return '[OPENCV] Corrections to the mask.'
return '[OPENCV] Correction of errors in the Maskcloth.'

case STEP.MASKDET:
return '[GAN] The algorithm recognizes and marks the ideal position and size of the body parts.<br><br><strong>This is the most important mask.</strong>'
return '[GAN] The algorithm recognizes and marks the ideal position and size of the body parts.<br><br><strong>This is the most important mask!</strong>'

case STEP.MASKFIN:
return '[OPENCV] Corrections, problem solving and body preferences are applied.<br><br><strong>NOTE:</strong> This mask needs a valid Maskref and Maskdet to generate.'
return '[OPENCV] Correction of errors and scale of the body parts according to the preferences.<br><br><strong>NOTE:</strong> This mask needs a valid Maskref and Maskdet to generate.'

case STEP.NUDE:
return '[GAN] The algorithm generates the fake nude.'

+ 9
- 4
src/modules/nudify/photo-run.js View File

@@ -50,6 +50,7 @@ export class PhotoRun {

/**
* Mask that will be generated with this run.
* @type {import('./photo-mask').PhotoMask}
*/
mask

@@ -121,15 +122,19 @@ export class PhotoRun {

let ext = 'png'

if (file.extension === 'gif') {
ext = 'gif'
} else if (file.extension === 'mp4') {
ext = 'mp4'
if (file.isAnimated) {
ext = file.extension
}

return `${name}-RUN${this.id}-${now}-dreamtime.${ext}`
}

/**
* Creates an instance of PhotoRun.
* @param {string} id
* @param {import('./photo').Photo} photo
* @param {string} mask
*/
constructor(id, photo, mask) {
this.id = id
this.photo = photo

+ 9
- 1
src/modules/nudify/photo.js View File

@@ -840,7 +840,13 @@ export class Photo {
* Cancel the photo runs and remove it from the queue.
*/
cancel() {
NudifyQueue.cancel(this)
if (this.withCustomMasks) {
// When working with custom masks the photo is not part of the queue
// Why? Because that's extra work :(
this.stop()
} else {
NudifyQueue.cancel(this)
}
}

/**
@@ -905,6 +911,8 @@ export class Photo {

const run = new PhotoRun(1, this, mask)

this.masks[mask].run = run

this.runs.push(run)
this.queue.add(run)


+ 1
- 1
src/modules/projects/checkpoints.js View File

@@ -12,7 +12,7 @@ class Checkpoints {
},
about: {
title: 'Checkpoints',
description: 'DeepNude data models.',
description: 'DeepNude trained models.',
logo: 'https://link.dreamnet.tech/ipfs/QmWkpwjEq6YQLSud4pS8ChkdED4NZrup6fKirFXXXLFe9u?filename=deepnude.png',
navigation: [],
},

+ 3
- 4
src/package.json View File

@@ -9,7 +9,7 @@
"license": "GPL-3.0-only",
"scripts": {
"postinstall": "patch-package",
"lint": "eslint --fix --ext .js,.vue --ignore-path .gitignore .",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"test": "env-cmd -e default,test mocha",
"clean": "shx rm -rf .nuxt/ dist/ electron/dist/",
"optimize": "modclean --patterns default:safe --run",
@@ -22,9 +22,8 @@
"build:nuxt": "yarn production nuxt build && yarn production nuxt export",
"build:babel": "yarn production babel electron/src --out-dir electron/dist --minified",
"build:electron": "yarn production electron-builder --publish=never --x64",
"build:pre": "yarn run clean && yarn run build:nuxt && yarn run build:babel",
"build:post": "yarn run optimize && yarn run build:electron",
"build": "yarn run build:pre && yarn run build:post",
"build:dev": "yarn run clean && yarn run build:nuxt && yarn run build:babel && yarn run build:electron",
"build": "yarn run clean && yarn run build:nuxt && yarn run build:babel && yarn run optimize && yarn run build:electron",
"preview:electron": "env-cmd -e default,production,preview --no-override electron .",
"preview:production": "yarn build:nuxt && yarn build:babel && yarn preview:electron"
},

+ 7
- 6
src/pages/help.vue View File

@@ -12,11 +12,8 @@
</PageHeader>

<div class="help__content">
<div v-for="(lesson, index) in help.lessons"
:key="index"
class="column">
<HelpLesson
:lesson="lesson" />
<div v-for="(lesson, index) in help.lessons" :id="lesson.photo" :key="index">
<HelpLesson :lesson="lesson" />
</div>
</div>
</div>
@@ -34,7 +31,11 @@ export default {

<style lang="scss" scoped>
.help__content {
@apply flex flex-wrap;
@apply grid grid-cols-2 gap-6;

@screen sm {
@apply grid-cols-1;
}

.column {
@apply w-1/2 px-3 mb-6;

+ 7
- 13
src/pages/index.vue View File

@@ -73,8 +73,8 @@
</h2>

<h3 class="subtitle">
Upload photos from the web.
<span v-tooltip="'Only web addresses that end in: jpg, png, gif or mp4.'" class="help">
Upload photos and videos from the web.
<span v-tooltip="'Only web addresses that end in: jpg, png, gif, webm or mp4.'" class="help">
<font-awesome-icon icon="info-circle" />
</span>
</h3>
@@ -102,7 +102,7 @@
</h2>

<h3 class="subtitle">
Upload photos from any public Instagram profile.
Upload photos and videos from any public Instagram profile.
</h3>
</PageHeader>

@@ -121,8 +121,7 @@
</div>

<!-- File -->
<div v-show="selectionId === 2"
class="methods__content">
<div v-show="selectionId === 2" class="methods__content">
<PageHeader>
<h2 class="title">
<span class="icon"><font-awesome-icon icon="file" /></span>
@@ -138,7 +137,7 @@
v-show="false"
ref="photo"
type="file"
accept="image/jpeg, image/png, image/gif, video/mp4"
accept="image/jpeg, image/png, image/gif, video/mp4, video/webm"
multiple
@change="openFile">

@@ -151,8 +150,7 @@
</div>

<!-- Folder -->
<div v-show="selectionId === 3"
class="methods__content">
<div v-show="selectionId === 3" class="methods__content">
<PageHeader>
<h2 class="title">
<span class="icon"><font-awesome-icon icon="folder" /></span>
@@ -160,7 +158,7 @@
</h2>

<h3 class="subtitle">
Upload all valid photos from a folder on your computer.
Upload all valid photos and videos from a folder on your computer.
</h3>
</PageHeader>

@@ -276,10 +274,6 @@ export default {
)
}

if (post.isVideo) {
throw new Warning('Upload failed.', 'Videos are not supported yet.')
}

Nudify.addUrl(post.downloadUrl)

consola.track('UPLOAD_INSTAGRAM')

+ 1
- 1
src/pages/nudify/_id/padding.vue View File

@@ -117,7 +117,7 @@ export default {
.cropper-view-box,
.cropper-face {
@apply bg-black bg-no-repeat opacity-100;
background-image: var(--photo-image, url('~assets/images/d1hpv9d-e1c2c577-d272-41b0-bd73-a89209108efd.jpg'));
background-image: var(--photo-image, url('~assets/images/etc/MvlZgXx.jpg'));
background-size: 100% 100%;
}
}

+ 7
- 3
src/pages/nudify/_id/results.vue View File

@@ -131,16 +131,20 @@ export default {
}

.results__masks {
@apply grid grid-cols-6 gap-6;
@apply grid grid-cols-3 gap-6;

.mask {
@apply col-span-2;
@screen sm {
@apply grid-cols-2;
}
}

.results__runs {
@apply grid grid-cols-2 gap-6;

@screen sm {
@apply grid-cols-1;
}

.run {
@media (min-height: 1280px) {
height: 1024px;

+ 8
- 0
src/pages/photos.vue View File

@@ -61,5 +61,13 @@ export default {

.photos__content {
@apply grid grid-cols-4 gap-6;

@screen md {
@apply grid-cols-3;
}

@screen sm {
@apply grid-cols-2;
}
}
</style>

+ 7
- 0
src/tailwind.config.js View File

@@ -27,6 +27,13 @@ module.exports = {
64: '16rem',
},

screens: {
xl: { max: '2000px' },
lg: { max: '1800px' },
md: { max: '1600px' },
sm: { max: '1400px' },
},

extend: {
fontFamily: {
sans: [

Loading…
Cancel
Save