Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <div class="box run" :class="previewClass">
  3. <!-- Preview -->
  4. <div class="box__photo run__photo">
  5. <video v-if="file.exists && isVideo"
  6. :src="file.url"
  7. class="run__video__preview"
  8. autoplay
  9. muted
  10. loop
  11. data-private
  12. @click="openPreview" />
  13. <div v-else-if="file.exists"
  14. class="run__photo__preview"
  15. :style="{ backgroundImage: `url('${file.url}')` }"
  16. data-private
  17. @click="openPreview" />
  18. <div v-if="run.algorithmStatus !== ALGORITHM.NONE" class="run__photo__status">
  19. <span v-if="run.algorithmStatus === ALGORITHM.DREAMPOWER" key="dreampower" v-tooltip="'The photo is being nudified by the algorithm.'">
  20. Nudifying
  21. </span>
  22. <span v-if="run.algorithmStatus === ALGORITHM.WAIFU2X" key="waifu2x" v-tooltip="'The photo is being upscaled by Waifu2X.'">Upscaling</span>
  23. <span v-if="run.algorithmStatus === ALGORITHM.DREAMTIME" key="dreamtime" v-tooltip="'The photo is being prepared by DreamTime.'">Other</span>
  24. <span v-if="run.frameStatus" v-tooltip="'Video frame.'"> ({{ run.frameStatus }})</span>
  25. </div>
  26. </div>
  27. <!-- Preferences -->
  28. <div
  29. v-if="run.preferences.body.runs.mode !== false"
  30. class="run__preferences">
  31. <div class="preference">
  32. <span>Boobs</span>
  33. <span>{{ run.preferences.body.boobs.size | fixedValue }}</span>
  34. </div>
  35. <div class="preference">
  36. <span>Areola</span>
  37. <span>{{ run.preferences.body.areola.size | fixedValue }}</span>
  38. </div>
  39. <div class="preference">
  40. <span>Nipple</span>
  41. <span>{{ run.preferences.body.nipple.size | fixedValue }}</span>
  42. </div>
  43. <div class="preference">
  44. <span>Vagina</span>
  45. <span>{{ run.preferences.body.vagina.size | fixedValue }}</span>
  46. </div>
  47. <div class="preference">
  48. <span>Pubic hair</span>
  49. <span>{{ run.preferences.body.pubicHair.size | fixedValue }}</span>
  50. </div>
  51. </div>
  52. <!-- Buttons -->
  53. <div class="box__footer buttons">
  54. <div v-if="run.running" key="button-status" class="button button--sm">
  55. <span class="icon">
  56. <font-awesome-icon icon="running" />
  57. </span>
  58. <span>{{ run.timer.duration }}s</span>
  59. </div>
  60. <div v-else-if="run.failed" key="button-status" class="button button--danger button--sm">
  61. <span class="icon">
  62. <font-awesome-icon icon="exclamation-circle" />
  63. </span>
  64. <span>Error!</span>
  65. </div>
  66. <div v-else-if="run.finished" key="button-status" class="button button--sm">
  67. <span class="icon">
  68. <font-awesome-icon icon="heart" />
  69. </span>
  70. <span>{{ run.timer.duration }}s</span>
  71. </div>
  72. <div v-else key="button-status" class="button button--sm">
  73. <span>
  74. <font-awesome-icon icon="clock" />
  75. </span>
  76. </div>
  77. <button
  78. key="button-terminal"
  79. v-tooltip="'View terminal'"
  80. class="button button--sm"
  81. @click.prevent="$refs.terminalDialog.showModal()">
  82. <font-awesome-icon icon="terminal" />
  83. </button>
  84. <!--
  85. <button
  86. v-if="run.finished && run.outputFile.exists"
  87. v-tooltip="'Open photo'"
  88. class="button button--info button--sm"
  89. @click.prevent="open">
  90. <font-awesome-icon icon="image" />
  91. </button>
  92. -->
  93. <button
  94. v-if="run.finished && run.outputFile.exists"
  95. key="button-save"
  96. class="button button--success button--sm"
  97. @click.prevent="save">
  98. <span class="icon">
  99. <font-awesome-icon icon="save" />
  100. </span>
  101. <span>Save</span>
  102. </button>
  103. <button v-if="run.finished"
  104. key="button-rerun"
  105. class="button button--info button--sm"
  106. @click.prevent="rerun">
  107. <span class="icon">
  108. <font-awesome-icon icon="retweet" />
  109. </span>
  110. <span>Rerun</span>
  111. </button>
  112. <button v-if="run.running"
  113. key="button-stop"
  114. v-tooltip="'Stop'"
  115. class="button button--danger button--sm"
  116. @click.prevent="cancel">
  117. <font-awesome-icon icon="stop" />
  118. </button>
  119. </div>
  120. <!-- Terminal Dialog -->
  121. <dialog ref="terminalDialog">
  122. <div class="dialog__content">
  123. <div class="terminal">
  124. <li
  125. v-for="(item, index) in run.cli.lines"
  126. :key="index"
  127. :class="item.css">
  128. > {{ item.text }}
  129. </li>
  130. </div>
  131. <div class="dialog__buttons">
  132. <button class="button button--danger" @click="$refs.terminalDialog.close()">
  133. Close
  134. </button>
  135. </div>
  136. </div>
  137. </dialog>
  138. </div>
  139. </template>
  140. <script>
  141. import { dreamtrack } from '~/modules/services'
  142. import { Nudify } from '~/modules/nudify'
  143. import { ALGORITHM } from '~/modules/nudify/photo-run'
  144. export default {
  145. filters: {
  146. size(value) {
  147. return Number.parseFloat(value).toFixed(2)
  148. },
  149. fixedValue(value) {
  150. return Number(value).toFixed(2)
  151. },
  152. },
  153. props: {
  154. run: {
  155. type: Object,
  156. required: true,
  157. },
  158. },
  159. data: () => ({
  160. ALGORITHM,
  161. }),
  162. computed: {
  163. isVideo() {
  164. return this.run.photo.file.isVideo
  165. },
  166. file() {
  167. return this.run.outputFile
  168. },
  169. previewStyle() {
  170. if (!this.run.finished) {
  171. return {}
  172. }
  173. const url = encodeURI(this.run.outputFile.path)
  174. return { backgroundImage: `url(${url})` }
  175. },
  176. previewClass() {
  177. return {
  178. 'run--failed': this.run.failed,
  179. 'run--running': this.run.running,
  180. 'run--finished': this.run.finished,
  181. }
  182. },
  183. manualURL() {
  184. return dreamtrack.get(
  185. 'urls.docs.manual',
  186. 'https://time.dreamnet.tech/docs/guide/upload',
  187. )
  188. },
  189. },
  190. methods: {
  191. save() {
  192. this.run.outputFile.save(this.run.outputName)
  193. },
  194. openPreview() {
  195. this.run.outputFile.openItem()
  196. },
  197. rerun() {
  198. this.run.add()
  199. },
  200. cancel() {
  201. this.run.cancel()
  202. },
  203. addMaskToQueue() {
  204. Nudify.add(this.run.maskfinFile, { isMaskfin: true })
  205. },
  206. saveMask() {
  207. this.run.maskfinFile.save(`maskfin-${this.run.outputName}`)
  208. },
  209. },
  210. }
  211. </script>
  212. <style lang="scss" scoped>
  213. .run {
  214. @apply mb-0 relative border border-transparent;
  215. &.run--running {
  216. @apply border-primary;
  217. }
  218. &.run--failed {
  219. @apply border-danger;
  220. }
  221. &:hover {
  222. .run__preferences {
  223. @apply opacity-100;
  224. }
  225. }
  226. }
  227. .run__photo {
  228. background-image: url('~@/assets/images/repeated-square-dark.png');
  229. will-change: transform;
  230. height: 500px;
  231. }
  232. .run__photo__preview {
  233. @apply absolute top-0 bottom-0 left-0 right-0 z-10;
  234. @apply bg-contain bg-no-repeat bg-center;
  235. cursor: zoom-in;
  236. }
  237. .run__photo__status {
  238. @apply absolute z-20;
  239. @apply bg-primary py-2 px-6 rounded-br rounded-tr text-black font-semibold;
  240. left: 0;
  241. top: 20px;
  242. cursor: help;
  243. }
  244. .run__video__preview {
  245. @apply h-full w-full overflow-hidden;
  246. cursor: zoom-in;
  247. }
  248. .run__preferences {
  249. @apply absolute top-0 z-20;
  250. @apply flex opacity-0 bg-menus-default-80 w-full;
  251. backdrop-filter: blur(6px);
  252. transition: opacity 0.1s linear;
  253. height: 80px;
  254. .preference {
  255. @apply flex flex-col flex-1 items-center justify-center;
  256. span {
  257. &:first-child {
  258. @apply text-xs;
  259. }
  260. &:last-child {
  261. @apply text-sm text-white font-bold;
  262. }
  263. }
  264. }
  265. }
  266. .buttons {
  267. @apply justify-end;
  268. .button {
  269. max-width: 100px;
  270. }
  271. }
  272. .terminal {
  273. @apply p-2 bg-black overflow-auto rounded;
  274. height: 400px;
  275. li {
  276. @apply font-mono text-xs text-generic-100 mb-3 block;
  277. &.text-danger {
  278. @apply text-danger-500;
  279. }
  280. }
  281. }
  282. </style>