You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Upload.vue 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <template>
  2. <div id="uploader" class="uploader">
  3. <!-- Uploader Selection -->
  4. <div class="uploader__selection">
  5. <div class="selection__menu">
  6. <select
  7. id="uploader-settings"
  8. v-model="$settings.app.uploadMode"
  9. v-tooltip="{ content: 'Upload mode. What will happen when uploading a photo.', placement: 'right' }"
  10. class="input">
  11. <option value="add-queue">
  12. Put in Queue
  13. </option>
  14. <option value="none">
  15. Put in Pending
  16. </option>
  17. <option value="go-preferences">
  18. Put in Pending and Open preferences
  19. </option>
  20. </select>
  21. <div id="uploader-methods" class="box box--items">
  22. <div class="box__content">
  23. <box-item
  24. label="Instagram"
  25. :icon="['fab', 'instagram']"
  26. :is-link="true"
  27. :class="{'box__item--active': selectionId === 1}"
  28. @click="selectionId = 1" />
  29. <box-item
  30. label="Web"
  31. icon="globe"
  32. :is-link="true"
  33. :class="{'box__item--active': selectionId === 0}"
  34. @click="selectionId = 0" />
  35. <box-item
  36. label="File"
  37. icon="file"
  38. :is-link="true"
  39. :class="{'box__item--active': selectionId === 2}"
  40. @click="selectionId = 2" />
  41. <box-item
  42. label="Folder"
  43. icon="folder-open"
  44. :is-link="true"
  45. :class="{'box__item--active': selectionId === 3}"
  46. @click="selectionId = 3" />
  47. <box-item
  48. label="Examples"
  49. icon="images"
  50. href="https://time.dreamnet.tech/docs/guide/photos" />
  51. </div>
  52. </div>
  53. <div class="box uploader__hint">
  54. <div class="box__content">
  55. <p>
  56. <font-awesome-icon icon="exclamation-circle" />
  57. You can drag and drop photos and folders into the application no matter where you are.
  58. </p>
  59. </div>
  60. </div>
  61. </div>
  62. <div class="selection__content">
  63. <!-- Web Address -->
  64. <div v-show="selectionId === 0" class="selection__content__body">
  65. <input v-model="webAddress" type="url" class="input mb-2" placeholder="https://" data-private="lipsum">
  66. <p class="help">
  67. Enter the web address of a photo that ends in a valid extension. <i>(jpg, png, gif)</i>
  68. </p>
  69. <button class="button" @click="openUrl">
  70. <span class="icon"><font-awesome-icon icon="globe" /></span>
  71. <span>Submit</span>
  72. </button>
  73. </div>
  74. <!-- Instagram -->
  75. <div v-show="selectionId === 1" class="selection__content__body">
  76. <input v-model="instagramPhoto" type="url" class="input mb-2" placeholder="https://www.instagram.com/p/dU4fHDw-Ho/" data-private="lipsum">
  77. <p class="help">
  78. Enter the web address or ID of an Instagram photo.
  79. </p>
  80. <button class="button" @click="openInstagramPhoto">
  81. <span class="icon"><font-awesome-icon :icon="['fab', 'instagram']" /></span>
  82. <span>Submit</span>
  83. </button>
  84. </div>
  85. <!-- File -->
  86. <div v-show="selectionId === 2" class="selection__content__body">
  87. <input
  88. v-show="false"
  89. ref="photo"
  90. type="file"
  91. accept="image/jpeg, image/png, image/gif"
  92. multiple
  93. @change="openFile">
  94. <button class="button" @click.prevent="$refs.photo.click()">
  95. <span>Open File</span>
  96. </button>
  97. <p class="help">
  98. Select one or more photos from your computer.
  99. </p>
  100. </div>
  101. <!-- Folder -->
  102. <div v-show="selectionId === 3" class="selection__content__body">
  103. <button class="button" @click.prevent="openFolder">
  104. <span>Open folder</span>
  105. </button>
  106. <p class="help">
  107. Select a folder from your computer. All valid photos inside will be uploaded.
  108. </p>
  109. </div>
  110. </div>
  111. </div>
  112. </div>
  113. </template>
  114. <script>
  115. import {
  116. isEmpty, startsWith, map, toNumber,
  117. } from 'lodash'
  118. import { Nudify } from '~/modules/nudify'
  119. import { tutorial } from '~/modules'
  120. import { UploadMixin } from '~/mixins'
  121. const { instagram } = $provider
  122. export default {
  123. mixins: [UploadMixin],
  124. props: {
  125. model: {
  126. type: String,
  127. default: undefined,
  128. },
  129. },
  130. data: () => ({
  131. selectionId: 1,
  132. webAddress: '',
  133. instagramPhoto: '',
  134. }),
  135. watch: {
  136. selectionId(value) {
  137. localStorage.uploadSelectionId = value
  138. },
  139. },
  140. created() {
  141. this.selectionId = localStorage.uploadSelectionId || 1
  142. this.selectionId = toNumber(this.selectionId)
  143. },
  144. mounted() {
  145. tutorial.upload()
  146. },
  147. methods: {
  148. /**
  149. *
  150. */
  151. openFile(event) {
  152. const { files } = event.target
  153. if (files.length === 0) {
  154. return
  155. }
  156. const paths = map(files, 'path')
  157. consola.track('UPLOAD_FILE')
  158. this.addFiles(paths)
  159. event.target.value = ''
  160. },
  161. /**
  162. *
  163. */
  164. openUrl() {
  165. if (isEmpty(this.webAddress) || (!startsWith(this.webAddress, 'http://') && !startsWith(this.webAddress, 'https://'))) {
  166. throw new Warning('Upload failed.', 'Please enter a valid web address.')
  167. }
  168. Nudify.addUrl(this.webAddress)
  169. consola.track('UPLOAD_URL')
  170. this.webAddress = ''
  171. },
  172. /**
  173. *
  174. */
  175. async openInstagramPhoto() {
  176. if (isEmpty(this.instagramPhoto)) {
  177. throw new Warning('Upload failed.', 'Please enter a valid Instagram photo.')
  178. }
  179. let post
  180. try {
  181. post = await instagram.getPost(this.instagramPhoto)
  182. } catch (error) {
  183. 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.', error)
  184. }
  185. if (post.isVideo) {
  186. throw new Warning('Upload failed.', 'Videos are not supported yet.')
  187. }
  188. Nudify.addUrl(post.downloadUrl)
  189. consola.track('UPLOAD_INSTAGRAM')
  190. this.instagramPhoto = ''
  191. },
  192. },
  193. }
  194. </script>
  195. <style lang="scss" scoped>
  196. .uploader {
  197. @apply w-full relative;
  198. }
  199. .uploader__selection {
  200. @apply flex;
  201. .selection__menu {
  202. @apply mr-4;
  203. width: 200px;
  204. .input {
  205. @apply mb-6;
  206. }
  207. }
  208. .selection__content {
  209. @apply flex flex-1 items-center justify-center;
  210. .selection__content__body {
  211. @apply text-center;
  212. width: 70%;
  213. }
  214. .input {
  215. @apply mb-4;
  216. }
  217. .help {
  218. @apply text-sm text-generic-700;
  219. &:not(:last-child) {
  220. @apply mb-4;
  221. }
  222. }
  223. .button:not(:last-child) {
  224. @apply mb-4;
  225. }
  226. .button {
  227. }
  228. }
  229. }
  230. .uploader__hint {
  231. @apply text-center;
  232. p {
  233. @apply text-sm;
  234. }
  235. }
  236. </style>