diff options
Diffstat (limited to 'src/client/app/desktop/api')
| -rw-r--r-- | src/client/app/desktop/api/choose-drive-file.ts | 30 | ||||
| -rw-r--r-- | src/client/app/desktop/api/choose-drive-folder.ts | 17 | ||||
| -rw-r--r-- | src/client/app/desktop/api/contextmenu.ts | 16 | ||||
| -rw-r--r-- | src/client/app/desktop/api/dialog.ts | 19 | ||||
| -rw-r--r-- | src/client/app/desktop/api/input.ts | 20 | ||||
| -rw-r--r-- | src/client/app/desktop/api/notify.ts | 10 | ||||
| -rw-r--r-- | src/client/app/desktop/api/post.ts | 21 | ||||
| -rw-r--r-- | src/client/app/desktop/api/update-avatar.ts | 98 | ||||
| -rw-r--r-- | src/client/app/desktop/api/update-banner.ts | 98 |
9 files changed, 329 insertions, 0 deletions
diff --git a/src/client/app/desktop/api/choose-drive-file.ts b/src/client/app/desktop/api/choose-drive-file.ts new file mode 100644 index 0000000000..fbda600e6e --- /dev/null +++ b/src/client/app/desktop/api/choose-drive-file.ts @@ -0,0 +1,30 @@ +import { url } from '../../config'; +import MkChooseFileFromDriveWindow from '../views/components/choose-file-from-drive-window.vue'; + +export default function(opts) { + return new Promise((res, rej) => { + const o = opts || {}; + + if (document.body.clientWidth > 800) { + const w = new MkChooseFileFromDriveWindow({ + propsData: { + title: o.title, + multiple: o.multiple, + initFolder: o.currentFolder + } + }).$mount(); + w.$once('selected', file => { + res(file); + }); + document.body.appendChild(w.$el); + } else { + window['cb'] = file => { + res(file); + }; + + window.open(url + '/selectdrive', + 'choose_drive_window', + 'height=500, width=800'); + } + }); +} diff --git a/src/client/app/desktop/api/choose-drive-folder.ts b/src/client/app/desktop/api/choose-drive-folder.ts new file mode 100644 index 0000000000..9b33a20d9a --- /dev/null +++ b/src/client/app/desktop/api/choose-drive-folder.ts @@ -0,0 +1,17 @@ +import MkChooseFolderFromDriveWindow from '../views/components/choose-folder-from-drive-window.vue'; + +export default function(opts) { + return new Promise((res, rej) => { + const o = opts || {}; + const w = new MkChooseFolderFromDriveWindow({ + propsData: { + title: o.title, + initFolder: o.currentFolder + } + }).$mount(); + w.$once('selected', folder => { + res(folder); + }); + document.body.appendChild(w.$el); + }); +} diff --git a/src/client/app/desktop/api/contextmenu.ts b/src/client/app/desktop/api/contextmenu.ts new file mode 100644 index 0000000000..b70d7122d3 --- /dev/null +++ b/src/client/app/desktop/api/contextmenu.ts @@ -0,0 +1,16 @@ +import Ctx from '../views/components/context-menu.vue'; + +export default function(e, menu, opts?) { + const o = opts || {}; + const vm = new Ctx({ + propsData: { + menu, + x: e.pageX - window.pageXOffset, + y: e.pageY - window.pageYOffset, + } + }).$mount(); + vm.$once('closed', () => { + if (o.closed) o.closed(); + }); + document.body.appendChild(vm.$el); +} diff --git a/src/client/app/desktop/api/dialog.ts b/src/client/app/desktop/api/dialog.ts new file mode 100644 index 0000000000..07935485b0 --- /dev/null +++ b/src/client/app/desktop/api/dialog.ts @@ -0,0 +1,19 @@ +import Dialog from '../views/components/dialog.vue'; + +export default function(opts) { + return new Promise<string>((res, rej) => { + const o = opts || {}; + const d = new Dialog({ + propsData: { + title: o.title, + text: o.text, + modal: o.modal, + buttons: o.actions + } + }).$mount(); + d.$once('clicked', id => { + res(id); + }); + document.body.appendChild(d.$el); + }); +} diff --git a/src/client/app/desktop/api/input.ts b/src/client/app/desktop/api/input.ts new file mode 100644 index 0000000000..ce26a8112f --- /dev/null +++ b/src/client/app/desktop/api/input.ts @@ -0,0 +1,20 @@ +import InputDialog from '../views/components/input-dialog.vue'; + +export default function(opts) { + return new Promise<string>((res, rej) => { + const o = opts || {}; + const d = new InputDialog({ + propsData: { + title: o.title, + placeholder: o.placeholder, + default: o.default, + type: o.type || 'text', + allowEmpty: o.allowEmpty + } + }).$mount(); + d.$once('done', text => { + res(text); + }); + document.body.appendChild(d.$el); + }); +} diff --git a/src/client/app/desktop/api/notify.ts b/src/client/app/desktop/api/notify.ts new file mode 100644 index 0000000000..1f89f40ce6 --- /dev/null +++ b/src/client/app/desktop/api/notify.ts @@ -0,0 +1,10 @@ +import Notification from '../views/components/ui-notification.vue'; + +export default function(message) { + const vm = new Notification({ + propsData: { + message + } + }).$mount(); + document.body.appendChild(vm.$el); +} diff --git a/src/client/app/desktop/api/post.ts b/src/client/app/desktop/api/post.ts new file mode 100644 index 0000000000..cf49615df3 --- /dev/null +++ b/src/client/app/desktop/api/post.ts @@ -0,0 +1,21 @@ +import PostFormWindow from '../views/components/post-form-window.vue'; +import RepostFormWindow from '../views/components/repost-form-window.vue'; + +export default function(opts) { + const o = opts || {}; + if (o.repost) { + const vm = new RepostFormWindow({ + propsData: { + repost: o.repost + } + }).$mount(); + document.body.appendChild(vm.$el); + } else { + const vm = new PostFormWindow({ + propsData: { + reply: o.reply + } + }).$mount(); + document.body.appendChild(vm.$el); + } +} diff --git a/src/client/app/desktop/api/update-avatar.ts b/src/client/app/desktop/api/update-avatar.ts new file mode 100644 index 0000000000..36a2ffe914 --- /dev/null +++ b/src/client/app/desktop/api/update-avatar.ts @@ -0,0 +1,98 @@ +import OS from '../../common/mios'; +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 => { + + const w = new CropWindow({ + propsData: { + image: file, + title: 'アバターとして表示する部分を選択', + aspectRatio: 1 / 1 + } + }).$mount(); + + w.$once('cropped', blob => { + const data = new FormData(); + data.append('i', os.i.account.token); + data.append('file', blob, file.name + '.cropped.png'); + + os.api('drive/folders/find', { + name: 'アイコン' + }).then(iconFolder => { + if (iconFolder.length === 0) { + os.api('drive/folders/create', { + name: 'アイコン' + }).then(iconFolder => { + upload(data, iconFolder); + }); + } else { + upload(data, iconFolder[0]); + } + }); + }); + + w.$once('skipped', () => { + set(file); + }); + + document.body.appendChild(w.$el); + }; + + const upload = (data, folder) => { + const dialog = new ProgressDialog({ + propsData: { + title: '新しいアバターをアップロードしています' + } + }).$mount(); + document.body.appendChild(dialog.$el); + + if (folder) data.append('folderId', folder.id); + + const xhr = new XMLHttpRequest(); + xhr.open('POST', apiUrl + '/drive/files/create', true); + xhr.onload = e => { + const file = JSON.parse((e.target as any).response); + (dialog as any).close(); + set(file); + }; + + 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', { + avatarId: file.id + }).then(i => { + os.i.avatarId = i.avatarId; + os.i.avatarUrl = i.avatarUrl; + + os.apis.dialog({ + title: '%fa:info-circle%アバターを更新しました', + text: '新しいアバターが反映されるまで時間がかかる場合があります。', + actions: [{ + text: 'わかった' + }] + }); + + if (cb) cb(i); + }); + }; + + if (file) { + fileSelected(file); + } else { + os.apis.chooseDriveFile({ + multiple: false, + title: '%fa:image%アバターにする画像を選択' + }).then(file => { + fileSelected(file); + }); + } +}; diff --git a/src/client/app/desktop/api/update-banner.ts b/src/client/app/desktop/api/update-banner.ts new file mode 100644 index 0000000000..e66dbf016b --- /dev/null +++ b/src/client/app/desktop/api/update-banner.ts @@ -0,0 +1,98 @@ +import OS from '../../common/mios'; +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 => { + + const w = new CropWindow({ + propsData: { + image: file, + title: 'バナーとして表示する部分を選択', + aspectRatio: 16 / 9 + } + }).$mount(); + + w.$once('cropped', blob => { + const data = new FormData(); + data.append('i', os.i.account.token); + data.append('file', blob, file.name + '.cropped.png'); + + os.api('drive/folders/find', { + name: 'バナー' + }).then(bannerFolder => { + if (bannerFolder.length === 0) { + os.api('drive/folders/create', { + name: 'バナー' + }).then(iconFolder => { + upload(data, iconFolder); + }); + } else { + upload(data, bannerFolder[0]); + } + }); + }); + + w.$once('skipped', () => { + set(file); + }); + + document.body.appendChild(w.$el); + }; + + const upload = (data, folder) => { + const dialog = new ProgressDialog({ + propsData: { + title: '新しいバナーをアップロードしています' + } + }).$mount(); + document.body.appendChild(dialog.$el); + + if (folder) data.append('folderId', folder.id); + + const xhr = new XMLHttpRequest(); + xhr.open('POST', apiUrl + '/drive/files/create', true); + xhr.onload = e => { + const file = JSON.parse((e.target as any).response); + (dialog as any).close(); + set(file); + }; + + 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', { + bannerId: file.id + }).then(i => { + os.i.bannerId = i.bannerId; + os.i.bannerUrl = i.bannerUrl; + + os.apis.dialog({ + title: '%fa:info-circle%バナーを更新しました', + text: '新しいバナーが反映されるまで時間がかかる場合があります。', + actions: [{ + text: 'わかった' + }] + }); + + if (cb) cb(i); + }); + }; + + if (file) { + fileSelected(file); + } else { + os.apis.chooseDriveFile({ + multiple: false, + title: '%fa:image%バナーにする画像を選択' + }).then(file => { + fileSelected(file); + }); + } +}; |