%fa:heart%%i18n:@title%
-+
{{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }} {{ meta.maintainer.name }} {{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }} diff --git a/src/client/app/config.ts b/src/client/app/config.ts index 74b9ea21c8..a326c521db 100644 --- a/src/client/app/config.ts +++ b/src/client/app/config.ts @@ -4,6 +4,7 @@ declare const _THEME_COLOR_: string; declare const _COPYRIGHT_: string; declare const _VERSION_: string; declare const _CODENAME_: string; +declare const _ENV_: string; const address = new URL(location.href); @@ -18,3 +19,4 @@ export const themeColor = _THEME_COLOR_; export const copyright = _COPYRIGHT_; export const version = _VERSION_; export const codename = _CODENAME_; +export const env = _ENV_; diff --git a/src/client/app/desktop/api/update-avatar.ts b/src/client/app/desktop/api/update-avatar.ts index 83820f92bd..e9d92d1eb1 100644 --- a/src/client/app/desktop/api/update-avatar.ts +++ b/src/client/app/desktop/api/update-avatar.ts @@ -3,8 +3,21 @@ 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) => { + + const 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, @@ -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..e8fa35149b 100644 --- a/src/client/app/desktop/api/update-banner.ts +++ b/src/client/app/desktop/api/update-banner.ts @@ -6,6 +6,19 @@ import ProgressDialog from '../views/components/progress-dialog.vue'; export default (os: OS) => { const cropImage = file => new Promise((resolve, reject) => { + + const 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/components/charts.vue b/src/client/app/desktop/views/components/charts.vue index e400aebbb7..c4e92e429f 100644 --- a/src/client/app/desktop/views/components/charts.vue +++ b/src/client/app/desktop/views/components/charts.vue @@ -88,7 +88,9 @@ export default Vue.extend({ }, created() { - (this as any).api('chart').then(chart => { + (this as any).api('chart', { + limit: 32 + }).then(chart => { this.chart = chart; }); }, @@ -580,6 +582,6 @@ export default Vue.extend({ > div > * display block - height 300px + height 320px diff --git a/src/client/app/desktop/views/components/note-detail.vue b/src/client/app/desktop/views/components/note-detail.vue index 227bcc349d..1ba4a9a447 100644 --- a/src/client/app/desktop/views/components/note-detail.vue +++ b/src/client/app/desktop/views/components/note-detail.vue @@ -47,7 +47,7 @@