diff --git a/locales/en-US.yml b/locales/en-US.yml index bc2dbc86f6..c7c24433e0 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -411,6 +411,7 @@ desktop: uploading-avatar: "Uploading a new avatar" avatar-updated: "Successfully updated the avatar" choose-avatar: "Select an image for the avatar" + invalid-filetype: "This filetype is not acceptable here" desktop/views/components/activity.chart.vue: total: "Black ... Total" notes: "Blue ... Notes" diff --git a/package.json b/package.json index c84f01fc51..c68983411e 100644 --- a/package.json +++ b/package.json @@ -158,7 +158,7 @@ "mongodb": "3.1.1", "monk": "6.0.6", "ms": "2.1.1", - "nan": "2.10.0", + "nan": "2.11.0", "nested-property": "0.0.7", "node-sass": "4.9.3", "node-sass-json-importer": "3.3.1", @@ -190,11 +190,11 @@ "single-line-log": "1.1.2", "speakeasy": "2.0.0", "stringz": "1.0.0", - "style-loader": "0.22.1", + "style-loader": "0.23.0", "stylus": "0.54.5", "stylus-loader": "3.0.2", "summaly": "2.1.4", - "systeminformation": "3.43.0", + "systeminformation": "3.44.0", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", "tmp": "0.0.33", @@ -210,9 +210,9 @@ "vue": "2.5.17", "vue-chartjs": "3.4.0", "vue-cropperjs": "2.2.1", - "vue-js-modal": "1.3.19", + "vue-js-modal": "1.3.20", "vue-json-tree-view": "2.1.4", - "vue-loader": "15.4.0", + "vue-loader": "15.4.1", "vue-router": "3.0.1", "vue-style-loader": "4.1.2", "vue-template-compiler": "2.5.17", diff --git a/src/client/app/desktop/api/update-avatar.ts b/src/client/app/desktop/api/update-avatar.ts index 83820f92bd..f07dc623f2 100644 --- a/src/client/app/desktop/api/update-avatar.ts +++ b/src/client/app/desktop/api/update-avatar.ts @@ -3,9 +3,22 @@ import { apiUrl } from '../../config'; import CropWindow from '../views/components/crop-window.vue'; import ProgressDialog from '../views/components/progress-dialog.vue'; -export default (os: OS) => (cb, file = null) => { - const fileSelected = file => { +export default (os: OS) => { + const cropImage = file => new Promise((resolve, reject) => { + + var regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$') + if(!regex.test(file.name) ) { + os.apis.dialog({ + title: '%fa:info-circle% %i18n:desktop.invalid-filetype%', + text: null, + actions: [{ + text: '%i18n:common.got-it%' + }] + }); + reject + } + const w = os.new(CropWindow, { image: file, title: '%i18n:desktop.avatar-crop-title%', @@ -19,27 +32,29 @@ export default (os: OS) => (cb, file = null) => { os.api('drive/folders/find', { name: '%i18n:desktop.avatar%' - }).then(iconFolder => { - if (iconFolder.length === 0) { + }).then(avatarFolder => { + if (avatarFolder.length === 0) { os.api('drive/folders/create', { name: '%i18n:desktop.avatar%' }).then(iconFolder => { - upload(data, iconFolder); + resolve(upload(data, iconFolder)); }); } else { - upload(data, iconFolder[0]); + resolve(upload(data, avatarFolder[0])); } }); }); w.$once('skipped', () => { - set(file); + resolve(file); }); - document.body.appendChild(w.$el); - }; + w.$once('cancelled', reject); - const upload = (data, folder) => { + document.body.appendChild(w.$el); + }); + + const upload = (data, folder) => new Promise((resolve, reject) => { const dialog = os.new(ProgressDialog, { title: '%i18n:desktop.uploading-avatar%' }); @@ -52,18 +67,19 @@ export default (os: OS) => (cb, file = null) => { xhr.onload = e => { const file = JSON.parse((e.target as any).response); (dialog as any).close(); - set(file); + resolve(file); }; + xhr.onerror = reject; xhr.upload.onprogress = e => { if (e.lengthComputable) (dialog as any).update(e.loaded, e.total); }; xhr.send(data); - }; + }); - const set = file => { - os.api('i/update', { + const setAvatar = file => { + return os.api('i/update', { avatarId: file.id }).then(i => { os.store.commit('updateIKeyValue', { @@ -83,18 +99,21 @@ export default (os: OS) => (cb, file = null) => { }] }); - if (cb) cb(i); + return i; }); }; - if (file) { - fileSelected(file); - } else { - os.apis.chooseDriveFile({ - multiple: false, - title: '%fa:image% %i18n:desktop.choose-avatar%' - }).then(file => { - fileSelected(file); - }); - } + return (file = null) => { + const selectedFile = file + ? Promise.resolve(file) + : os.apis.chooseDriveFile({ + multiple: false, + title: '%fa:image% %i18n:desktop.choose-avatar%' + }); + + return selectedFile + .then(cropImage) + .then(setAvatar) + .catch(err => err && console.warn(err)); + }; }; diff --git a/src/client/app/desktop/api/update-banner.ts b/src/client/app/desktop/api/update-banner.ts index 33c4e306a2..5af6ea88d2 100644 --- a/src/client/app/desktop/api/update-banner.ts +++ b/src/client/app/desktop/api/update-banner.ts @@ -6,6 +6,20 @@ import ProgressDialog from '../views/components/progress-dialog.vue'; export default (os: OS) => { const cropImage = file => new Promise((resolve, reject) => { + + var regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$') + + if(!regex.test(file.name) ) { + os.apis.dialog({ + title: '%fa:info-circle% %i18n:desktop.invalid-filetype%', + text: null, + actions: [{ + text: '%i18n:common.got-it%' + }] + }); + reject + } + const w = os.new(CropWindow, { image: file, title: '%i18n:desktop.banner-crop-title%', diff --git a/src/client/app/desktop/views/pages/user/user.friends.vue b/src/client/app/desktop/views/pages/user/user.friends.vue index 49ca7a3f8f..516eea0288 100644 --- a/src/client/app/desktop/views/pages/user/user.friends.vue +++ b/src/client/app/desktop/views/pages/user/user.friends.vue @@ -45,6 +45,7 @@ root(isDark) background isDark ? #282C37 : #fff border solid 1px rgba(#000, 0.075) border-radius 6px + overflow hidden > .title z-index 1 diff --git a/src/client/app/desktop/views/pages/user/user.photos.vue b/src/client/app/desktop/views/pages/user/user.photos.vue index 2318f2b8e4..8397e56484 100644 --- a/src/client/app/desktop/views/pages/user/user.photos.vue +++ b/src/client/app/desktop/views/pages/user/user.photos.vue @@ -44,6 +44,7 @@ root(isDark) background isDark ? #282C37 : #fff border solid 1px rgba(#000, 0.075) border-radius 6px + overflow hidden > .title z-index 1