From fd15ce9ed7f6f823d3c639aac4181758f5822e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 03:22:37 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=E3=83=9F=E3=83=89=E3=83=AB=E3=82=A6?= =?UTF-8?q?=E3=82=A7=E3=82=A2=E3=82=92axios=E3=81=AE=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=81=A3=E3=81=A6=E5=AE=9F=E7=8F=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/axios.js | 15 ++ src/bin/client.js | 403 ++++++++++++++-------------------------------- 2 files changed, 132 insertions(+), 286 deletions(-) diff --git a/src/bin/axios.js b/src/bin/axios.js index 208d8ff5..f5e4b36e 100644 --- a/src/bin/axios.js +++ b/src/bin/axios.js @@ -1,3 +1,18 @@ import axios from 'axios' +axios.interceptors.response.use( + res => { + if (process.env.NODE_ENV === 'development' || window.debug) { + console.info((res.config.method || '').toUpperCase(), res.config.url, res) + } + return res + }, + err => { + if (process.env.NODE_ENV === 'development' || window.debug) { + console.info((err.config.method || '').toUpperCase(), err.config.url, err) + } + return err + } +) + export default axios diff --git a/src/bin/client.js b/src/bin/client.js index 6e90c41d..11d20638 100644 --- a/src/bin/client.js +++ b/src/bin/client.js @@ -1,265 +1,168 @@ import axios from '@/bin/axios' -const middleWare = - process.env.NODE_ENV === 'development' || window.debug - ? (name, fn) => { - return fn() - .then(res => { - console.info(name, res) - return Promise.resolve(res) - }) - .catch(err => { - console.error(name, err) - return Promise.reject(err) - }) - } - : (name, fn) => { - return fn().catch(err => { - console.error(name, err) - return Promise.reject(err) - }) - } const client = { // Tag: authorization login(name, pass) { - return middleWare('login', () => { - return axios.post(`/api/1.0/login`, { name, pass }) - }) + return axios.post(`/api/1.0/login`, { name, pass }) }, logout() { - return middleWare('logout', () => { - return axios.post(`/api/1.0/logout`) - }) + return axios.post(`/api/1.0/logout`) }, // Tag: Session getSessions() { - return middleWare('getSessions', () => { - return axios.get('/api/1.0/users/me/sessions') - }) + return axios.get('/api/1.0/users/me/sessions') }, deleteSessions() { - return middleWare('deleteSessions', () => { - return axios.delete('/api/1.0/users/me/sessions') - }) + return axios.delete('/api/1.0/users/me/sessions') }, deleteSession(sessionId) { - return middleWare('deleteSession', () => { - return axios.delete(`/api/1.0/users/me/sessions/${sessionId}`) - }) + return axios.delete(`/api/1.0/users/me/sessions/${sessionId}`) }, // Tag: channel makeChannel(type, member, name, parent) { - return middleWare('makeChannel', () => { - return axios.post(`/api/1.0/channels`, { type, member, name, parent }) - }) + return axios.post(`/api/1.0/channels`, { type, member, name, parent }) }, getChannels() { - return middleWare('getChannels', () => { - return axios.get(`/api/1.0/channels`) - }) + return axios.get(`/api/1.0/channels`) }, getChannelInfo(channelId) { - return middleWare('getChannelInfo', () => { - return axios.get(`/api/1.0/channels/${channelId}`) - }) + return axios.get(`/api/1.0/channels/${channelId}`) }, changeChannelInfo(channelId, name, visibility, force) { - return middleWare('changeChannelName', () => { - return axios.patch(`/api/1.0/channels/${channelId}`, { - name, - visibility, - force - }) + return axios.patch(`/api/1.0/channels/${channelId}`, { + name, + visibility, + force }) }, changeChannelParent(channelId, parent) { - return middleWare('changeChannelParent', () => { - return axios.put(`/api/1.0/channels/${channelId}/parent`, { parent }) - }) + return axios.put(`/api/1.0/channels/${channelId}/parent`, { parent }) }, deleteChannel(channelId) { - return middleWare('changeChannelName', () => { - return axios.delete(`/api/1.0/channels/${channelId}`) - }) + return axios.delete(`/api/1.0/channels/${channelId}`) }, // Tag: topic getChannelTopic(channelId) { - return middleWare('getChannelTopic', () => { - return axios.get(`/api/1.0/channels/${channelId}/topic`) - }) + return axios.get(`/api/1.0/channels/${channelId}/topic`) }, changeChannelTopic(channelId, text) { - return middleWare('changeChannelTopic', () => { - return axios.put(`/api/1.0/channels/${channelId}/topic`, { text }) - }) + return axios.put(`/api/1.0/channels/${channelId}/topic`, { text }) }, // Tag: message loadMessages(channelId, limit, offset) { - return middleWare('loadMessages', () => { - return axios.get(`/api/1.0/channels/${channelId}/messages`, { - params: { - limit: limit, - offset: offset - } - }) + return axios.get(`/api/1.0/channels/${channelId}/messages`, { + params: { + limit: limit, + offset: offset + } }) }, postMessage(channelId, text) { - return middleWare('postMessage', () => { - return axios.post(`/api/1.0/channels/${channelId}/messages`, { text }) - }) + return axios.post(`/api/1.0/channels/${channelId}/messages`, { text }) }, postDirectMessage(userId, text) { - return middleWare('postDirectMessage', () => { - return axios.post(`/api/1.0/users/${userId}/messages`, { text }) - }) + return axios.post(`/api/1.0/users/${userId}/messages`, { text }) }, editMessage(messageId, text) { - return middleWare('editMessage', () => { - return axios.put(`/api/1.0/messages/${messageId}`, { text }) - }) + return axios.put(`/api/1.0/messages/${messageId}`, { text }) }, getMessage(messageId) { - return middleWare('getMessage', () => { - return axios.get(`/api/1.0/messages/${messageId}`) - }) + return axios.get(`/api/1.0/messages/${messageId}`) }, deleteMessage(messageId) { - return middleWare('deleteMessage', () => { - return axios.delete(`/api/1.0/messages/${messageId}`) - }) + return axios.delete(`/api/1.0/messages/${messageId}`) }, reportMessage(messageId, reason) { - return middleWare('reportMessage', () => { - return axios.post(`/api/1.0/messages/${messageId}/report`, { reason }) - }) + return axios.post(`/api/1.0/messages/${messageId}/report`, { reason }) }, getReports(page) { - return middleWare('getReports', () => { - return axios.get('/api/1.0/reports', { - params: { - p: page - } - }) + return axios.get('/api/1.0/reports', { + params: { + p: page + } }) }, // Tag: pin getPinnedMessages(channelId) { - return middleWare('getPinnedMessages', () => { - return axios.get(`/api/1.0/channels/${channelId}/pins`) - }) + return axios.get(`/api/1.0/channels/${channelId}/pins`) }, pinMessage(messageId) { - return middleWare('pinMessage', () => { - return axios.post(`/api/1.0/pins`, { messageId }) - }) + return axios.post(`/api/1.0/pins`, { messageId }) }, getPinnedMessage(pinId) { - return middleWare('getPinnedMessage', () => { - return axios.get(`/api/1.0/pins/${pinId}`) - }) + return axios.get(`/api/1.0/pins/${pinId}`) }, unpinMessage(pinId) { - return middleWare('unpinMessage', () => { - return axios.delete(`/api/1.0/pins/${pinId}`) - }) + return axios.delete(`/api/1.0/pins/${pinId}`) }, // Tag: notification getNotifications(channelId) { - return middleWare('getNotifications', () => { - return axios.get(`/api/1.0/channels/${channelId}/notification`) - }) + return axios.get(`/api/1.0/channels/${channelId}/notification`) }, changeNotifications(channelId, state) { - return middleWare('changeNotifications', () => { - return axios.put(`/api/1.0/channels/${channelId}/notification`, state) - }) + return axios.put(`/api/1.0/channels/${channelId}/notification`, state) }, getNotifiedChannels(userId) { - return middleWare('getNotifiedChannels', () => { - return axios.get(`/api/1.0/users/${userId}/notification`) - }) + return axios.get(`/api/1.0/users/${userId}/notification`) }, registerDevice(token) { - return middleWare('registerDevice', () => { - return axios.post(`/api/1.0/notification/device`, { token }) - }) + return axios.post(`/api/1.0/notification/device`, { token }) }, getMyNotifiedChannels() { - return middleWare('getMyNotifiedChannels', () => { - return axios.get('/api/1.0/users/me/notification') - }) + return axios.get('/api/1.0/users/me/notification') }, // Tag: user registerUser(name, password) { - return middleWare('registerUser', () => { - return axios.post(`/api/1.0/users`, { name, password }) - }) + return axios.post(`/api/1.0/users`, { name, password }) }, getMembers() { - return middleWare('getMembers', () => { - return axios.get(`/api/1.0/users`) - }) + return axios.get(`/api/1.0/users`) }, whoAmI() { - return middleWare('whoAmI', () => { - return axios.get(`/api/1.0/users/me`) - }) + return axios.get(`/api/1.0/users/me`) }, // deprecated getUserIconUrl(userId) { return (axios.defaults.baseURL || '/') + 'api/1.0/users/' + userId + '/icon' }, changeIcon(file) { - return middleWare('changeIcon', () => { - const form = new FormData() - form.enctype = 'multipart/form-data' - form.append('file', file) - return axios.put('/api/1.0/users/me/icon', form) - }) + const form = new FormData() + form.enctype = 'multipart/form-data' + form.append('file', file) + return axios.put('/api/1.0/users/me/icon', form) }, changeDisplayName(name) { - return middleWare('changeDisplayName', () => { - return axios.patch('/api/1.0/users/me', { - displayName: name - }) + return axios.patch('/api/1.0/users/me', { + displayName: name }) }, changeTwitterId(twitterId) { - return middleWare('changeTwitterId', () => { - return axios.patch('/api/1.0/users/me', { - twitterId - }) + return axios.patch('/api/1.0/users/me', { + twitterId }) }, changePassword(pass, newPass) { - return middleWare('changePassword', () => { - return axios.put('api/1.0/users/me/password', { - password: pass, - newPassword: newPass - }) + return axios.put('api/1.0/users/me/password', { + password: pass, + newPassword: newPass }) }, getUserDetail(userId) { - return middleWare('getUserDetail', () => { - return axios.get(`/api/1.0/users/${userId}`) - }) + return axios.get(`/api/1.0/users/${userId}`) }, loadDirectMessages(userId, limit, offset) { - return middleWare('loadDirectMessages', () => { - return axios.get(`/api/1.0/users/${userId}/messages`, { - params: { - limit: limit, - offset: offset - } - }) + return axios.get(`/api/1.0/users/${userId}/messages`, { + params: { + limit: limit, + offset: offset + } }) }, getQRCodeUrl() { @@ -268,213 +171,143 @@ const client = { // Tag: clip getAllClipMessages() { - return middleWare('getAllClipMessages', () => { - return axios.get(`/api/1.0/users/me/clips`) - }) + return axios.get(`/api/1.0/users/me/clips`) }, getClipMessages(folderId) { - return middleWare('getClipMessages', () => { - return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) - }) + return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) }, clipMessage(folderId, messageId) { - return middleWare('clipMessage', () => { - return axios.post(`/api/1.0/users/me/clips`, { folderId, messageId }) - }) + return axios.post(`/api/1.0/users/me/clips`, { folderId, messageId }) }, unclipMessage(clipId) { - return middleWare('unclipMessage', () => { - return axios.delete(`/api/1.0/users/me/clips/${clipId}`) - }) + return axios.delete(`/api/1.0/users/me/clips/${clipId}`) }, getClipFolders() { - return middleWare('getClipFolders', () => { - return axios.get(`/api/1.0/users/me/clips/folders`) - }) + return axios.get(`/api/1.0/users/me/clips/folders`) }, getClipFolderInfo(folderId) { - return middleWare('getClipFolder', () => { - return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) - }) + return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) }, renameClipFolder(folderId, name) { - return middleWare('renameClipFolder', () => { - return axios.patch(`/api/1.0/users/me/clips/folders/${folderId}`, { - name - }) + return axios.patch(`/api/1.0/users/me/clips/folders/${folderId}`, { + name }) }, deleteClipFolder(folderId) { - return middleWare('deleteClipFolder', () => { - return axios.delete(`/api/1.0/users/me/clips/folders/${folderId}`) - }) + return axios.delete(`/api/1.0/users/me/clips/folders/${folderId}`) }, makeClipFolder(name) { - return middleWare('makeClipFolder', () => { - return axios.post(`/api/1.0/users/me/clips/folders`, { name }) - }) + return axios.post(`/api/1.0/users/me/clips/folders`, { name }) }, // Tag: star getStaredChannels() { - return middleWare('getStaredChannels', () => { - return axios.get(`/api/1.0/users/me/stars`) - }) + return axios.get(`/api/1.0/users/me/stars`) }, starChannel(channelId) { - return middleWare('starChannel', () => { - return axios.put(`/api/1.0/users/me/stars/${channelId}`) - }) + return axios.put(`/api/1.0/users/me/stars/${channelId}`) }, unstarChannel(channelId) { - return middleWare('unstarChannel', () => { - return axios.delete(`/api/1.0/users/me/stars/${channelId}`) - }) + return axios.delete(`/api/1.0/users/me/stars/${channelId}`) }, // Tag: unread getUnreadChannels() { - return middleWare('getUnreadChannels', () => { - return axios.get('/api/1.0/users/me/unread/channels') - }) + return axios.get('/api/1.0/users/me/unread/channels') }, readMessages(channelId) { - return middleWare('readMessages', () => { - return axios.delete(`/api/1.0/users/me/unread/channels/${channelId}`) - }) + return axios.delete(`/api/1.0/users/me/unread/channels/${channelId}`) }, // Tag: mute getMutedChannels() { - return middleWare('getMutedChannels', () => { - return axios.get(`/api/1.0/users/me/mute`) - }) + return axios.get(`/api/1.0/users/me/mute`) }, muteChannel(channelId) { - return middleWare('muteChannel', () => { - return axios.post(`/api/1.0/users/me/mute/${channelId}`) - }) + return axios.post(`/api/1.0/users/me/mute/${channelId}`) }, unmuteChannel(channelId) { - return middleWare('unmuteChannel', () => { - return axios.delete(`/api/1.0/users/me/mute/${channelId}`) - }) + return axios.delete(`/api/1.0/users/me/mute/${channelId}`) }, // Tag: stamp getStampHistory() { - return middleWare('getStampHistory', () => { - return axios.get('/api/1.0/users/me/stamp-history') - }) + return axios.get('/api/1.0/users/me/stamp-history') }, getStamps() { - return middleWare('getStamps', () => { - return axios.get(`/api/1.0/stamps`) - }) + return axios.get(`/api/1.0/stamps`) }, addStamp(name, file) { - return middleWare('addStamp', () => { - const form = new FormData() - form.enctype = 'multipart/form-data' - form.append('name', name) - form.append('file', file) - return axios.post(`/api/1.0/stamps`, form) - }) + const form = new FormData() + form.enctype = 'multipart/form-data' + form.append('name', name) + form.append('file', file) + return axios.post(`/api/1.0/stamps`, form) }, getStampDetail(stampId) { - return middleWare('getStampDetail', () => { - return axios.get(`/api/1.0/stamps/${stampId}`) - }) + return axios.get(`/api/1.0/stamps/${stampId}`) }, fixStamp(stampId, name, file) { - return middleWare('fixStamp', () => { - const form = new FormData() - form.enctype = 'multipart/form-data' - form.append('name', name) - form.append('file', file) - return axios.patch(`/api/1.0/stamps/${stampId}`, form) - }) + const form = new FormData() + form.enctype = 'multipart/form-data' + form.append('name', name) + form.append('file', file) + return axios.patch(`/api/1.0/stamps/${stampId}`, form) }, deleteStamp(stampId) { - return middleWare('deleteStamp', () => { - return axios.delete(`/api/1.0/stamps/${stampId}`) - }) + return axios.delete(`/api/1.0/stamps/${stampId}`) }, getMessageStamp(messageId) { - return middleWare('getMessageStamp', () => { - return axios.get(`/api/1.0/messages/${messageId}/stamps`) - }) + return axios.get(`/api/1.0/messages/${messageId}/stamps`) }, stampMessage(messageId, stampId) { - return middleWare('stampMessage', () => { - return axios.post(`/api/1.0/messages/${messageId}/stamps/${stampId}`) - }) + return axios.post(`/api/1.0/messages/${messageId}/stamps/${stampId}`) }, unstampMessage(messageId, stampId) { - return middleWare('unstampMessage', () => { - return axios.delete(`/api/1.0/messages/${messageId}/stamps/${stampId}`) - }) + return axios.delete(`/api/1.0/messages/${messageId}/stamps/${stampId}`) }, // Tag: userTag getUserTags(userId) { - return middleWare('getUserTag', () => { - return axios.get(`/api/1.0/users/${userId}/tags`) - }) + return axios.get(`/api/1.0/users/${userId}/tags`) }, addUserTag(userId, tag) { - return middleWare('addUserTag', () => { - return axios.post(`/api/1.0/users/${userId}/tags`, { tag }) - }) + return axios.post(`/api/1.0/users/${userId}/tags`, { tag }) }, changeLockUserTag(userId, tagId, isLocked) { - return middleWare('changeLockUserTag', () => { - return axios.patch(`/api/1.0/users/${userId}/tags/${tagId}`, { isLocked }) - }) + return axios.patch(`/api/1.0/users/${userId}/tags/${tagId}`, { isLocked }) }, deleteUserTag(userId, tagId) { - return middleWare('deleteUserTag', () => { - return axios.delete(`/api/1.0/users/${userId}/tags/${tagId}`) - }) + return axios.delete(`/api/1.0/users/${userId}/tags/${tagId}`) }, getTag(tagId) { - return middleWare('getTag', () => { - return axios.get(`/api/1.0/tags/${tagId}`) - }) + return axios.get(`/api/1.0/tags/${tagId}`) }, // Tag: file uploadFile(file, readableUsers, onUploadProgress) { - return middleWare('uploadFile', () => { - const form = new FormData() - form.enctype = 'multipart/form-data' - form.append('file', file) - form.append('acl_readable', readableUsers.join(',')) - return axios.post( - '/api/1.0/files', - form, - onUploadProgress - ? { - onUploadProgress - } - : {} - ) - }) + const form = new FormData() + form.enctype = 'multipart/form-data' + form.append('file', file) + form.append('acl_readable', readableUsers.join(',')) + return axios.post( + '/api/1.0/files', + form, + onUploadProgress + ? { + onUploadProgress + } + : {} + ) }, deleteFile(fileId) { - return middleWare('deleteFile', () => { - return axios.delete(`/api/1.0/files/${fileId}`) - }) + return axios.delete(`/api/1.0/files/${fileId}`) }, getFileMeta(fileId) { - return middleWare('getFileMeta', () => { - return axios.get(`/api/1.0/files/${fileId}/meta`) - }) + return axios.get(`/api/1.0/files/${fileId}/meta`) }, getFileThumbnail(fileId) { - return middleWare('getFileThumbnail', () => { - return axios.get(`/api/1.0/files/${fileId}/thumbnail`) - }) + return axios.get(`/api/1.0/files/${fileId}/thumbnail`) }, // Tag: search @@ -484,9 +317,7 @@ const client = { // Tag: heartbeat getHeartbeat() { - return middleWare('getHeartbeat', () => { - return axios.get(`/api/1.0/heartbeat`) - }) + return axios.get(`/api/1.0/heartbeat`) }, postHeartbeat(status, channelId) { return axios.post(`/api/1.0/heartbeat`, { status, channelId }) From b0230edaf698f181345815edf0ba36b171cd0768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 03:25:57 +0900 Subject: [PATCH 02/12] rename .js -> .ts --- src/bin/{axios.js => axios.ts} | 0 src/bin/{client.js => client.ts} | 0 tsconfig.json | 1 + 3 files changed, 1 insertion(+) rename src/bin/{axios.js => axios.ts} (100%) rename src/bin/{client.js => client.ts} (100%) diff --git a/src/bin/axios.js b/src/bin/axios.ts similarity index 100% rename from src/bin/axios.js rename to src/bin/axios.ts diff --git a/src/bin/client.js b/src/bin/client.ts similarity index 100% rename from src/bin/client.js rename to src/bin/client.ts diff --git a/tsconfig.json b/tsconfig.json index cc040959..47a6d3a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, + "noImplicitAny": false, "baseUrl": ".", "types": [ "webpack-env" From 03213a8aea0d015629a5778561a226a53634c776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 03:51:25 +0900 Subject: [PATCH 03/12] =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E7=BE=A9=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E7=94=9F=E6=88=90=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- package-lock.json | 129 ++++++++++++++++++++++++++++++---------------- package.json | 4 +- tsconfig.json | 2 +- 4 files changed, 92 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 185e6631..712d8d2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .DS_Store node_modules /dist +src/swagger.d.ts # local env files .env.local @@ -9,7 +10,7 @@ node_modules # Log files npm-debug.log* yarn-debug.log* -yarn-error.log* +yarn-error.log* w # Editor directories and files .idea @@ -19,3 +20,4 @@ yarn-error.log* *.njsproj *.sln *.sw* + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3a561577..18e68d48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2128,7 +2128,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -2568,8 +2567,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", @@ -2759,7 +2757,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3400,7 +3397,8 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "dev": true, + "optional": true }, "coa": { "version": "2.0.2", @@ -3576,8 +3574,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.2", @@ -3935,6 +3932,15 @@ "integrity": "sha512-b6+gzlkhxEUswBNVwYct6fz+sJYdbmW7F6dAXwNkjTVfZcPcXBYADnVzvxNYcSOPkh/ytzmTRktbNkg5/Uw/PQ==", "dev": true }, + "cross-fetch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.3.tgz", + "integrity": "sha512-mplYkc4CopHu+AdHK8wxjJcPskUxp5CvPTdtDij3MUgVNBa0xOb9CQqbbn1zO23qISM4WLxIBociyEVQL7WQAg==", + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -4275,7 +4281,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -4606,6 +4611,27 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, + "dtsgenerator": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/dtsgenerator/-/dtsgenerator-2.0.7.tgz", + "integrity": "sha512-3DlNPdiPVcONJpMLPgbGNptXtgpqINdvSocli7wS6DUFnptQWd3JgbOxG0g0zgQVcWFhwmzoxGRFQisUx/inww==", + "requires": { + "commander": "^2.20.0", + "cross-fetch": "^3.0.2", + "debug": "^4.1.1", + "glob": "^7.1.3", + "js-yaml": "^3.13.1", + "mkdirp": "^0.5.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + } + } + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -5148,8 +5174,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.0.1", @@ -5810,8 +5835,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.7", @@ -5833,7 +5857,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5854,12 +5879,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5874,17 +5901,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6001,7 +6031,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6013,6 +6044,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6027,6 +6059,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6034,12 +6067,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6058,6 +6093,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6138,7 +6174,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6150,6 +6187,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6235,7 +6273,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6271,6 +6310,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6290,6 +6330,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6333,12 +6374,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6473,7 +6516,6 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7111,7 +7153,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -7120,8 +7161,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "inquirer": { "version": "3.3.0", @@ -7631,7 +7671,6 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -8595,7 +8634,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8686,7 +8724,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" }, @@ -8694,8 +8731,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, @@ -8716,8 +8752,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "multicast-dns": { "version": "6.2.3", @@ -8800,6 +8835,11 @@ "lower-case": "^1.1.1" } }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, "node-forge": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", @@ -9304,7 +9344,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -9557,8 +9596,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -11221,7 +11259,8 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "dev": true, + "optional": true }, "rx-lite-aggregates": { "version": "4.0.8", @@ -12031,8 +12070,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", @@ -12690,8 +12728,7 @@ "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tslint": { "version": "5.16.0", @@ -13671,6 +13708,11 @@ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -13967,8 +14009,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "0.2.1", diff --git a/package.json b/package.json index ff5341a6..f017c926 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ "build": "vue-cli-service build --morden", "lint": "vue-cli-service lint", "fix": "vue-cli-service lint --fix", - "gen-unicode_emojis": "node build/gen-unicode_emojis" + "gen-unicode_emojis": "node build/gen-unicode_emojis", + "gen-swagger-type": "dtsgen --out src/swagger.d.ts --url https://traptitech.github.io/traQ/swagger.yaml && vue-cli-service lint --fix src/swagger.d.ts" }, "dependencies": { + "dtsgenerator": "^2.0.7", "lottie-web": "^5.5.1", "register-service-worker": "^1.5.2", "scroll-behavior-polyfill": "^2.0.7", diff --git a/tsconfig.json b/tsconfig.json index 47a6d3a3..617a5d5c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,7 @@ "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", - "tests/**/*.tsx" + "tests/**/*.tsx", ], "exclude": [ "node_modules" From d2c955e9534d57466aaf40aebbd31dbd9d68eb37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 04:41:38 +0900 Subject: [PATCH 04/12] fix build --- .circleci/config.yml | 3 +++ .eslintrc.js | 2 +- Dockerfile | 1 + src/bin/axios.ts | 5 +++++ src/bin/client.ts | 39 +++++++++++++++++++++++++++++---------- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c9ffde69..6045fc8c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,6 +48,9 @@ jobs: - checkout - restore_npm_cache - install_module + - run: + name: gen swagger.d.ts + command: npm run gen-swagger-type - run: name: build command: npm run build --morden diff --git a/.eslintrc.js b/.eslintrc.js index b66ea673..2ae16c9c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { node: true }, - extends: ['plugin:vue/essential', '@vue/prettier'], + extends: ['plugin:vue/essential', '@vue/prettier', '@vue/typescript'], rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', diff --git a/Dockerfile b/Dockerfile index 0c43851b..68859820 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,7 @@ RUN apk add --no-cache git COPY package*.json ./ RUN npm install COPY . . +RUN npm run gen-swagger-type RUN npm run build # 本番環境 diff --git a/src/bin/axios.ts b/src/bin/axios.ts index f5e4b36e..cb772e75 100644 --- a/src/bin/axios.ts +++ b/src/bin/axios.ts @@ -1,5 +1,10 @@ import axios from 'axios' +interface Window { + debug: boolean +} +declare var window: Window + axios.interceptors.response.use( res => { if (process.env.NODE_ENV === 'development' || window.debug) { diff --git a/src/bin/client.ts b/src/bin/client.ts index 11d20638..7079078a 100644 --- a/src/bin/client.ts +++ b/src/bin/client.ts @@ -134,9 +134,12 @@ const client = { }, changeIcon(file) { const form = new FormData() - form.enctype = 'multipart/form-data' form.append('file', file) - return axios.put('/api/1.0/users/me/icon', form) + return axios.put('/api/1.0/users/me/icon', form, { + headers: { + 'content-type': 'multipart/form-data' + } + }) }, changeDisplayName(name) { return axios.patch('/api/1.0/users/me', { @@ -239,20 +242,26 @@ const client = { }, addStamp(name, file) { const form = new FormData() - form.enctype = 'multipart/form-data' form.append('name', name) form.append('file', file) - return axios.post(`/api/1.0/stamps`, form) + return axios.post(`/api/1.0/stamps`, form, { + headers: { + 'content-type': 'multipart/form-data' + } + }) }, getStampDetail(stampId) { return axios.get(`/api/1.0/stamps/${stampId}`) }, fixStamp(stampId, name, file) { const form = new FormData() - form.enctype = 'multipart/form-data' form.append('name', name) form.append('file', file) - return axios.patch(`/api/1.0/stamps/${stampId}`, form) + return axios.patch(`/api/1.0/stamps/${stampId}`, form, { + headers: { + 'content-type': 'multipart/form-data' + } + }) }, deleteStamp(stampId) { return axios.delete(`/api/1.0/stamps/${stampId}`) @@ -287,7 +296,6 @@ const client = { // Tag: file uploadFile(file, readableUsers, onUploadProgress) { const form = new FormData() - form.enctype = 'multipart/form-data' form.append('file', file) form.append('acl_readable', readableUsers.join(',')) return axios.post( @@ -295,9 +303,16 @@ const client = { form, onUploadProgress ? { - onUploadProgress + onUploadProgress, + headers: { + 'content-type': 'multipart/form-data' + } + } + : { + headers: { + 'content-type': 'multipart/' + } } - : {} ) }, deleteFile(fileId) { @@ -377,8 +392,12 @@ const client = { } } +interface Window { + client: any +} +declare var window: Window + if (process.env.NODE_ENV === 'development') { window.client = client } - export default client From 660a9c4d52c307e277c8d15d5c9ae9d98a246330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 22:45:27 +0900 Subject: [PATCH 05/12] =?UTF-8?q?client=E3=81=AETS=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/client.ts | 416 +++++++++++------- .../MessageElement/MessageElement.vue | 8 +- .../Main/MessageView/MessageInput.vue | 4 +- .../Main/Modal/ChannelCreateModal.vue | 12 +- .../Main/Modal/UserModal/UserModalTags.vue | 10 +- src/pages/Main/Main.vue | 24 +- src/pages/Register/Register.vue | 2 +- src/pages/Setting/ProfileSetting.vue | 31 +- src/store/{index.js => index.ts} | 34 +- .../{messageInput.js => messageInput.ts} | 0 src/store/{modal.js => modal.ts} | 0 src/store/{pickerModal.js => pickerModal.ts} | 0 12 files changed, 337 insertions(+), 204 deletions(-) rename src/store/{index.js => index.ts} (98%) rename src/store/{messageInput.js => messageInput.ts} (100%) rename src/store/{modal.js => modal.ts} (100%) rename src/store/{pickerModal.js => pickerModal.ts} (100%) diff --git a/src/bin/client.ts b/src/bin/client.ts index 7079078a..7ae902e4 100644 --- a/src/bin/client.ts +++ b/src/bin/client.ts @@ -1,8 +1,11 @@ import axios from '@/bin/axios' +import { AxiosResponse, AxiosError, AxiosPromise } from 'axios' +import Schemas = Components.Schemas +import Parameters = Components.Parameters const client = { // Tag: authorization - login(name, pass) { + login(name: string, pass: string) { return axios.post(`/api/1.0/login`, { name, pass }) }, logout() { @@ -10,129 +13,175 @@ const client = { }, // Tag: Session - getSessions() { + getSessions(): AxiosPromise { return axios.get('/api/1.0/users/me/sessions') }, - deleteSessions() { + deleteSessions(): AxiosPromise { return axios.delete('/api/1.0/users/me/sessions') }, - deleteSession(sessionId) { + deleteSession( + sessionId: Paths.UsersMeSessions$ReferenceID.Parameters.ReferenceID + ): AxiosPromise { return axios.delete(`/api/1.0/users/me/sessions/${sessionId}`) }, // Tag: channel - makeChannel(type, member, name, parent) { - return axios.post(`/api/1.0/channels`, { type, member, name, parent }) + makeChannel( + reqBody: Paths.Channels.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/channels`, reqBody) }, - getChannels() { + getChannels(): AxiosPromise { return axios.get(`/api/1.0/channels`) }, - getChannelInfo(channelId) { + getChannelInfo( + channelId: Parameters.ChannelIdInPath.ChannelID + ): AxiosPromise { return axios.get(`/api/1.0/channels/${channelId}`) }, - changeChannelInfo(channelId, name, visibility, force) { - return axios.patch(`/api/1.0/channels/${channelId}`, { - name, - visibility, - force - }) + changeChannelInfo( + channelId: Parameters.ChannelIdInPath.ChannelID, + reqBody: Paths.Channels$ChannelID.Patch.RequestBody + ): AxiosPromise { + return axios.patch(`/api/1.0/channels/${channelId}`, reqBody) }, - changeChannelParent(channelId, parent) { - return axios.put(`/api/1.0/channels/${channelId}/parent`, { parent }) + changeChannelParent( + channelId: Parameters.ChannelIdInPath.ChannelID, + reqBody: Paths.Channels$ChannelIDParent.Put.RequestBody + ): AxiosPromise { + return axios.put(`/api/1.0/channels/${channelId}/parent`, reqBody) }, - deleteChannel(channelId) { + deleteChannel(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.delete(`/api/1.0/channels/${channelId}`) }, // Tag: topic - getChannelTopic(channelId) { + getChannelTopic( + channelId: Parameters.ChannelIdInPath.ChannelID + ): AxiosPromise { return axios.get(`/api/1.0/channels/${channelId}/topic`) }, - changeChannelTopic(channelId, text) { - return axios.put(`/api/1.0/channels/${channelId}/topic`, { text }) + changeChannelTopic( + channelId: Parameters.ChannelIdInPath.ChannelID, + reqBody: Paths.Channels$ChannelIDTopic.Put.RequestBody + ): AxiosPromise { + return axios.put(`/api/1.0/channels/${channelId}/topic`, reqBody) }, // Tag: message - loadMessages(channelId, limit, offset) { + loadMessages( + channelId: Parameters.ChannelIdInPath.ChannelID, + params: Paths.Channels$ChannelIDMessages.Get.QueryParameters + ): AxiosPromise { return axios.get(`/api/1.0/channels/${channelId}/messages`, { - params: { - limit: limit, - offset: offset - } + params }) }, - postMessage(channelId, text) { - return axios.post(`/api/1.0/channels/${channelId}/messages`, { text }) - }, - postDirectMessage(userId, text) { - return axios.post(`/api/1.0/users/${userId}/messages`, { text }) - }, - editMessage(messageId, text) { - return axios.put(`/api/1.0/messages/${messageId}`, { text }) - }, - getMessage(messageId) { + postMessage( + channelId: Parameters.ChannelIdInPath.ChannelID, + reqBody: Paths.Channels$ChannelIDMessages.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/channels/${channelId}/messages`, reqBody) + }, + postDirectMessage( + userId: Parameters.UserIdInPath.UserID, + reqBody: Paths.Users$UserIDMessages.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/users/${userId}/messages`, reqBody) + }, + editMessage( + messageId: Parameters.MessageIdInPath.MessageID, + reqBody: Paths.Users$UserIDMessages.Post.RequestBody + ): AxiosPromise { + return axios.put(`/api/1.0/messages/${messageId}`, reqBody) + }, + getMessage( + messageId: Parameters.MessageIdInPath.MessageID + ): AxiosPromise { return axios.get(`/api/1.0/messages/${messageId}`) }, - deleteMessage(messageId) { + deleteMessage(messageId: Parameters.MessageIdInPath.MessageID): AxiosPromise { return axios.delete(`/api/1.0/messages/${messageId}`) }, - reportMessage(messageId, reason) { - return axios.post(`/api/1.0/messages/${messageId}/report`, { reason }) + reportMessage( + messageId: Parameters.MessageIdInPath.MessageID, + reqBody: Paths.Messages$MessageIDReport.Post.RequestBody + ) { + return axios.post(`/api/1.0/messages/${messageId}/report`, reqBody) }, - getReports(page) { + getReports( + params: Paths.MessagesReports.Get.QueryParameters + ): AxiosPromise { return axios.get('/api/1.0/reports', { - params: { - p: page - } + params }) }, // Tag: pin - getPinnedMessages(channelId) { + getPinnedMessages( + channelId: Parameters.ChannelIdInPath.ChannelID + ): AxiosPromise { return axios.get(`/api/1.0/channels/${channelId}/pins`) }, - pinMessage(messageId) { - return axios.post(`/api/1.0/pins`, { messageId }) + pinMessage( + reqBody: Paths.Pins.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/pins`, reqBody) }, - getPinnedMessage(pinId) { + getPinnedMessage( + pinId: Parameters.PinIdInPath.PinID + ): AxiosPromise { return axios.get(`/api/1.0/pins/${pinId}`) }, - unpinMessage(pinId) { + unpinMessage(pinId: Parameters.PinIdInPath.PinID): AxiosPromise { return axios.delete(`/api/1.0/pins/${pinId}`) }, // Tag: notification - getNotifications(channelId) { + getNotifications( + channelId: Parameters.ChannelIdInPath.ChannelID + ): AxiosPromise { return axios.get(`/api/1.0/channels/${channelId}/notification`) }, - changeNotifications(channelId, state) { - return axios.put(`/api/1.0/channels/${channelId}/notification`, state) - }, - getNotifiedChannels(userId) { + changeNotifications( + channelId: Parameters.ChannelIdInPath.ChannelID, + reqBody: Paths.Channels$ChannelIDNotification.Put.RequestBody + ): AxiosPromise { + return axios.put(`/api/1.0/channels/${channelId}/notification`, reqBody) + }, + getNotifiedChannels( + userId: Parameters.UserIdInPath.UserID + ): AxiosPromise< + Paths.Users$UserIDNotification.Get.Responses.$200 | AxiosError + > { return axios.get(`/api/1.0/users/${userId}/notification`) }, - registerDevice(token) { - return axios.post(`/api/1.0/notification/device`, { token }) + registerDevice( + reqBody: Paths.NotificationDevice.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/notification/device`, reqBody) }, - getMyNotifiedChannels() { + getMyNotifiedChannels(): AxiosPromise< + Paths.UsersMeNotification.Get.Responses.$200 | AxiosError + > { return axios.get('/api/1.0/users/me/notification') }, // Tag: user - registerUser(name, password) { - return axios.post(`/api/1.0/users`, { name, password }) + registerUser(reqBody: Paths.Users.Post.RequestBody): AxiosPromise { + return axios.post(`/api/1.0/users`, reqBody) }, - getMembers() { + getMembers(): AxiosPromise { return axios.get(`/api/1.0/users`) }, - whoAmI() { + whoAmI(): AxiosPromise { return axios.get(`/api/1.0/users/me`) }, // deprecated - getUserIconUrl(userId) { + getUserIconUrl(userId: Parameters.UserIdInPath.UserID): string { return (axios.defaults.baseURL || '/') + 'api/1.0/users/' + userId + '/icon' }, - changeIcon(file) { + changeIcon(file: any): AxiosPromise { const form = new FormData() form.append('file', file) return axios.put('/api/1.0/users/me/icon', form, { @@ -141,106 +190,114 @@ const client = { } }) }, - changeDisplayName(name) { - return axios.patch('/api/1.0/users/me', { - displayName: name - }) + changeDisplayName(reqBody: Paths.UsersMe.Patch.RequestBody): AxiosPromise { + return axios.patch('/api/1.0/users/me', reqBody) }, - changeTwitterId(twitterId) { - return axios.patch('/api/1.0/users/me', { - twitterId - }) + changeTwitterId(reqBody: Paths.UsersMe.Patch.RequestBody): AxiosPromise { + return axios.patch('/api/1.0/users/me', reqBody) }, - changePassword(pass, newPass) { - return axios.put('api/1.0/users/me/password', { - password: pass, - newPassword: newPass - }) + changePassword(reqBody: Paths.UsersMePassword.Put.RequestBody): AxiosPromise { + return axios.put('api/1.0/users/me/password', reqBody) }, - getUserDetail(userId) { + getUserDetail( + userId: Parameters.UserIdInPath.UserID + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}`) }, - loadDirectMessages(userId, limit, offset) { + loadDirectMessages( + userId: Parameters.UserIdInPath.UserID, + params: Paths.Users$UserIDMessages.Get.QueryParameters + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}/messages`, { - params: { - limit: limit, - offset: offset - } + params }) }, - getQRCodeUrl() { + getQRCodeUrl(): string { return (axios.defaults.baseURL || '/') + 'api/1.0/users/me/qr-code' }, // Tag: clip - getAllClipMessages() { + getAllClipMessages(): AxiosPromise { return axios.get(`/api/1.0/users/me/clips`) }, - getClipMessages(folderId) { + getClipMessages( + folderId: string + ): AxiosPromise { return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) }, - clipMessage(folderId, messageId) { - return axios.post(`/api/1.0/users/me/clips`, { folderId, messageId }) + clipMessage( + reqBody: Paths.UsersMeClips.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/users/me/clips`, reqBody) }, - unclipMessage(clipId) { + unclipMessage(clipId: Parameters.ClientIdInPath.ClientID): AxiosPromise { return axios.delete(`/api/1.0/users/me/clips/${clipId}`) }, - getClipFolders() { + getClipFolders(): AxiosPromise { return axios.get(`/api/1.0/users/me/clips/folders`) }, - getClipFolderInfo(folderId) { + getClipFolderInfo( + folderId: Parameters.ClipIdInPath.ClipID + ): AxiosPromise { return axios.get(`/api/1.0/users/me/clips/folders/${folderId}`) }, - renameClipFolder(folderId, name) { - return axios.patch(`/api/1.0/users/me/clips/folders/${folderId}`, { - name - }) + renameClipFolder( + folderId: Parameters.ClipIdInPath.ClipID, + reqBody: Paths.UsersMeClipsFolders$FolderID.Patch.RequestBody + ): AxiosPromise { + return axios.patch(`/api/1.0/users/me/clips/folders/${folderId}`, reqBody) }, - deleteClipFolder(folderId) { + deleteClipFolder(folderId: Parameters.ClipIdInPath.ClipID): AxiosPromise { return axios.delete(`/api/1.0/users/me/clips/folders/${folderId}`) }, - makeClipFolder(name) { - return axios.post(`/api/1.0/users/me/clips/folders`, { name }) + makeClipFolder( + reqBody: Paths.UsersMeClipsFolders.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/users/me/clips/folders`, reqBody) }, // Tag: star - getStaredChannels() { + getStaredChannels(): AxiosPromise { return axios.get(`/api/1.0/users/me/stars`) }, - starChannel(channelId) { + starChannel(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.put(`/api/1.0/users/me/stars/${channelId}`) }, - unstarChannel(channelId) { + unstarChannel(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.delete(`/api/1.0/users/me/stars/${channelId}`) }, // Tag: unread - getUnreadChannels() { + getUnreadChannels(): AxiosPromise< + Paths.UsersMeUnreadChannels.Get.Responses.$200 + > { return axios.get('/api/1.0/users/me/unread/channels') }, - readMessages(channelId) { + readMessages(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.delete(`/api/1.0/users/me/unread/channels/${channelId}`) }, // Tag: mute - getMutedChannels() { + getMutedChannels(): AxiosPromise { return axios.get(`/api/1.0/users/me/mute`) }, - muteChannel(channelId) { + muteChannel(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.post(`/api/1.0/users/me/mute/${channelId}`) }, - unmuteChannel(channelId) { + unmuteChannel(channelId: Parameters.ChannelIdInPath.ChannelID): AxiosPromise { return axios.delete(`/api/1.0/users/me/mute/${channelId}`) }, // Tag: stamp - getStampHistory() { + getStampHistory(): AxiosPromise< + Paths.UsersMeStampHistory.Get.Responses.$200 + > { return axios.get('/api/1.0/users/me/stamp-history') }, - getStamps() { + getStamps(): AxiosPromise { return axios.get(`/api/1.0/stamps`) }, - addStamp(name, file) { + addStamp(name: string, file: any): AxiosPromise { const form = new FormData() form.append('name', name) form.append('file', file) @@ -250,10 +307,16 @@ const client = { } }) }, - getStampDetail(stampId) { + getStampDetail( + stampId: Parameters.StampIdInPath.StampID + ): AxiosPromise { return axios.get(`/api/1.0/stamps/${stampId}`) }, - fixStamp(stampId, name, file) { + fixStamp( + stampId: Parameters.StampIdInPath.StampID, + name: string, + file: any + ): AxiosPromise { const form = new FormData() form.append('name', name) form.append('file', file) @@ -263,38 +326,64 @@ const client = { } }) }, - deleteStamp(stampId) { + deleteStamp(stampId: Parameters.StampIdInPath.StampID): AxiosPromise { return axios.delete(`/api/1.0/stamps/${stampId}`) }, - getMessageStamp(messageId) { + getMessageStamp( + messageId: Parameters.MessageIdInPath.MessageID + ): AxiosPromise { return axios.get(`/api/1.0/messages/${messageId}/stamps`) }, - stampMessage(messageId, stampId) { + stampMessage( + messageId: Parameters.MessageIdInPath.MessageID, + stampId: Parameters.StampIdInPath.StampID + ): AxiosPromise { return axios.post(`/api/1.0/messages/${messageId}/stamps/${stampId}`) }, - unstampMessage(messageId, stampId) { + unstampMessage( + messageId: Parameters.MessageIdInPath.MessageID, + stampId: Parameters.StampIdInPath.StampID + ): AxiosPromise { return axios.delete(`/api/1.0/messages/${messageId}/stamps/${stampId}`) }, // Tag: userTag - getUserTags(userId) { + getUserTags( + userId: Parameters.UserIdInPath.UserID + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}/tags`) }, - addUserTag(userId, tag) { - return axios.post(`/api/1.0/users/${userId}/tags`, { tag }) - }, - changeLockUserTag(userId, tagId, isLocked) { - return axios.patch(`/api/1.0/users/${userId}/tags/${tagId}`, { isLocked }) - }, - deleteUserTag(userId, tagId) { + addUserTag( + userId: Parameters.UserIdInPath.UserID, + reqBody: Paths.Users$UserIDTags.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/users/${userId}/tags`, reqBody) + }, + changeLockUserTag( + userId: Parameters.UserIdInPath.UserID, + tagId: Parameters.TagIdInPath.TagID, + reqBody: Paths.Users$UserIDTagsTagID.Patch.RequestBody + ) { + return axios.patch(`/api/1.0/users/${userId}/tags/${tagId}`, reqBody) + }, + deleteUserTag( + userId: Parameters.UserIdInPath.UserID, + tagId: Parameters.TagIdInPath.TagID + ): AxiosPromise { return axios.delete(`/api/1.0/users/${userId}/tags/${tagId}`) }, - getTag(tagId) { + getTag( + tagId: Parameters.TagIdInPath.TagID + ): AxiosPromise { return axios.get(`/api/1.0/tags/${tagId}`) }, // Tag: file - uploadFile(file, readableUsers, onUploadProgress) { + uploadFile( + file: any, + readableUsers: string[], + onUploadProgress?: any + ): AxiosPromise { const form = new FormData() form.append('file', file) form.append('acl_readable', readableUsers.join(',')) @@ -310,84 +399,103 @@ const client = { } : { headers: { - 'content-type': 'multipart/' + 'content-type': 'multipart/form-data' } } ) }, - deleteFile(fileId) { + deleteFile(fileId: Parameters.FileIdInPath.FileID): AxiosPromise { return axios.delete(`/api/1.0/files/${fileId}`) }, - getFileMeta(fileId) { + getFileMeta( + fileId: Parameters.FileIdInPath.FileID + ): AxiosPromise { return axios.get(`/api/1.0/files/${fileId}/meta`) }, - getFileThumbnail(fileId) { + getFileThumbnail(fileId: Parameters.FileIdInPath.FileID): AxiosPromise { return axios.get(`/api/1.0/files/${fileId}/thumbnail`) }, // Tag: search - searchMessage() { - Promise.reject(console.error(`not implement`)) + searchMessage(): Promise { + return Promise.reject(console.error(`not implement`)) }, // Tag: heartbeat - getHeartbeat() { + getHeartbeat(): AxiosPromise { return axios.get(`/api/1.0/heartbeat`) }, - postHeartbeat(status, channelId) { - return axios.post(`/api/1.0/heartbeat`, { status, channelId }) + postHeartbeat(reqBody: Paths.Heartbeat.Post.QueryParameters): AxiosPromise { + return axios.post(`/api/1.0/heartbeat`, reqBody) }, // Tag: activity - getLatestMessages(limit, subscribe) { - return axios.get( - `/api/1.0/activity/latest-messages?limit=${limit}&subscribe=${subscribe}` - ) + getLatestMessages( + params: Paths.ActivityLatestMessages.Get.QueryParameters + ): AxiosPromise { + return axios.get(`/api/1.0/activity/latest-messages`, { + params + }) }, // Tag: group - getAllGroups() { + getAllGroups(): AxiosPromise { return axios.get('/api/1.0/groups') }, - postGroup(name, description) { - return axios.post('/api/1.0/groups', { name, description }) + postGroup( + reqBody: Paths.Groups.Post.RequestBody + ): AxiosPromise { + return axios.post('/api/1.0/groups', reqBody) }, - getGroup(groupId) { + getGroup( + groupId: Parameters.GroupIdInPath.GroupID + ): AxiosPromise { return axios.get(`/api/1.0/groups/${groupId}`) }, - changeGroup(groupId, name, description, adminUserId) { - return axios.patch(`/api/1.0/groups/${groupId}`, { - name, - description, - adminUserId - }) + changeGroup( + groupId: Parameters.GroupIdInPath.GroupID, + reqBody: Paths.Groups$GroupID.Patch.RequestBody + ): AxiosPromise { + return axios.patch(`/api/1.0/groups/${groupId}`, reqBody) }, - deleteGroup(groupId) { + deleteGroup(groupId: Parameters.GroupIdInPath.GroupID): AxiosPromise { return axios.delete(`/api/1.0/groups/${groupId}`) }, - getGroupMember(groupId) { + getGroupMember( + groupId: Parameters.GroupIdInPath.GroupID + ): AxiosPromise { return axios.get(`/api/1.0/groups/${groupId}/members`) }, - addGroupMember(groupId, userId) { - return axios.post(`/api/1.0/groups/${groupId}/members`, { userId }) + addGroupMember( + groupId: Parameters.GroupIdInPath.GroupID, + reqBody: Paths.Groups$GroupIDMembers.Post.RequestBody + ): AxiosPromise { + return axios.post(`/api/1.0/groups/${groupId}/members`, reqBody) }, - deleteGroupMember(groupId, userId) { + deleteGroupMember( + groupId: Parameters.GroupIdInPath.GroupID, + userId: Parameters.UserIdInPath.UserID + ): AxiosPromise { return axios.delete(`/api/1.0/groups/${groupId}/members/${userId}`) }, - getMyGroups() { + getMyGroups(): AxiosPromise { return axios.get('/api/1.0/users/me/groups') }, - getUserGroups(userId) { + getUserGroups( + userId: Parameters.UserIdInPath.UserID + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}/groups`) }, // Tag: client - getClient(clientId) { + getClient( + clientId: Parameters.ClientIdInPath.ClientID + ): AxiosPromise { return axios.get(`/api/1.0/clients/${clientId}`) }, // Tag: Webhook - getWebhooks() { + getWebhooks(): AxiosPromise { return axios.get(`/api/1.0/webhooks`) } } diff --git a/src/components/Main/MessageView/MessageElement/MessageElement.vue b/src/components/Main/MessageView/MessageElement/MessageElement.vue index f8c65cb7..180b27e4 100644 --- a/src/components/Main/MessageView/MessageElement/MessageElement.vue +++ b/src/components/Main/MessageView/MessageElement/MessageElement.vue @@ -163,7 +163,7 @@ export default { this.isEditing = false return } - client.editMessage(this.model.messageId, this.edited) + client.editMessage(this.model.messageId, { text: this.edited }) this.isEditing = false this.isPushedModifierKey = false this.getAttachments() @@ -177,7 +177,7 @@ export default { } }, async pinMessage() { - await client.pinMessage(this.model.messageId) + await client.pinMessage({ messageId: this.model.messageId }) this.$store.dispatch( 'getCurrentChannelPinnedMessages', this.$store.state.currentChannel.channelId @@ -191,7 +191,7 @@ export default { ) }, clipMessage() { - client.clipMessage('', this.model.messageId) + client.clipMessage({ messageId: this.model.messageId }) }, async getAttachments() { this.attachedData = detectFiles(this.model.content) @@ -251,7 +251,7 @@ export default { 'このメッセージを不適切なメッセージとして通報しますか?\n通報理由を入力してください' ) if (reason) { - client.reportMessage(this.model.messageId, reason).then(() => { + client.reportMessage(this.model.messageId, { reason }).then(() => { this.$store.commit('removeMessage', this.model.messageId) }) } diff --git a/src/components/Main/MessageView/MessageInput.vue b/src/components/Main/MessageView/MessageInput.vue index afa76611..bb2f5a6e 100644 --- a/src/components/Main/MessageView/MessageInput.vue +++ b/src/components/Main/MessageView/MessageInput.vue @@ -180,10 +180,10 @@ export default { }) .join('\n') const postedMessage = !nowChannel.dm - ? client.postMessage(nowChannel.channelId, message) + ? client.postMessage(nowChannel.channelId, { text: message }) : client.postDirectMessage( this.$store.getters.getUserIdByDirectMessageChannel(nowChannel), - message + { text: message } ) postedMessage .then(() => { diff --git a/src/components/Main/Modal/ChannelCreateModal.vue b/src/components/Main/Modal/ChannelCreateModal.vue index bac5a303..c03ba9bc 100644 --- a/src/components/Main/Modal/ChannelCreateModal.vue +++ b/src/components/Main/Modal/ChannelCreateModal.vue @@ -56,12 +56,12 @@ export default { createChannel() { this.state = 'processing' client - .makeChannel( - 'public', - [], - this.channelName, - this.$store.state.currentChannel.channelId - ) + .makeChannel({ + private: false, + member: [], + name: this.channelName, + parent: this.$store.state.currentChannel.channelId + }) .then(() => { this.state = 'successed' }) diff --git a/src/components/Main/Modal/UserModal/UserModalTags.vue b/src/components/Main/Modal/UserModal/UserModalTags.vue index fcfc34f3..3789ce28 100644 --- a/src/components/Main/Modal/UserModal/UserModalTags.vue +++ b/src/components/Main/Modal/UserModal/UserModalTags.vue @@ -84,7 +84,7 @@ export default { if (this.tagInput === '') { return } - client.addUserTag(this.data.userId, this.tagInput).then(() => { + client.addUserTag(this.data.userId, { tag: this.tagInput }).then(() => { this.tagInput = '' this.$store.dispatch('modal/updateCurrentUserTags') }) @@ -96,14 +96,18 @@ export default { }, lockTag(id) { client - .changeLockUserTag(this.data.userId, this.tags[id].tagId, true) + .changeLockUserTag(this.data.userId, this.tags[id].tagId, { + isLocked: true + }) .then(() => { this.$store.dispatch('modal/updateCurrentUserTags') }) }, unlockTag(id) { client - .changeLockUserTag(this.data.userId, this.tags[id].tagId, false) + .changeLockUserTag(this.data.userId, this.tags[id].tagId, { + isLocked: false + }) .then(() => { this.$store.dispatch('modal/updateCurrentUserTags') }) diff --git a/src/pages/Main/Main.vue b/src/pages/Main/Main.vue index 063c7f25..8dabc401 100644 --- a/src/pages/Main/Main.vue +++ b/src/pages/Main/Main.vue @@ -91,7 +91,7 @@ export default { .then(() => { console.log('permission granted') messaging.getToken().then(currentToken => { - client.registerDevice(currentToken) + client.registerDevice({ token: currentToken }) }) messaging.onMessage(payload => { @@ -113,7 +113,7 @@ export default { messaging.onTokenRefresh(() => { messaging.getToken().then(currentToken => { - client.registerDevice(currentToken) + client.registerDevice({ token: currentToken }) }) }) }) @@ -130,13 +130,13 @@ export default { const token = window.Bridge.getFCMToken() if (token) { console.log('register:' + token) - client.registerDevice(token) + client.registerDevice({ token }) } } else if (userAgent.includes('traQ-iOS')) { const token = window.iOSToken if (token) { console.log('register:' + token) - client.registerDevice(token) + client.registerDevice({ token }) } } @@ -226,10 +226,10 @@ export default { this.heartbeat = setInterval(() => { if (this.$store.state.channelId !== this.$store.state.directMessageId) { client - .postHeartbeat( - this.getStatus(), - this.$store.state.currentChannel.channelId - ) + .postHeartbeat({ + status: this.getStatus(), + channelId: this.$store.state.currentChannel.channelId + }) .then(res => { this.$store.commit('updateHeartbeatStatus', res.data) }) @@ -375,10 +375,10 @@ export default { watch: { '$route.params.channel': function() { client - .postHeartbeat( - this.getStatus(), - this.$store.state.currentChannel.channelId - ) + .postHeartbeat({ + status: this.getStatus(), + channelId: this.$store.state.currentChannel.channelId + }) .then(res => { this.$store.commit('updateHeartbeatStatus', res.data) }) diff --git a/src/pages/Register/Register.vue b/src/pages/Register/Register.vue index 9fbf7341..6f6c659b 100644 --- a/src/pages/Register/Register.vue +++ b/src/pages/Register/Register.vue @@ -43,7 +43,7 @@ export default { } if (confirm('登録してよろしいですか?')) { - client.registerUser(this.name, this.password) + client.registerUser({ name: this.name, password: this.password }) this.name = '' this.password = '' this.confirmPassword = '' diff --git a/src/pages/Setting/ProfileSetting.vue b/src/pages/Setting/ProfileSetting.vue index b6143fa2..ef94ce80 100644 --- a/src/pages/Setting/ProfileSetting.vue +++ b/src/pages/Setting/ProfileSetting.vue @@ -148,9 +148,11 @@ export default { this.displayName !== this.$store.state.me.displayName ) { tasks.push( - client.changeDisplayName(this.displayName).then(() => { - this.done += '表示名 ' - }) + client + .changeDisplayName({ displayName: this.displayName }) + .then(() => { + this.done += '表示名 ' + }) ) } if ( @@ -158,16 +160,21 @@ export default { this.twitterId !== this.$store.state.me.twitterId ) { tasks.push( - client.changeTwitterId(this.twitterId).then(() => { + client.changeTwitterId({ twitterId: this.twitterId }).then(() => { this.done += 'Twitter ID ' }) ) } if (this.newPassword !== '') { tasks.push( - client.changePassword(this.oldPassword, this.newPassword).then(() => { - this.done += 'パスワード ' - }) + client + .changePassword({ + password: this.oldPassword, + newPassword: this.newPassword + }) + .then(() => { + this.done += 'パスワード ' + }) ) } return Promise.all(tasks) @@ -205,9 +212,11 @@ export default { this.displayName !== this.$store.state.me.displayName ) { tasks.push( - client.changeDisplayName(this.displayName).then(() => { - this.done += '表示名 ' - }) + client + .changeDisplayName({ displayName: this.displayName }) + .then(() => { + this.done += '表示名 ' + }) ) } if ( @@ -215,7 +224,7 @@ export default { this.twitterId !== this.$store.state.me.twitterId ) { tasks.push( - client.changeTwitterId(this.twitterId).then(() => { + client.changeTwitterId({ twitterId: this.twitterId }).then(() => { this.done += 'Twitter ID ' }) ) diff --git a/src/store/index.js b/src/store/index.ts similarity index 98% rename from src/store/index.js rename to src/store/index.ts index c60d1186..5cd06da4 100644 --- a/src/store/index.js +++ b/src/store/index.ts @@ -7,6 +7,14 @@ import { detectMentions } from '@/bin/utils' import modal from './modal' import pickerModal from './pickerModal' import messageInput from './messageInput' + +interface Window { + openUserModal: (string) => void + openGroupModal: (string) => void + navigator: any +} +declare var window: Window + const db = indexedDB.db Vue.use(Vuex) @@ -568,12 +576,12 @@ const store = new Vuex.Store({ getChannelByName(state, getters) { return channelName => { const channelLevels = channelName.split('/') - let channel = null + let channel: { channelId: string } | null | undefined = null let channelId = '' channelLevels.forEach(name => { const levelChannels = getters.childrenChannels(channelId) channel = levelChannels.find(ch => ch.name === name) - if (channel === undefined) return null + if (channel === null || channel === undefined) return null channelId = channel.channelId }) return channel @@ -819,15 +827,16 @@ const store = new Vuex.Store({ .catch(() => {}) } const loadedMessages = !nowChannel.dm - ? client.loadMessages( - nowChannel.channelId, - 20, - latest ? 0 : state.messages.length - ) + ? client.loadMessages(nowChannel.channelId, { + limit: 20, + offset: latest ? 0 : state.messages.length + }) : client.loadDirectMessages( getters.getUserIdByDirectMessageChannel(nowChannel), - 20, - latest ? 0 : state.messages.length + { + limit: 20, + offset: latest ? 0 : state.messages.length + } ) return loadedMessages.then(res => { loaded = true @@ -1089,7 +1098,10 @@ const store = new Vuex.Store({ }, async updateChannelActivity({ state, commit }) { const filter = state.filterSubscribedActivity || false - const res = await client.getLatestMessages(50, filter) + const res = await client.getLatestMessages({ + limit: 50, + subscribe: filter + }) commit('setActivityMessages', res.data) }, async updateMyNotifiedChannels({ commit }) { @@ -1110,7 +1122,7 @@ const store = new Vuex.Store({ }, async updateCurrentChannelTopic({ state, dispatch }, text) { const channelId = state.currentChannel.channelId - await client.changeChannelTopic(channelId, text) + await client.changeChannelTopic(channelId, { text }) await dispatch('getChannelTopic', channelId) }, updateFilterSubscribedActivity({ commit }, filter) { diff --git a/src/store/messageInput.js b/src/store/messageInput.ts similarity index 100% rename from src/store/messageInput.js rename to src/store/messageInput.ts diff --git a/src/store/modal.js b/src/store/modal.ts similarity index 100% rename from src/store/modal.js rename to src/store/modal.ts diff --git a/src/store/pickerModal.js b/src/store/pickerModal.ts similarity index 100% rename from src/store/pickerModal.js rename to src/store/pickerModal.ts From 61745f61a103788d261e34786a9dfa24471db88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Sun, 26 May 2019 23:13:37 +0900 Subject: [PATCH 06/12] move d.ts --- .gitignore | 2 +- package.json | 2 +- src/{ => types}/shims-tsx.d.ts | 0 src/{ => types}/shims-vue.d.ts | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => types}/shims-tsx.d.ts (100%) rename src/{ => types}/shims-vue.d.ts (100%) diff --git a/.gitignore b/.gitignore index 712d8d2c..ce47c375 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store node_modules /dist -src/swagger.d.ts +swagger.d.ts # local env files .env.local diff --git a/package.json b/package.json index f017c926..40bd425f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "vue-cli-service lint", "fix": "vue-cli-service lint --fix", "gen-unicode_emojis": "node build/gen-unicode_emojis", - "gen-swagger-type": "dtsgen --out src/swagger.d.ts --url https://traptitech.github.io/traQ/swagger.yaml && vue-cli-service lint --fix src/swagger.d.ts" + "gen-swagger-type": "dtsgen --out src/types/swagger.d.ts --url https://traptitech.github.io/traQ/swagger.yaml && vue-cli-service lint --fix src/swagger.d.ts" }, "dependencies": { "dtsgenerator": "^2.0.7", diff --git a/src/shims-tsx.d.ts b/src/types/shims-tsx.d.ts similarity index 100% rename from src/shims-tsx.d.ts rename to src/types/shims-tsx.d.ts diff --git a/src/shims-vue.d.ts b/src/types/shims-vue.d.ts similarity index 100% rename from src/shims-vue.d.ts rename to src/types/shims-vue.d.ts From bfe3525eb0898098f52f9abeb2826200397bb149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Mon, 27 May 2019 15:21:01 +0900 Subject: [PATCH 07/12] =?UTF-8?q?store=E3=81=AETypeScript=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/client.ts | 18 +- src/store/general/index.ts | 1198 +++++++++++++++++++++++++++++++ src/store/general/type.ts | 394 ++++++++++ src/store/index.ts | 1174 +----------------------------- src/store/messageInput.ts | 32 - src/store/messageInput/index.ts | 60 ++ src/store/messageInput/type.ts | 38 + src/store/modal.ts | 164 ----- src/store/modal/index.ts | 145 ++++ src/store/modal/type.ts | 78 ++ src/store/pickerModal.ts | 47 -- src/store/pickerModal/index.ts | 41 ++ src/store/pickerModal/type.ts | 35 + src/types/vuex/impl.ts | 17 + src/types/vuex/index.d.ts | 2 + src/types/vuex/type.ts | 46 ++ 16 files changed, 2077 insertions(+), 1412 deletions(-) create mode 100644 src/store/general/index.ts create mode 100644 src/store/general/type.ts delete mode 100644 src/store/messageInput.ts create mode 100644 src/store/messageInput/index.ts create mode 100644 src/store/messageInput/type.ts delete mode 100644 src/store/modal.ts create mode 100644 src/store/modal/index.ts create mode 100644 src/store/modal/type.ts delete mode 100644 src/store/pickerModal.ts create mode 100644 src/store/pickerModal/index.ts create mode 100644 src/store/pickerModal/type.ts create mode 100644 src/types/vuex/impl.ts create mode 100644 src/types/vuex/index.d.ts create mode 100644 src/types/vuex/type.ts diff --git a/src/bin/client.ts b/src/bin/client.ts index 7ae902e4..6bca5bda 100644 --- a/src/bin/client.ts +++ b/src/bin/client.ts @@ -1,5 +1,5 @@ import axios from '@/bin/axios' -import { AxiosResponse, AxiosError, AxiosPromise } from 'axios' +import { AxiosResponse, AxiosPromise } from 'axios' import Schemas = Components.Schemas import Parameters = Components.Parameters @@ -151,9 +151,7 @@ const client = { }, getNotifiedChannels( userId: Parameters.UserIdInPath.UserID - ): AxiosPromise< - Paths.Users$UserIDNotification.Get.Responses.$200 | AxiosError - > { + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}/notification`) }, registerDevice( @@ -162,7 +160,7 @@ const client = { return axios.post(`/api/1.0/notification/device`, reqBody) }, getMyNotifiedChannels(): AxiosPromise< - Paths.UsersMeNotification.Get.Responses.$200 | AxiosError + Paths.UsersMeNotification.Get.Responses.$200 > { return axios.get('/api/1.0/users/me/notification') }, @@ -171,10 +169,10 @@ const client = { registerUser(reqBody: Paths.Users.Post.RequestBody): AxiosPromise { return axios.post(`/api/1.0/users`, reqBody) }, - getMembers(): AxiosPromise { + getMembers(): AxiosPromise { return axios.get(`/api/1.0/users`) }, - whoAmI(): AxiosPromise { + whoAmI(): AxiosPromise { return axios.get(`/api/1.0/users/me`) }, // deprecated @@ -201,7 +199,7 @@ const client = { }, getUserDetail( userId: Parameters.UserIdInPath.UserID - ): AxiosPromise { + ): AxiosPromise { return axios.get(`/api/1.0/users/${userId}`) }, loadDirectMessages( @@ -425,7 +423,9 @@ const client = { getHeartbeat(): AxiosPromise { return axios.get(`/api/1.0/heartbeat`) }, - postHeartbeat(reqBody: Paths.Heartbeat.Post.QueryParameters): AxiosPromise { + postHeartbeat( + reqBody: Paths.Heartbeat.Post.QueryParameters + ): AxiosPromise { return axios.post(`/api/1.0/heartbeat`, reqBody) }, diff --git a/src/store/general/index.ts b/src/store/general/index.ts new file mode 100644 index 00000000..72e74011 --- /dev/null +++ b/src/store/general/index.ts @@ -0,0 +1,1198 @@ +import Vue from 'vue' +import { Store, Getters, Mutations, Actions, RootState } from 'vuex' +import { S, G, M, A } from './type' +import client from '@/bin/client' +import indexedDB from '@/bin/indexeddb' +import stampCategorizer from '@/bin/stampCategorizer' +import { detectMentions } from '@/bin/utils' + +interface Window { + navigator: any +} +declare var window: Window + +const db = indexedDB.db + +const loadGeneralData = (dataName, webLoad, commit) => { + let loaded = false + const fetch = webLoad().then(res => { + loaded = true + commit(`set${dataName}Data`, res.data) + db.write('generalData', { type: dataName, data: res.data }) + }) + const getFromDB = db + .read('generalData', dataName) + .then(data => { + if (!loaded && data) { + commit(`set${dataName}Data`, data) + } else { + throw new Error('No data exists') + } + }) + .catch(async () => { + await fetch + }) + if ( + 'navigator' in window && + 'onLine' in window.navigator && + !window.navigator.onLine + ) { + return Promise.race([getFromDB]) + } else { + return Promise.race([getFromDB, fetch]) + } +} + +const stringSortGen = key => (lhs, rhs) => { + const ls = lhs[key].toLowerCase() + const rs = rhs[key].toLowerCase() + if (ls < rs) { + return -1 + } else if (ls > rs) { + return 1 + } else { + return 0 + } +} + +const state: S = { + loaded: false, + loadedComponent: false, + channelData: [], + channelMap: {}, + activityMessages: [], + activityChannelIdSet: new Set(), + openChannels: {}, + openUserLists: {}, + sidebarOpened: false, + titlebarExpanded: false, + memberData: [], + memberMap: {}, + groupData: [], + groupMap: {}, + stampData: [], + stampMap: {}, + stampCategolized: {}, + stampNameMap: {}, + stampHistory: [], + currentChannel: {}, + currentChannelUpdateDate: new Date(0), + clipedMessages: {}, + unreadChannelMap: {}, + staredChannels: [], + staredChannelMap: {}, + mutedChannels: [], + mutedChannelMap: {}, + messages: [], + channelTopicMap: {}, + currentChannelPinnedMessages: [], + currentChannelNotifications: [], + myNotifiedChannels: [], + myNotifiedChannelSet: new Set(), + me: null, + menuContent: 'Channels', + channelView: 'tree', + heartbeatStatus: { channelId: '', userStatuses: [] }, + baseURL: + process.env.NODE_ENV === 'development' + ? 'https://traq-dev.tokyotech.org' + : '', + files: [], + directMessageId: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa', + editing: false, + isActivePinnedModal: false, + openMode: 'particular', + openChannelId: '', + lastChannelId: '', + theme: 'light', + windowWidth: 0, + windowHeight: 0, + filterSubscribedActivity: true, + activeMessageContextMenu: '', + isOnline: true, + filterText: '', + isUnreadFiltered: false, + webhooks: [], + messageSendKey: '' +} + +const mutations: Mutations = { + openSidebar(state) { + state.sidebarOpened = true + }, + closeSidebar(state) { + state.sidebarOpened = false + }, + expandTitlebar(state) { + state.titlebarExpanded = true + }, + contractTitlebar(state) { + state.titlebarExpanded = false + }, + setMe(state, me) { + state.me = me + db.write('generalData', { type: 'me', data: me }) + }, + setChannelData(state, newChannelData) { + newChannelData.sort(stringSortGen('name')) + state.channelData = newChannelData + const map = {} + state.channelData.forEach(channel => { + if (channel.channelId) { + map[channel.channelId] = channel + } + }) + state.channelMap = map + state.channelData.forEach(channel => { + if (channel.children) { + channel.children.sort((lhs, rhs) => + stringSortGen('name')(state.channelMap[lhs], state.channelMap[rhs]) + ) + } + }) + }, + setMemberData(state, newMemberData) { + state.memberData = newMemberData + state.memberData.forEach(member => { + if (member.userId) { + state.memberMap[member.userId] = member + } + }) + }, + setGroupData(state, newGroupData) { + newGroupData.forEach(group => { + if (group.members) { + group.members = group.members.filter( + userId => state.memberMap[userId].accountStatus !== 0 + ) + } + }) + state.groupData = newGroupData + const map = {} + state.groupData.forEach(group => { + if (group.groupId) { + map[group.groupId] = group + } + }) + state.groupMap = map + }, + setStampData(state, newStampData) { + state.stampData = newStampData + state.stampCategolized = stampCategorizer(newStampData) + state.stampData.sort(stringSortGen('name')) + const stampMap = {} + const stampNameMap = {} + state.stampData.forEach(stamp => { + if (stamp.id && stamp.name) { + stampMap[stamp.id] = stamp + stampNameMap[stamp.name] = stamp + } + }) + state.stampMap = stampMap + state.stampNameMap = stampNameMap + }, + setStampHistory(state, stampHistory) { + state.stampHistory = stampHistory.map( + stamp => state.stampMap[stamp.stampId || ''] + ) + }, + addMessages(state, message) { + if (Array.isArray(message)) { + state.messages.push(...message) + } else { + state.messages.push(message) + } + db.write('channelMessages', { + channelId: state.currentChannel.channelId, + data: state.messages.slice(-50) + }) + }, + unshiftMessages(state, message) { + if (Array.isArray(message)) { + state.messages.unshift(...message) + } else { + state.messages.unshift(message) + } + }, + setMessages(state, messages) { + state.messages = messages + }, + updateMessage(state, message) { + const index = state.messages.findIndex( + mes => mes.messageId === message.messageId + ) + if (index === -1) { + return false + } + Vue.set(state.messages, index, message) + db.write('channelMessages', { + channelId: state.currentChannel.channelId, + data: state.messages.slice(-50) + }) + return true + }, + deleteMessage(state, messageId) { + state.messages = state.messages.filter( + message => message.messageId !== messageId + ) + db.write('channelMessages', { + channelId: state.currentChannel.channelId, + data: state.messages.slice(-50) + }) + }, + changeChannel(state, channel) { + if (!channel.channelId) return + state.currentChannel = channel + const unread = state.unreadChannelMap[channel.channelId] + if (unread && unread.since) { + state.currentChannelUpdateDate = new Date(unread.since) + } else { + state.currentChannelUpdateDate = new Date(0) + } + state.messages = [] + }, + loadStart(state) { + state.loaded = false + }, + loadEnd(state) { + state.loaded = true + }, + loadEndComponent(state) { + state.loadedComponent = true + }, + changeMenuContent(state, contentName) { + state.menuContent = contentName + }, + setClipedMessagesData(state, data) { + data.forEach(message => { + if (message.messageId) { + Vue.set(state.clipedMessages, message.messageId, message) + } + }) + }, + setUnreadMessagesData(state, data) { + const channelMap = {} + data.forEach(channel => { + if (channel.channelId) { + channelMap[channel.channelId] = channel + } + }) + state.unreadChannelMap = channelMap + }, + addUnreadMessage(state, message) { + if ( + (state.me && message.userId === state.me.userId) || + message.parentChannelId === undefined || + message.createdAt === undefined + ) { + return + } + let channel = state.unreadChannelMap[message.parentChannelId] + if (channel) { + channel.count += 1 + channel.updatedAt = message.createdAt + if (!channel.noticeable) { + channel.noticeable = detectMentions(message.content).some( + data => state.me && data.id === state.me.userId + ) + } + } else { + channel = { + channelId: message.parentChannelId, + count: 1, + since: message.createdAt, + updatedAt: message.createdAt, + noticeable: detectMentions(message.content).some( + data => state.me && data.id === state.me.userId + ) + } + } + Vue.set(state.unreadChannelMap, message.parentChannelId, channel) + }, + readChannel(state, channelId) { + if (state.unreadChannelMap[channelId]) { + Vue.delete(state.unreadChannelMap, channelId) + } + }, + setStaredChannelsData(state, data) { + state.staredChannels = data + const map = {} + state.staredChannels.forEach(channelId => { + map[channelId] = true + }) + state.staredChannelMap = map + }, + setMutedChannelsData(state, data) { + state.mutedChannels = data || [] + const map = {} + data.forEach(channelId => { + map[channelId] = true + }) + state.mutedChannelMap = map + }, + updateHeartbeatStatus(state, data) { + state.heartbeatStatus = data + }, + setChannelTopic(state, { data, channelId }) { + Vue.set(state.channelTopicMap, channelId, data) + }, + setCurrentChannelPinnedMessages(state, data) { + state.currentChannelPinnedMessages = data + }, + setCurrentChannelNotifications(state, data) { + state.currentChannelNotifications = data + }, + updateMessageStamp(state, data) { + const index = state.messages.findIndex(e => e.messageId === data.message_id) + if (index >= 0) { + const message = state.messages[index] + if (message.stampList) { + const userData = message.stampList.find( + e => e.userId === data.user_id && e.stampId === data.stamp_id + ) + if (userData) { + userData.count = data.count + } else { + message.stampList.push({ + userId: data.user_id, + stampId: data.stamp_id, + count: data.count, + createdAt: data.created_at + }) + } + } else { + message.stampList = [ + { + userId: data.user_id, + stampId: data.stamp_id, + count: data.count, + createdAt: data.created_at + } + ] + } + Vue.set(state.messages, index, message) + } + const pinnedIndex = state.currentChannelPinnedMessages.findIndex( + e => !!e.message && e.message.messageId === data.message_id + ) + if (pinnedIndex >= 0) { + const message = state.currentChannelPinnedMessages[pinnedIndex].message + if (!message) return + if (message.stampList) { + const userData = message.stampList.find( + e => e.userId === data.user_id && e.stampId === data.stamp_id + ) + if (userData) { + userData.count = data.count + } else { + message.stampList.push({ + userId: data.user_id, + stampId: data.stamp_id, + count: data.count + }) + } + } else { + message.stampList = [ + { + userId: data.user_id, + stampId: data.stamp_id, + count: data.count + } + ] + } + Vue.set( + state.currentChannelPinnedMessages, + pinnedIndex, + state.currentChannelPinnedMessages[pinnedIndex] + ) + } + }, + deleteMessageStamp(state, data) { + const index = state.messages.findIndex(e => e.messageId === data.message_id) + if (index >= 0) { + const message = state.messages[index] + if (message.stampList) { + const userDataIndex = message.stampList.findIndex( + e => e.userId === data.user_id && e.stampId === data.stamp_id + ) + if (userDataIndex >= 0) { + message.stampList = message.stampList.filter( + (_, i) => i !== userDataIndex + ) + Vue.set(state.messages, index, message) + } + } + } + const pinnedIndex = state.currentChannelPinnedMessages.findIndex( + e => !!e.message && e.message.messageId === data.message_id + ) + if (pinnedIndex >= 0) { + const message = state.currentChannelPinnedMessages[pinnedIndex].message + if (!message) return + if (message.stampList) { + const userDataIndex = message.stampList.findIndex( + e => e.userId === data.user_id && e.stampId === data.stamp_id + ) + if (userDataIndex >= 0) { + message.stampList = message.stampList.filter( + (_, i) => i !== userDataIndex + ) + Vue.set( + state.currentChannelPinnedMessages, + pinnedIndex, + state.currentChannelPinnedMessages[pinnedIndex] + ) + } + } + } + }, + setFiles(state, files) { + state.files = files + }, + clearFiles(state) { + state.files = [] + }, + setEditing(state, isEditing) { + state.editing = isEditing + }, + removeMessage(state, messageId) { + state.messages = state.messages.filter( + message => message.messageId !== messageId + ) + }, + setPinnedModal(state, isActive) { + state.isActivePinnedModal = isActive + }, + setUserOnline(state, { userId, isOnline }) { + const user = state.memberMap[userId] + user.isOnline = isOnline + Vue.set(state.memberMap, userId, user) + }, + setOpenChannels(state, data) { + state.openChannels = data + }, + setOpenUserLists(state, data) { + state.openUserLists = data + }, + setOpenUserList(state, { groupId, isOpen }) { + Vue.set(state.openUserLists, groupId, isOpen) + }, + setOpenChannel(state, { channelId, isOpen }) { + Vue.set(state.openChannels, channelId, isOpen) + }, + setOpenMode(state, mode) { + state.openMode = mode + }, + setOpenChannelId(state, channelId) { + state.openChannelId = channelId + }, + setLastChannelId(state, channelId) { + state.lastChannelId = channelId + }, + setTheme(state, themeName) { + state.theme = themeName + }, + setWindowSize(state, { windowWidth, windowHeight }) { + state.windowWidth = windowWidth + state.windowHeight = windowHeight + }, + setMyNotifiedChannels(state, channels) { + state.myNotifiedChannels = channels + const set = new Set() + channels.forEach(channelId => { + set.add(channelId) + }) + state.myNotifiedChannelSet = set + }, + setActivityMessages(state, data) { + state.activityMessages = data + state.activityChannelIdSet = new Set(data.map(m => m.parentChannelId || '')) + }, + addActivityMessages(state, data) { + if (!data.parentChannelId) return + if (state.activityChannelIdSet.has(data.parentChannelId)) { + const index = state.activityMessages.findIndex( + m => m.parentChannelId === data.parentChannelId + ) + state.activityMessages.splice(index, 1) + state.activityMessages = [data, ...state.activityMessages] + } else { + state.activityMessages = [data, ...state.activityMessages] + state.activityChannelIdSet.add(data.parentChannelId) + } + }, + setFilterSubscribedActivity(state, data) { + state.filterSubscribedActivity = data + }, + setChannelView(state, mode) { + state.channelView = mode + }, + setActiveMessageContextMenu(state, messageId) { + state.activeMessageContextMenu = messageId + }, + changeNetwork(state, condition) { + state.isOnline = condition + }, + setFilterText(state, filterText) { + state.filterText = filterText + }, + setIsUnreadFiltered(state, isUnreadFiltered) { + state.isUnreadFiltered = isUnreadFiltered + }, + setWebhooks(state, webhooks) { + state.webhooks = webhooks + }, + setMessageSendKey(state, key) { + state.messageSendKey = key + } +} +const getters: Getters = { + channelTopic(state) { + return channelId => state.channelTopicMap[channelId] || '' + }, + activeMessageContextMenu(state) { + return state.activeMessageContextMenu + }, + channelView(state) { + return state.channelView + }, + theme(state) { + return typeof state.theme === 'string' ? state.theme : 'light' + }, + windowWidth(state) { + return state.windowWidth + }, + windowHeight(state) { + return state.windowHeight + }, + childrenChannels(state) { + return parentId => + state.channelData.filter( + channel => channel.parent === parentId && channel.name !== '' + ) + }, + allChannels(state) { + return state.channelData.filter( + channel => + channel.parent !== 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa' && + channel.name !== '' + ) + }, + getChannelByName(state, getters) { + return channelName => { + const channelLevels = channelName.split('/') + let channel: Components.Schemas.Channel | undefined + let channelId = '' + channelLevels.forEach(name => { + const levelChannels = getters.childrenChannels(channelId) + channel = levelChannels.find(ch => ch.name === name) + if (channel === undefined) return null + channelId = channel.channelId || '' + }) + return channel + } + }, + getDirectMessageChannels(state) { + return state.channelData.filter(channel => channel.dm) + }, + getUserByName(state, getters) { + return userName => { + const user = getters.memberData.find(user => user.name === userName) + if (user) { + return user + } else { + return null + } + } + }, + getChannelPathById(state) { + return channelId => { + let current = state.channelMap[channelId] + let path = current.name + if (!current.parent) return path + let next = state.channelMap[current.parent] + while (next.name) { + path = next.name + '/' + path + current = next + if (!current.parent) return path + next = state.channelMap[current.parent] + } + return path + } + }, + getShortChannelPathById(state) { + return channelId => { + let current = state.channelMap[channelId] + let path = current.name + if (!current.parent) return path + let next = state.channelMap[current.parent] + while (next.name) { + path = next.name[0] + '/' + path + current = next + if (!current.parent) return path + next = state.channelMap[current.parent] + } + return path + } + }, + getFileDataById() { + return fileId => { + return client.getFileMeta(fileId) + } + }, + isPinned(state) { + return messageId => { + return state.currentChannelPinnedMessages.find( + pin => !!pin.message && pin.message.messageId === messageId + ) + } + }, + getMyId(state) { + return state.me && state.me.userId ? state.me.userId : '' + }, + getMyName(state) { + return state.me && state.me.name ? state.me.name : '' + }, + notificationsOnMembers(state) { + return state.currentChannelNotifications.map(id => state.memberMap[id]) + }, + notificationsOffMembers(state, getters) { + return getters.memberData.filter( + user => !state.currentChannelNotifications.find(id => id === user.userId) + ) + }, + getCurrentChannelUpdateDate(state) { + return state.currentChannelUpdateDate + }, + getChannelUnreadMessageNum(state) { + return channelId => { + if (!state.unreadChannelMap[channelId]) { + return 0 + } + return state.unreadChannelMap[channelId].count + } + }, + getChannelUnreadMessageSum(state, getters) { + return channelId => { + let sum = getters.getChannelUnreadMessageNum(channelId) + if ( + !state.channelMap[channelId] || + !state.channelMap[channelId].children || + !Array.isArray(state.channelMap[channelId].children) + ) { + return sum + } + return (state.channelMap[channelId].children || []) + .filter(childChannelId => childChannelId !== state.directMessageId) + .map(child => getters.getChannelUnreadMessageSum(child)) + .reduce((a, b) => a + b, sum) + } + }, + getUnreadMessageNum(state, getters) { + return Object.keys(state.unreadChannelMap).reduce((pre, channelId) => { + return pre + getters.getChannelUnreadMessageNum(channelId) + }, 0) + }, + getUnreadDirectMessagesSum(state, getters) { + return getters.getDirectMessageChannels.reduce((pre, channel) => { + return ( + pre + + (channel.channelId + ? getters.getChannelUnreadMessageNum(channel.channelId) + : 0) + ) + }, 0) + }, + getStaredChannels(state) { + const channels = state.staredChannels.map( + channelId => state.channelMap[channelId] + ) + channels.sort(stringSortGen('name')) + return channels + }, + getUserIdByDirectMessageChannel(state) { + return channel => { + if (!channel.dm) { + return '' + } + if (channel.member && channel.member.length === 1) { + return channel.member[0] + } else { + if (!channel.member) return '' + return channel.member.find( + userId => !!state.me && userId !== state.me.userId + ) + } + } + }, + deviceType(state) { + return state.windowWidth < 680 ? 'sp' : 'pc' + }, + isSidebarOpened(state) { + return state.sidebarOpened + }, + isTitlebarExpanded(state) { + return state.titlebarExpanded + }, + fileUrl(state) { + return fileId => { + return `${state.baseURL}/api/1.0/files/${fileId}` + } + }, + grades(state) { + return state.groupData.filter( + group => + group.type === 'grade' && group.members && group.members.length > 0 + ) + }, + sortedGrades(state, getters) { + const map = { + B: 3, + M: 2, + D: 1, + R: 0 + } + const f = s => { + return map[s[2]] * 100 + parseInt(s.substr(0, 2), 10) + } + const gradeReg = /^\d\d[BMDR]$/ + return getters.grades.sort((lhs, rhs) => { + if (!lhs.name || !rhs.name) return 0 + if (gradeReg.test(lhs.name) && gradeReg.test(rhs.name)) { + return f(rhs.name) - f(lhs.name) + } else if (gradeReg.test(lhs.name)) { + return -1 + } else if (gradeReg.test(rhs.name)) { + return 1 + } else { + if (lhs.name < rhs.name) { + return -1 + } else { + return 1 + } + } + }) + }, + memberData(state) { + return state.memberData.filter(user => user.accountStatus !== 0) + }, + nonBotUsers(state, getters) { + return getters.memberData.filter(user => !user.bot) + }, + gradeByUserMap(state, getters) { + const map = {} + getters.nonBotUsers.forEach(u => { + let gradeObj = getters.grades.find(g => { + if (!g.members) return false + return !!g.members.some(userId => userId === u.userId) + }) + if (u.userId) { + map[u.userId] = gradeObj || undefined + } + }) + return map + }, + getGroupByContent(state) { + return groupName => state.groupData.find(group => group.name === groupName) + }, + userDisplayName(state) { + return userId => state.memberMap[userId].displayName + }, + stampHistory(state) { + return state.stampHistory + }, + filteringUser(state) { + return users => + users.filter(userId => state.memberData[userId].accountStatus !== 0) + }, + sortByUserId(state) { + return userIds => + userIds + .map(userId => state.memberMap[userId]) + .sort(stringSortGen('name')) + .map(user => user.userId || '') + }, + filterText(state) { + return state.filterText + }, + isUnreadFiltered(state) { + return state.isUnreadFiltered + }, + getWebhookUserIds(state) { + return state.webhooks.map(w => w.botUserId || '') + } +} +const actions: Actions = { + whoAmI({ commit }) { + return client + .whoAmI() + .then(res => { + commit('setMe', res.data) + }) + .catch(() => { + commit('setMe', null) + }) + }, + getMessages({ state, commit, getters, dispatch }, update) { + const nowChannel = state.currentChannel + let loaded = false + const latest = state.messages.length === 0 || update + if (latest) { + db.read('channelMessages', nowChannel.channelId) + .then(data => { + if (!loaded && data) { + commit('setMessages', data) + } + }) + .catch(() => {}) + } + const loadedMessages = !nowChannel.dm + ? client.loadMessages(nowChannel.channelId || '', { + limit: 20, + offset: latest ? 0 : state.messages.length + }) + : client.loadDirectMessages( + getters.getUserIdByDirectMessageChannel(nowChannel) || '', + { + limit: 20, + offset: latest ? 0 : state.messages.length + } + ) + return loadedMessages.then(res => { + loaded = true + const messages = res.data.reverse() + dispatch('readMessages', nowChannel.channelId) + if (latest) { + db.write('channelMessages', { + channelId: nowChannel.channelId, + data: messages + }) + } + if (nowChannel === state.currentChannel) { + if (latest) { + commit('setMessages', messages) + return messages.length > 0 + } else { + commit('unshiftMessages', messages) + return messages.length > 0 + } + } + return false + }) + }, + async updateChannels({ commit }) { + return loadGeneralData('Channel', client.getChannels, commit) + }, + updateMembers({ commit }) { + return loadGeneralData('Member', client.getMembers, commit) + }, + updateGroups({ commit }) { + return loadGeneralData('Group', client.getAllGroups, commit) + }, + updateStamps({ commit }) { + return loadGeneralData('Stamp', client.getStamps, commit) + }, + getStampHistory({ commit }) { + return client.getStampHistory().then(res => { + commit('setStampHistory', res.data) + }) + }, + updateWebhooks({ commit }) { + return client.getWebhooks().then(res => commit('setWebhooks', res.data)) + }, + addStamp({ commit, state }, stampId) { + return client.getStampDetail(stampId).then(res => { + commit('setStampData', state.stampData.concat([res.data])) + }) + }, + updateClipedMessages({ commit }) { + return loadGeneralData('ClipedMessages', client.getAllClipMessages, commit) + }, + updateUnreadMessages({ commit }) { + return loadGeneralData('UnreadMessages', client.getUnreadChannels, commit) + }, + updateStaredChannels({ commit }) { + return loadGeneralData('StaredChannels', client.getStaredChannels, commit) + }, + updateMutedChannels({ commit }) { + return loadGeneralData('MutedChannels', client.getMutedChannels, commit) + }, + getChannelTopic({ commit }, channelId) { + return client.getChannelTopic(channelId).then(res => { + commit('setChannelTopic', { + data: res.data.text ? res.data.text : '', + channelId + }) + }) + }, + getCurrentChannelPinnedMessages({ commit }, channelId) { + return client.getPinnedMessages(channelId).then(res => { + commit('setCurrentChannelPinnedMessages', res.data) + }) + }, + getCurrentChannelNotifications({ commit }, channelId) { + return client.getNotifications(channelId).then(res => { + commit('setCurrentChannelNotifications', res.data) + }) + }, + addChannel({ state, commit }, channelId) { + return client.getChannelInfo(channelId).then(res => { + const parent = state.channelData.find( + channel => channel.channelId === res.data.parent + ) + if (parent) { + if (parent.children) { + parent.children.push(channelId) + } else { + parent.children = [channelId] + } + } + commit('setChannelData', [res.data].concat(state.channelData)) + }) + }, + deleteChannel({ state, commit }, channelId) { + const parent = state.channelData.find( + channel => channel.channelId === state.channelMap[channelId].parent + ) + if (parent && parent.children) { + parent.children = parent.children.filter(c => c !== channelId) + } + commit( + 'setChannelData', + state.channelData.filter(channel => channel.channelId !== channelId) + ) + }, + updateChannel({ state, commit }, channelId) { + return client.getChannelInfo(channelId).then(res => { + commit( + 'setChannelData', + [res.data].concat( + state.channelData.filter(channel => channel.channelId !== channelId) + ) + ) + }) + }, + checkPinnedMessage({ state, dispatch }, messageId) { + if ( + state.currentChannelPinnedMessages.find( + pin => !!pin.message && pin.message.messageId === messageId + ) + ) { + dispatch( + 'getCurrentChannelPinnedMessages', + state.currentChannel.channelId + ) + } + }, + updateUserOnline({ state, commit, rootState }, { userId, isOnline }) { + commit('setUserOnline', { userId, isOnline }) + if ( + rootState.modal && + rootState.modal.data && + rootState.modal.data.userId === userId + ) { + commit('modal/setModalData', state.memberMap[userId]) + } + }, + updateChannelOpen({ state, commit }, { channelId, isOpen }) { + commit('setOpenChannel', { channelId, isOpen }) + return db.write('generalData', { + type: 'openChannels', + data: state.openChannels + }) + }, + updateUserListOpen({ state, commit }, { groupId, isOpen }) { + commit('setOpenUserList', { groupId, isOpen }) + return db.write('generalData', { + type: 'openUserLists', + data: state.openUserLists + }) + }, + loadSetting({ dispatch }) { + return Promise.all([ + dispatch('loadOpenMode'), + dispatch('loadOpenChannelId'), + dispatch('loadLastChannelId'), + dispatch('loadTheme'), + dispatch('loadOpenChannels'), + dispatch('loadFilterSubscribedActivity'), + dispatch('loadOpenUserLists'), + dispatch('loadChannelView'), + dispatch('loadMessageSendKey') + ]) + }, + loadOpenMode({ commit, dispatch }) { + return db + .read('browserSetting', 'openMode') + .then(data => { + commit('setOpenMode', data) + }) + .catch(async () => { + await dispatch('updateOpenMode', 'particular') + }) + }, + loadOpenChannelId({ commit, dispatch, getters }) { + return db + .read('browserSetting', 'openChannelId') + .then(data => { + commit('setOpenChannelId', data) + }) + .catch(async () => { + await dispatch( + 'updateOpenChannelId', + (getters.getChannelByName('general') || { channelId: '' }).channelId + ) + }) + }, + loadLastChannelId({ commit, dispatch, getters }) { + return db + .read('browserSetting', 'lastChannelId') + .then(data => { + commit('setLastChannelId', data) + }) + .catch(async () => { + await dispatch( + 'updateLastChannelId', + (getters.getChannelByName('general') || { channelId: '' }).channelId + ) + }) + }, + loadTheme({ commit, dispatch }) { + return db + .read('browserSetting', 'theme') + .then(data => { + commit('setTheme', data) + }) + .catch(async () => { + await dispatch('updateTheme', 'light') + }) + }, + loadOpenChannels({ commit }) { + return db + .read('generalData', 'openChannels') + .then(data => { + commit('setOpenChannels', data || {}) + }) + .catch(() => { + commit('setOpenChannels', {}) + }) + }, + loadOpenUserLists({ commit }) { + return db + .read('generalData', 'openUserLists') + .then(data => { + commit('setOpenUserLists', data || {}) + }) + .catch(() => { + commit('setOpenUserLists', {}) + }) + }, + loadMessageSendKey({ commit, dispatch }) { + return db + .read('browserSetting', 'messageSendKey') + .then(data => { + commit('setMessageSendKey', data) + }) + .catch(async () => { + await dispatch('updateMessageSendKey', 'modifier') + }) + }, + updateOpenMode({ commit }, mode) { + commit('setOpenMode', mode) + return db.write('browserSetting', { type: 'openMode', data: mode }) + }, + updateOpenChannelId({ commit }, channelId) { + commit('setOpenChannelId', channelId) + return db.write('browserSetting', { + type: 'openChannelId', + data: channelId + }) + }, + updateLastChannelId({ commit }, channelId) { + commit('setLastChannelId', channelId) + return db.write('browserSetting', { + type: 'lastChannelId', + data: channelId + }) + }, + updateTheme({ commit }, themeName) { + commit('setTheme', themeName) + return db.write('browserSetting', { type: 'theme', data: themeName }) + }, + async updateChannelActivity({ state, commit }) { + const filter = state.filterSubscribedActivity || false + const res = await client.getLatestMessages({ + limit: 50, + subscribe: filter + }) + commit('setActivityMessages', res.data) + }, + async updateMyNotifiedChannels({ commit }) { + const res = await client.getMyNotifiedChannels() + const data = res.data + if (!data) return + commit('setMyNotifiedChannels', data) + }, + async updateCurrentChannelNotifications({ state, dispatch }, { on, off }) { + await client.changeNotifications(state.currentChannel.channelId || '', { + on: on || [], + off: off || [] + }) + await dispatch( + 'getCurrentChannelNotifications', + state.currentChannel.channelId + ) + }, + async updateCurrentChannelTopic({ state, dispatch }, text) { + const channelId = state.currentChannel.channelId || '' + await client.changeChannelTopic(channelId, { text }) + await dispatch('getChannelTopic', channelId) + }, + updateFilterSubscribedActivity({ commit }, filter) { + commit('setFilterSubscribedActivity', filter) + return db.write('browserSetting', { + type: 'filterSubscribedActivity', + data: filter + }) + }, + loadFilterSubscribedActivity({ commit, dispatch }) { + return db + .read('browserSetting', 'filterSubscribedActivity') + .then(data => { + commit('setFilterSubscribedActivity', data) + }) + .catch(async () => { + await dispatch('updateFilterSubscribedActivity', true) + }) + }, + readMessages({ dispatch }, channelId) { + return client.readMessages(channelId).then(() => { + dispatch('updateUnreadMessages') + }) + }, + updateChannelView({ commit }, mode) { + commit('setChannelView', mode) + return db.write('browserSetting', { type: 'channelView', data: mode }) + }, + loadChannelView({ commit, dispatch }) { + return db + .read('browserSetting', 'channelView') + .then(data => { + commit('setChannelView', data) + }) + .catch(async () => { + await dispatch('updateChannelView', 'tree') + }) + }, + updateMessageSendKey({ commit }, key) { + commit('setMessageSendKey', key) + return db.write('browserSetting', { type: 'messageSendKey', data: key }) + } +} + +export default { + state, + getters, + mutations, + actions +} diff --git a/src/store/general/type.ts b/src/store/general/type.ts new file mode 100644 index 00000000..e45ac2e1 --- /dev/null +++ b/src/store/general/type.ts @@ -0,0 +1,394 @@ +import Schemas = Components.Schemas +import { AxiosPromise } from 'axios' + +export interface S { + loaded: boolean + loadedComponent: boolean + channelData: Schemas.ChannelList + channelMap: { [channelId: string]: Schemas.Channel } + activityMessages: Schemas.MessageList + activityChannelIdSet: Set + openChannels: { [channelId: string]: boolean } + openUserLists: { [grade: string]: boolean } + sidebarOpened: boolean + titlebarExpanded: boolean + memberData: Schemas.UserList + memberMap: { [userId: string]: Schemas.User } + groupData: (Schemas.UserGroup & { type: string })[] //TODO + groupMap: { [groupId: string]: Schemas.UserGroup & { type: string } } + stampData: Schemas.Stamp[] + stampMap: { [stampId: string]: Schemas.Stamp } + stampCategolized: { [order: number]: any } // TODO + stampNameMap: { [stampId: string]: Schemas.Stamp } + stampHistory: Schemas.Stamp[] + currentChannel: Schemas.Channel + currentChannelUpdateDate: Date + clipedMessages: { [messageId: string]: Schemas.Message } + unreadChannelMap: { + [channelId: string]: { + channelId: string + count: number + noticeable: boolean + since: string + updatedAt: string + } + } + staredChannels: string[] + staredChannelMap: { [channelId: string]: Schemas.Channel } + mutedChannels: string[] + mutedChannelMap: { [channelId: string]: Schemas.Channel } + messages: Schemas.MessageList + channelTopicMap: { [channelId: string]: string } + currentChannelPinnedMessages: Schemas.Pin[] + currentChannelNotifications: string[] + myNotifiedChannels: string[] + myNotifiedChannelSet: Set + me: null | Schemas.UserDetail + menuContent: string + channelView: string + heartbeatStatus: { + channelId: string + userStatuses: Schemas.UserHeartbeatStatus[] + } + baseURL: string + files: any[] + directMessageId: string + editing: boolean + isActivePinnedModal: boolean + openMode: string + openChannelId: string + lastChannelId: string + theme: string + windowWidth: number + windowHeight: number + filterSubscribedActivity: boolean + activeMessageContextMenu: string + isOnline: boolean + filterText: string + isUnreadFiltered: boolean + webhooks: Schemas.Webhook[] + messageSendKey: string +} + +export interface G { + channelTopic: (channelId: string) => string + activeMessageContextMenu: string + channelView: string + theme: string + windowWidth: number + windowHeight: number + childrenChannels: (channelId: string) => Schemas.ChannelList + allChannels: Schemas.ChannelList + getChannelByName: (channelName: string) => Schemas.Channel | undefined + getDirectMessageChannels: Schemas.ChannelList + getUserByName: (userName: string) => Schemas.User | null + getChannelPathById: (channelId: string) => string | undefined + getShortChannelPathById: (channelId: string) => string | undefined + getFileDataById: (fileId: string) => AxiosPromise + isPinned: (messageId: string) => Schemas.Pin | undefined + getMyId: string + getMyName: string + notificationsOnMembers: Schemas.UserList + notificationsOffMembers: Schemas.UserList + getCurrentChannelUpdateDate: Date + getChannelUnreadMessageNum: (channelId: string) => number + getChannelUnreadMessageSum: (channelId: string) => number + getUnreadMessageNum: number + getUnreadDirectMessagesSum: number + getStaredChannels: Schemas.ChannelList + getUserIdByDirectMessageChannel: ( + channel: Schemas.Channel + ) => string | undefined + deviceType: string + isSidebarOpened: boolean + isTitlebarExpanded: boolean + fileUrl: (fileId: string) => string + grades: Schemas.UserGroup[] + sortedGrades: Schemas.UserGroup[] + memberData: Schemas.UserList + nonBotUsers: Schemas.UserList + gradeByUserMap: { [userId: string]: string | undefined } + getGroupByContent: ( + group: string + ) => Schemas.UserGroup & { type: string } | undefined // TODO + userDisplayName: (userId: string) => string | undefined + stampHistory: Schemas.Stamp[] + filteringUser: (users: string[]) => string[] + sortByUserId: (userIds: string[]) => string[] + filterText: string + isUnreadFiltered: boolean + getWebhookUserIds: string[] +} + +export interface RG { + channelTopic: G['channelTopic'] + activeMessageContextMenu: G['activeMessageContextMenu'] + channelView: G['channelView'] + theme: G['theme'] + windowWidth: G['windowWidth'] + windowHeight: G['windowHeight'] + childrenChannels: G['childrenChannels'] + allChannels: G['allChannels'] + getChannelByName: G['getChannelByName'] + getDirectMessageChannels: G['getDirectMessageChannels'] + getUserByName: G['getUserByName'] + getChannelPathById: G['getChannelPathById'] + getShortChannelPathById: G['getShortChannelPathById'] + getFileDataById: G['getFileDataById'] + isPinned: G['isPinned'] + getMyId: G['getMyId'] + getMyName: G['getMyName'] + notificationsOnMembers: G['notificationsOnMembers'] + notificationsOffMembers: G['notificationsOffMembers'] + getCurrentChannelUpdateDate: G['getCurrentChannelUpdateDate'] + getChannelUnreadMessageNum: G['getChannelUnreadMessageNum'] + getChannelUnreadMessageSum: G['getChannelUnreadMessageSum'] + getUnreadMessageNum: G['getUnreadMessageNum'] + getUnreadDirectMessagesSum: G['getUnreadDirectMessagesSum'] + getStaredChannels: G['getStaredChannels'] + getUserIdByDirectMessageChannel: G['getUserIdByDirectMessageChannel'] + deviceType: G['deviceType'] + isSidebarOpened: G['isSidebarOpened'] + isTitlebarExpanded: G['isTitlebarExpanded'] + fileUrl: G['fileUrl'] + grades: G['grades'] + sortedGrades: G['sortedGrades'] + memberData: G['memberData'] + nonBodUsers: G['nonBotUsers'] + gradeByUserMap: G['gradeByUserMap'] + getGroupByContent: G['getGroupByContent'] + userDisplayName: G['userDisplayName'] + stampHistory: G['stampHistory'] + filteringUser: G['filteringUser'] + sortByUserId: G['sortByUserId'] + filterText: G['filterText'] + isUnreadFiltered: G['isUnreadFiltered'] + getWebhookUserIds: G['getWebhookUserIds'] +} + +export interface M { + openSidebar: void + closeSidebar: void + expandTitlebar: void + contractTitlebar: void + setMe: Schemas.UserDetail | null + setChannelData: Schemas.ChannelList + setMemberData: Schemas.UserList + setGroupData: (Schemas.UserGroup & { type: string })[] + setStampData: Schemas.Stamp[] + setStampHistory: { + stampId?: string | undefined + datetime?: string | undefined + }[] + addMessages: Schemas.MessageList + unshiftMessages: Schemas.MessageList + setMessages: Schemas.MessageList + updateMessage: Schemas.Message + deleteMessage: string + changeChannel: Schemas.Channel + loadStart: void + loadEnd: void + loadEndComponent: void + changeMenuContent: string + setClipedMessagesData: Schemas.MessageList + setUnreadMessagesData: Schemas.ChannelList + addUnreadMessage: Schemas.Message + readChannel: string + setStaredChannelsData: string[] + setMutedChannelsData: string[] + updateHeartbeatStatus: { + channelId: string + userStatuses: Schemas.UserHeartbeatStatus[] + } + setChannelTopic: { channelId: string; data: string } + setCurrentChannelPinnedMessages: Schemas.MessageList + setCurrentChannelNotifications: string[] + updateMessageStamp: { + message_id: string + user_id: string + stamp_id: string + count: number + created_at: string + } + deleteMessageStamp: { message_id: string; user_id: string; stamp_id: string } + setFiles: any[] + clearFiles: void + setEditing: boolean + removeMessage: string + setPinnedModal: boolean + setUserOnline: { userId: string; isOnline: boolean } + setOpenChannels: { [channelId: string]: boolean } + setOpenUserLists: { [groupId: string]: boolean } + setOpenUserList: { groupId: string; isOpen: boolean } + setOpenChannel: { channelId: string; isOpen: boolean } + setOpenMode: string + setOpenChannelId: string + setLastChannelId: string + setTheme: string + setWindowSize: { windowWidth: number; windowHeight: number } + setMyNotifiedChannels: string[] + setActivityMessages: Schemas.MessageList + addActivityMessages: Schemas.Message + setFilterSubscribedActivity: boolean + setChannelView: string + setActiveMessageContextMenu: string + changeNetwork: boolean + setFilterText: string + setIsUnreadFiltered: boolean + setWebhooks: Schemas.Webhook[] + setMessageSendKey: string +} + +export interface RM { + openSidebar: M['openSidebar'] + closeSidebar: M['closeSidebar'] + expandTitlebar: M['expandTitlebar'] + contractTitlebar: M['contractTitlebar'] + setMe: M['setMe'] + setChannelData: M['setChannelData'] + setMemberData: M['setMemberData'] + setStampData: M['setStampData'] + setStampHistory: M['setStampHistory'] + addMessages: M['addMessages'] + unshiftMessages: M['unshiftMessages'] + setMessages: M['setMessages'] + updateMessage: M['updateMessage'] + deleteMessage: M['deleteMessage'] + changeChannel: M['changeChannel'] + loadStart: M['loadStart'] + loadEnd: M['loadEnd'] + loadEndComponent: M['loadEndComponent'] + changeMenuContent: M['changeMenuContent'] + setClipedMessagesData: M['setClipedMessagesData'] + setUnreadMessagesData: M['setUnreadMessagesData'] + addUnreadMessage: M['addUnreadMessage'] + readChannel: M['readChannel'] + setStaredChannelsData: M['setStaredChannelsData'] + setMutedChannelsData: M['setMutedChannelsData'] + updateHeartbeatStatus: M['updateHeartbeatStatus'] + setChannelTopic: M['setChannelTopic'] + setCurrentChannelPinnedMessages: M['setCurrentChannelPinnedMessages'] + setCurrentChannelNotifications: M['setCurrentChannelNotifications'] + updateMessageStamp: M['updateMessageStamp'] + deleteMessageStamp: M['deleteMessageStamp'] + setFiles: M['setFiles'] + clearFiles: M['clearFiles'] + setEditing: M['setEditing'] + removeMessage: M['removeMessage'] + setPinnedModal: M['setPinnedModal'] + setUserOnline: M['setUserOnline'] + setOpenMode: M['setOpenMode'] + setOpenChannels: M['setOpenChannels'] + setOpenUserList: M['setOpenUserList'] + setOpenChannelId: M['setOpenChannelId'] + setLastChannelId: M['setLastChannelId'] + setTheme: M['setTheme'] + setWindowSize: M['setWindowSize'] + setMyNotifiedChannels: M['setMyNotifiedChannels'] + setActivityMessages: M['setActivityMessages'] + addActivityMessages: M['addActivityMessages'] + setFilterSubscribedActivity: M['setFilterSubscribedActivity'] + setChannelView: M['setChannelView'] + setActiveMessageContextMenu: M['setActiveMessageContextMenu'] + changeNetwork: M['changeNetwork'] + setFilterText: M['setFilterText'] + setIsUnreadFiltered: M['setIsUnreadFiltered'] + setWebhooks: M['setWebhooks'] + setMessageSendKey: M['setMessageSendKey'] +} + +export interface A { + whoAmI: void + getMessages: boolean + updateChannels: void + updateMembers: void + updateGroups: void + updateStamps: void + getStampHistory: void + updateWebhooks: void + addStamp: string + updateClipedMessages: void + updateUnreadMessages: void + updateStaredChannels: void + updateMutedChannels: void + getChannelTopic: string + getCurrentChannelPinnedMessages: string + getCurrentChannelNotifications: string + addChannel: string + deleteChannel: string + updateChannel: string + checkPinnedMessage: string + updateUserOnline: { userId: string; isOnline: boolean } + updateChannelOpen: { channelId: string; isOpen: boolean } + updateUserListOpen: { groupId: string; isOpen: boolean } + loadSetting: void + loadOpenMode: void + loadOpenChannelId: void + loadLastChannelId: void + loadTheme: void + loadOpenChannels: void + loadOpenUserLists: void + loadMessageSendKey: void + updateOpenMode: string + updateOpenChannelId: string + updateLastChannelId: string + updateTheme: string + updateChannelActivity: void + updateMyNotifiedChannels: void + updateCurrentChannelNotifications: { on: string[]; off: string[] } + updateCurrentChannelTopic: string + updateFilterSubscribedActivity: boolean + loadFilterSubscribedActivity: void + readMessages: string + updateChannelView: string + loadChannelView: void + updateMessageSendKey: string +} + +export interface RA { + whoAmI: A['whoAmI'] + getMessages: A['getMessages'] + updateChannels: A['updateChannels'] + updateMembers: A['updateMembers'] + updateGroups: A['updateGroups'] + updateStamps: A['updateStamps'] + getStampHistory: A['getStampHistory'] + updateWebhooks: A['updateWebhooks'] + addStamp: A['addStamp'] + updateClipedMessages: A['updateClipedMessages'] + updateUnreadMessages: A['updateUnreadMessages'] + updateStaredChannels: A['updateStaredChannels'] + updateMutedChannels: A['updateMutedChannels'] + getChannelTopic: A['getChannelTopic'] + getCurrentChannelPinnedMessages: A['getCurrentChannelPinnedMessages'] + getCurrentChannelNotifications: A['getCurrentChannelNotifications'] + addChannel: A['addChannel'] + deleteChannel: A['deleteChannel'] + updateChannel: A['updateChannel'] + checkPinnedMessage: A['checkPinnedMessage'] + updateUserOnline: A['updateUserOnline'] + updateChannelOpen: A['updateChannelOpen'] + updateUserListOpen: A['updateUserListOpen'] + loadSetting: A['loadSetting'] + loadOpenMode: A['loadOpenMode'] + loadOpenChannelId: A['loadOpenChannelId'] + loadLastChannelId: A['loadLastChannelId'] + loadTheme: A['loadTheme'] + loadOpenChannels: A['loadOpenChannels'] + loadOpenUserLists: A['loadOpenUserLists'] + loadMessageSendKey: A['loadMessageSendKey'] + updateOpenMode: A['updateOpenMode'] + updateOpenChannelId: A['updateOpenChannelId'] + updateLastChannelId: A['updateLastChannelId'] + updateTheme: A['updateTheme'] + updateChannelActivity: A['updateChannelActivity'] + updateMyNotifiedChannels: A['updateMyNotifiedChannels'] + updateCurrentChannelNotifications: A['updateCurrentChannelNotifications'] + updateCurrentChannelTopic: A['updateCurrentChannelTopic'] + updateFilterSubscribedActivity: A['updateFilterSubscribedActivity'] + loadFilterSubscribedActivity: A['loadFilterSubscribedActivity'] + readMessages: A['readMessages'] + updateChannelView: A['updateChannelView'] + loadChannelView: A['loadChannelView'] + updateMessageSendKey: A['updateMessageSendKey'] +} diff --git a/src/store/index.ts b/src/store/index.ts index 5cd06da4..25cdb953 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,1172 +1,26 @@ import Vue from 'vue' -import Vuex from 'vuex' -import client from '@/bin/client' -import indexedDB from '@/bin/indexeddb' -import stampCategorizer from '@/bin/stampCategorizer' -import { detectMentions } from '@/bin/utils' +import Vuex, { Store } from 'vuex' +import general from './general' import modal from './modal' -import pickerModal from './pickerModal' import messageInput from './messageInput' - -interface Window { - openUserModal: (string) => void - openGroupModal: (string) => void - navigator: any -} -declare var window: Window - -const db = indexedDB.db +import pickerModal from './pickerModal' Vue.use(Vuex) -const loadGeneralData = (dataName, webLoad, commit) => { - let loaded = false - const fetch = webLoad().then(res => { - loaded = true - commit(`set${dataName}Data`, res.data) - db.write('generalData', { type: dataName, data: res.data }) - }) - const getFromDB = db - .read('generalData', dataName) - .then(data => { - if (!loaded && data) { - commit(`set${dataName}Data`, data) - } else { - throw new Error('No data exists') - } - }) - .catch(async () => { - await fetch - }) - if ( - 'navigator' in window && - 'onLine' in window.navigator && - !window.navigator.onLine - ) { - return Promise.race([getFromDB]) - } else { - return Promise.race([getFromDB, fetch]) - } -} - -const stringSortGen = key => (lhs, rhs) => { - const ls = lhs[key].toLowerCase() - const rs = rhs[key].toLowerCase() - if (ls < rs) { - return -1 - } else if (ls > rs) { - return 1 - } else { - return 0 - } -} - -const store = new Vuex.Store({ +const store = new Store({ + ...general, modules: { modal, - pickerModal, - messageInput - }, - state: { - loaded: false, - loadedComponent: false, - channelData: [], - channelMap: {}, - activityMessages: [], - activityChannelIdSet: new Set(), - openChannels: {}, - openUserLists: {}, - sidebarOpened: false, - titlebarExpanded: false, - memberData: [], - memberMap: {}, - groupData: [], - groupMap: {}, - stampData: [], - stampMap: {}, - stampCategolized: {}, - stampNameMap: [], - stampHistory: [], - currentChannel: {}, - currentChannelUpdateDate: new Date(0), - clipedMessages: {}, - unreadChannelMap: {}, - staredChannels: [], - staredChannelMap: {}, - mutedChannels: [], - mutedChannelMap: {}, - messages: [], - channelTopicMap: {}, - currentChannelPinnedMessages: [], - currentChannelNotifications: [], - myNotifiedChannels: [], - myNotifiedChannelSet: new Set(), - me: null, - menuContent: 'Channels', - channelView: 'tree', - heartbeatStatus: { userStatuses: [] }, - baseURL: - process.env.NODE_ENV === 'development' - ? 'https://traq-dev.tokyotech.org' - : '', - files: [], - userModal: null, - tagModal: null, - directMessageId: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa', - editing: false, - isActivePinnedModal: false, - openMode: 'particular', - openChannelId: '', - lastChannelId: '', - theme: 'light', - windowWidth: 0, - windowHeight: 0, - filterSubscribedActivity: true, - activeMessageContextMenu: '', - isOnline: true, - filterText: '', - isUnreadFiltered: false, - webhooks: [], - messageSendKey: '' - }, - mutations: { - openSidebar(state) { - state.sidebarOpened = true - }, - closeSidebar(state) { - state.sidebarOpened = false - }, - expandTitlebar(state) { - state.titlebarExpanded = true - }, - contractTitlebar(state) { - state.titlebarExpanded = false - }, - setMe(state, me) { - state.me = me - db.write('generalData', { type: 'me', data: me }) - }, - setChannelData(state, newChannelData) { - newChannelData.sort(stringSortGen('name')) - state.channelData = newChannelData - const map = {} - state.channelData.forEach(channel => { - map[channel.channelId] = channel - }) - state.channelMap = map - state.channelData.forEach(channel => { - if (channel.children) { - channel.children.sort((lhs, rhs) => - stringSortGen('name')(state.channelMap[lhs], state.channelMap[rhs]) - ) - } - }) - }, - setMemberData(state, newMemberData) { - state.memberData = newMemberData - state.memberData.forEach(member => { - state.memberMap[member.userId] = member - }) - }, - setGroupData(state, newGroupData) { - newGroupData.forEach(group => { - group.members = group.members.filter( - userId => state.memberMap[userId].accountStatus !== 0 - ) - }) - state.groupData = newGroupData - const map = {} - state.groupData.forEach(group => { - map[group.groupId] = group - }) - state.groupMap = map - }, - setStampData(state, newStampData) { - state.stampData = newStampData - state.stampCategolized = stampCategorizer(newStampData) - state.stampData.sort(stringSortGen('name')) - const stampMap = {} - const stampNameMap = {} - state.stampData.forEach(stamp => { - stampMap[stamp.id] = stamp - stampNameMap[stamp.name] = stamp - }) - state.stampMap = stampMap - state.stampNameMap = stampNameMap - }, - setStampHistory(state, stampHistory) { - state.stampHistory = stampHistory.map( - stamp => state.stampMap[stamp.stampId] - ) - }, - addMessages(state, message) { - if (Array.isArray(message)) { - state.messages.push(...message) - } else { - state.messages.push(message) - } - db.write('channelMessages', { - channelId: state.currentChannel.channelId, - data: state.messages.slice(-50) - }) - }, - unshiftMessages(state, message) { - if (Array.isArray(message)) { - state.messages.unshift(...message) - } else { - state.messages.unshift(message) - } - }, - setMessages(state, messages) { - state.messages = messages - }, - updateMessage(state, message) { - const index = state.messages.findIndex( - mes => mes.messageId === message.messageId - ) - if (index === -1) { - return false - } - Vue.set(state.messages, index, message) - db.write('channelMessages', { - channelId: state.currentChannel.channelId, - data: state.messages.slice(-50) - }) - return true - }, - deleteMessage(state, messageId) { - state.messages = state.messages.filter( - message => message.messageId !== messageId - ) - db.write('channelMessages', { - channelId: state.currentChannel.channelId, - data: state.messages.slice(-50) - }) - }, - changeChannel(state, channel) { - state.currentChannel = channel - const unread = state.unreadChannelMap[channel.channelId] - if (unread) { - state.currentChannelUpdateDate = new Date(unread.since) - } else { - state.currentChannelUpdateDate = new Date(0) - } - state.messages = [] - }, - loadStart(state) { - state.loaded = false - }, - loadEnd(state) { - state.loaded = true - }, - loadEndComponent(state) { - state.loadedComponent = true - }, - changeMenuContent(state, contentName) { - state.menuContent = contentName - }, - setClipedMessagesData(state, data) { - data.forEach(message => { - Vue.set(state.clipedMessages, message.messageId, message) - }) - }, - setUnreadMessagesData(state, data) { - const channelMap = {} - data.forEach(channel => { - channelMap[channel.channelId] = channel - }) - state.unreadChannelMap = channelMap - }, - addUnreadMessage(state, message) { - if (message.userId === state.me.userId) { - return - } - let channel = state.unreadChannelMap[message.parentChannelId] - if (channel) { - channel.count += 1 - channel.updatedAt = message.createdAt - if (!channel.noticeable) { - channel.noticeable = detectMentions(message.content).some( - data => data.id === state.me.userId - ) - } - } else { - channel = { - channelId: message.parentChannelId, - count: 1, - since: message.createdAt, - updatedAt: message.createdAt, - noticeable: detectMentions(message.content).some( - data => data.id === state.me.userId - ) - } - } - Vue.set(state.unreadChannelMap, message.parentChannelId, channel) - }, - readChannel(state, channelId) { - if (state.unreadChannelMap[channelId]) { - Vue.delete(state.unreadChannelMap, channelId) - } - }, - setStaredChannelsData(state, data) { - state.staredChannels = data - const map = {} - state.staredChannels.forEach(channelId => { - map[channelId] = true - }) - state.staredChannelMap = map - }, - setMutedChannelsData(state, data) { - state.mutedChannels = data || [] - const map = {} - data.forEach(channelId => { - map[channelId] = true - }) - state.mutedChannelMap = map - }, - updateHeartbeatStatus(state, data) { - state.heartbeatStatus = data - }, - setChannelTopic(state, { data, channelId }) { - Vue.set(state.channelTopicMap, channelId, data) - }, - setCurrentChannelPinnedMessages(state, data) { - state.currentChannelPinnedMessages = data - }, - setCurrentChannelNotifications(state, data) { - state.currentChannelNotifications = data - }, - updateMessageStamp(state, data) { - const index = state.messages.findIndex( - e => e.messageId === data.message_id - ) - if (index >= 0) { - const message = state.messages[index] - if (message.stampList) { - const userData = message.stampList.find( - e => e.userId === data.user_id && e.stampId === data.stamp_id - ) - if (userData) { - userData.count = data.count - } else { - message.stampList.push({ - userId: data.user_id, - stampId: data.stamp_id, - count: data.count, - createdAt: data.created_at - }) - } - } else { - message.stampList = [ - { - userId: data.user_id, - stampId: data.stamp_id, - count: data.count, - createdAt: data.created_at - } - ] - } - Vue.set(state.messages, index, message) - } - const pinnedIndex = state.currentChannelPinnedMessages.findIndex( - e => e.message.messageId === data.message_id - ) - if (pinnedIndex >= 0) { - const message = state.currentChannelPinnedMessages[pinnedIndex].message - if (message.stampList) { - const userData = message.stampList.find( - e => e.userId === data.user_id && e.stampId === data.stamp_id - ) - if (userData) { - userData.count = data.count - } else { - message.stampList.push({ - userId: data.user_id, - stampId: data.stamp_id, - count: data.count - }) - } - } else { - message.stampList = [ - { - userId: data.user_id, - stampId: data.stamp_id, - count: data.count - } - ] - } - Vue.set( - state.currentChannelPinnedMessages, - pinnedIndex, - state.currentChannelPinnedMessages[pinnedIndex] - ) - } - }, - deleteMessageStamp(state, data) { - const index = state.messages.findIndex( - e => e.messageId === data.message_id - ) - if (index >= 0) { - const message = state.messages[index] - if (message.stampList) { - const userDataIndex = message.stampList.findIndex( - e => e.userId === data.user_id && e.stampId === data.stamp_id - ) - if (userDataIndex >= 0) { - message.stampList = message.stampList.filter( - (_, i) => i !== userDataIndex - ) - Vue.set(state.messages, index, message) - } - } - } - const pinnedIndex = state.currentChannelPinnedMessages.findIndex( - e => e.message.messageId === data.message_id - ) - if (pinnedIndex >= 0) { - const message = state.currentChannelPinnedMessages[pinnedIndex].message - if (message.stampList) { - const userDataIndex = message.stampList.findIndex( - e => e.userId === data.user_id && e.stampId === data.stamp_id - ) - if (userDataIndex >= 0) { - message.stampList = message.stampList.filter( - (_, i) => i !== userDataIndex - ) - Vue.set( - state.currentChannelPinnedMessages, - pinnedIndex, - state.currentChannelPinnedMessages[pinnedIndex] - ) - } - } - } - }, - setFiles(state, files) { - state.files = files - }, - clearFiles(state) { - state.files = [] - }, - setEditing(state, isEditing) { - state.editing = isEditing - }, - removeMessage(state, messageId) { - state.messages = state.messages.filter( - message => message.messageId !== messageId - ) - }, - setPinnedModal(state, isActive) { - state.isActivePinnedModal = isActive - }, - setUserOnline(state, { userId, isOnline }) { - const user = state.memberMap[userId] - user.isOnline = isOnline - Vue.set(state.memberMap, userId, user) - }, - setOpenChannels(state, data) { - state.openChannels = data - }, - setOpenUserLists(state, data) { - state.openUserLists = data - }, - setOpenUserList(state, { groupId, isOpen }) { - Vue.set(state.openUserLists, groupId, isOpen) - }, - setOpenChannel(state, { channelId, isOpen }) { - Vue.set(state.openChannels, channelId, isOpen) - }, - setOpenMode(state, mode) { - state.openMode = mode - }, - setOpenChannelId(state, channelId) { - state.openChannelId = channelId - }, - setLastChannelId(state, channelId) { - state.lastChannelId = channelId - }, - setTheme(state, themeName) { - state.theme = themeName - }, - setWindowSize(state, { windowWidth, windowHeight }) { - state.windowWidth = windowWidth - state.windowHeight = windowHeight - }, - setMyNotifiedChannels(state, channels) { - state.myNotifiedChannels = channels - const set = new Set() - channels.forEach(channelId => { - set.add(channelId) - }) - state.myNotifiedChannelSet = set - }, - setActivityMessages(state, data) { - state.activityMessages = data - state.activityChannelIdSet = new Set(data.map(m => m.parentChannelId)) - }, - addActivityMessages(state, data) { - if (state.activityChannelIdSet.has(data.parentChannelId)) { - const index = state.activityMessages.findIndex( - m => m.parentChannelId === data.parentChannelId - ) - state.activityMessages.splice(index, 1) - state.activityMessages = [data, ...state.activityMessages] - } else { - state.activityMessages = [data, ...state.activityMessages] - state.activityChannelIdSet.add(data.parentChannelId) - } - }, - setFilterSubscribedActivity(state, data) { - state.filterSubscribedActivity = data - }, - setChannelView(state, mode) { - state.channelView = mode - }, - setActiveMessageContextMenu(state, messageId) { - state.activeMessageContextMenu = messageId - }, - changeNetwork(state, condition) { - state.isOnline = condition - }, - setFilterText(state, filterText) { - state.filterText = filterText - }, - setIsUnreadFiltered(state, isUnreadFiltered) { - state.isUnreadFiltered = isUnreadFiltered - }, - setWebhooks(state, webhooks) { - state.webhooks = webhooks - }, - setMessageSendKey(state, key) { - state.messageSendKey = key - } - }, - getters: { - channelTopic(state) { - return channelId => state.channelTopicMap[channelId] || '' - }, - activeMessageContextMenu(state) { - return state.activeMessageContextMenu - }, - channelView(state) { - return state.channelView - }, - theme(state) { - return typeof state.theme === 'string' ? state.theme : 'light' - }, - windowWidth(state) { - return state.windowWidth - }, - windowHeight(state) { - return state.windowHeight - }, - childrenChannels(state) { - return parentId => - state.channelData.filter( - channel => channel.parent === parentId && channel.name !== '' - ) - }, - allChannels(state) { - return state.channelData.filter( - channel => - channel.parent !== 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa' && - channel.name !== '' - ) - }, - getChannelByName(state, getters) { - return channelName => { - const channelLevels = channelName.split('/') - let channel: { channelId: string } | null | undefined = null - let channelId = '' - channelLevels.forEach(name => { - const levelChannels = getters.childrenChannels(channelId) - channel = levelChannels.find(ch => ch.name === name) - if (channel === null || channel === undefined) return null - channelId = channel.channelId - }) - return channel - } - }, - getDirectMessageChannels(state) { - return state.channelData.filter(channel => channel.dm) - }, - getUserByName(state, getters) { - return userName => { - const user = getters.memberData.find(user => user.name === userName) - if (user) { - return user - } else { - return null - } - } - }, - getChannelPathById(state) { - return channelId => { - let current = state.channelMap[channelId] - let path = current.name - let next = state.channelMap[current.parent] - while (next.name) { - path = next.name + '/' + path - current = next - next = state.channelMap[current.parent] - } - return path - } - }, - getShortChannelPathById(state) { - return channelId => { - let current = state.channelMap[channelId] - let path = current.name - let next = state.channelMap[current.parent] - while (next.name) { - path = next.name[0] + '/' + path - current = next - next = state.channelMap[current.parent] - } - return path - } - }, - getFileDataById() { - return fileId => { - return client.getFileMeta(fileId) - } - }, - isPinned(state) { - return messageId => { - return state.currentChannelPinnedMessages.find( - pin => pin.message.messageId === messageId - ) - } - }, - getMyId(state) { - return state.me ? state.me.userId : '' - }, - getMyName(state) { - return state.me ? state.me.name : '' - }, - notificationsOnMembers(state) { - return state.currentChannelNotifications.map(id => state.memberMap[id]) - }, - notificationsOffMembers(state, getters) { - return getters.memberData.filter( - user => - !state.currentChannelNotifications.find(id => id === user.userId) - ) - }, - getCurrentChannelUpdateDate(state) { - return state.currentChannelUpdateDate - }, - getChannelUnreadMessageNum(state) { - return channelId => { - if (!state.unreadChannelMap[channelId]) { - return 0 - } - return state.unreadChannelMap[channelId].count - } - }, - getChannelUnreadMessageSum(state, getters) { - return channelId => { - let sum = getters.getChannelUnreadMessageNum(channelId) - if ( - !state.channelMap[channelId] || - !state.channelMap[channelId].children || - !Array.isArray(state.channelMap[channelId].children) - ) { - return sum - } - return state.channelMap[channelId].children - .filter(child => child.channelId !== state.directMessageId) - .map(child => getters.getChannelUnreadMessageSum(child)) - .reduce((a, b) => a + b, sum) - } - }, - getUnreadMessageNum(state, getters) { - return Object.keys(state.unreadChannelMap).reduce((pre, channelId) => { - return pre + getters.getChannelUnreadMessageNum(channelId) - }, 0) - }, - getUnreadDirectMessagesSum(state, getters) { - return getters.getDirectMessageChannels.reduce((pre, channel) => { - return pre + getters.getChannelUnreadMessageNum(channel.channelId) - }, 0) - }, - getStaredChannels(state) { - const channels = state.staredChannels.map( - channelId => state.channelMap[channelId] - ) - channels.sort(stringSortGen('name')) - return channels - }, - getUserIdByDirectMessageChannel(state) { - return channel => { - if (!channel.dm) { - return '' - } - if (channel.member.length === 1) { - return channel.member[0] - } else { - return channel.member.find(userId => userId !== state.me.userId) - } - } - }, - deviceType(state) { - return state.windowWidth < 680 ? 'sp' : 'pc' - }, - isSidebarOpened(state) { - return state.sidebarOpened - }, - isTitlebarExpanded(state) { - return state.titlebarExpanded - }, - fileUrl(state) { - return fileId => { - return `${state.baseURL}/api/1.0/files/${fileId}` - } - }, - grades(state) { - return state.groupData.filter( - group => group.type === 'grade' && group.members.length > 0 - ) - }, - sortedGrades(state, getters) { - const map = { - B: 3, - M: 2, - D: 1, - R: 0 - } - const f = s => { - return map[s[2]] * 100 + parseInt(s.substr(0, 2), 10) - } - const gradeReg = /^\d\d[BMDR]$/ - return getters.grades.sort((lhs, rhs) => { - if (gradeReg.test(lhs.name) && gradeReg.test(rhs.name)) { - return f(rhs.name) - f(lhs.name) - } else if (gradeReg.test(lhs.name)) { - return -1 - } else if (gradeReg.test(rhs.name)) { - return 1 - } else { - if (lhs.name < rhs.name) { - return -1 - } else { - return 1 - } - } - }) - }, - memberData(state) { - return state.memberData.filter(user => user.accountStatus !== 0) - }, - nonBotUsers(state, getters) { - return getters.memberData.filter(user => !user.bot) - }, - gradeByUserMap(state, getters) { - const map = {} - getters.nonBotUsers.forEach(u => { - let gradeObj = getters.grades.find(g => - g.members.some(userId => userId === u.userId) - ) - map[u.userId] = gradeObj || undefined - }) - return map - }, - getGroupByContent(state) { - return groupName => - state.groupData.find(group => group.name === groupName) - }, - userDisplayName(state) { - return userId => state.memberMap[userId].displayName - }, - stampHistory(state) { - return state.stampHistory - }, - filteringUser(state) { - return users => - users.filter(userId => state.memberData[userId].accountStatus !== 0) - }, - sortByUserId(state) { - return userIds => - userIds - .map(userId => state.memberMap[userId]) - .sort(stringSortGen('name')) - .map(user => user.userId) - }, - filterText(state) { - return state.filterText - }, - isUnreadFiltered(state) { - return state.isUnreadFiltered - }, - getWebhookUserIds(state) { - return state.webhooks.map(w => w.botUserId) - } - }, - actions: { - whoAmI({ commit }) { - return client - .whoAmI() - .then(res => { - commit('setMe', res.data) - }) - .catch(() => { - commit('setMe', null) - }) - }, - getMessages({ state, commit, getters, dispatch }, update) { - const nowChannel = state.currentChannel - let loaded = false - const latest = state.messages.length === 0 || update - if (latest) { - db.read('channelMessages', nowChannel.channelId) - .then(data => { - if (!loaded && data) { - commit('setMessages', data) - } - }) - .catch(() => {}) - } - const loadedMessages = !nowChannel.dm - ? client.loadMessages(nowChannel.channelId, { - limit: 20, - offset: latest ? 0 : state.messages.length - }) - : client.loadDirectMessages( - getters.getUserIdByDirectMessageChannel(nowChannel), - { - limit: 20, - offset: latest ? 0 : state.messages.length - } - ) - return loadedMessages.then(res => { - loaded = true - const messages = res.data.reverse() - dispatch('readMessages', nowChannel.channelId) - if (latest) { - db.write('channelMessages', { - channelId: nowChannel.channelId, - data: messages - }) - } - if (nowChannel === state.currentChannel) { - if (latest) { - commit('setMessages', messages) - return messages.length > 0 - } else { - commit('unshiftMessages', messages) - return messages.length > 0 - } - } - return false - }) - }, - async updateChannels({ commit }) { - return loadGeneralData('Channel', client.getChannels, commit) - }, - updateMembers({ commit }) { - return loadGeneralData('Member', client.getMembers, commit) - }, - updateGroups({ commit }) { - return loadGeneralData('Group', client.getAllGroups, commit) - }, - updateStamps({ commit }) { - return loadGeneralData('Stamp', client.getStamps, commit) - }, - getStampHistory({ commit }) { - client.getStampHistory().then(res => { - commit('setStampHistory', res.data) - }) - }, - updateWebhooks({ commit }) { - client.getWebhooks().then(res => commit('setWebhooks', res.data)) - }, - addStamp({ commit, state }, stampId) { - return client.getStampDetail(stampId).then(res => { - commit('setStampData', state.stampData.concat([res.data])) - }) - }, - updateClipedMessages({ commit }) { - return loadGeneralData( - 'ClipedMessages', - client.getAllClipMessages, - commit - ) - }, - updateUnreadMessages({ commit }) { - return loadGeneralData('UnreadMessages', client.getUnreadChannels, commit) - }, - updateStaredChannels({ commit }) { - return loadGeneralData('StaredChannels', client.getStaredChannels, commit) - }, - updateMutedChannels({ commit }) { - return loadGeneralData('MutedChannels', client.getMutedChannels, commit) - }, - getChannelTopic({ commit }, channelId) { - return client.getChannelTopic(channelId).then(res => { - commit('setChannelTopic', { data: res.data.text, channelId }) - }) - }, - getCurrentChannelPinnedMessages({ commit }, channelId) { - return client.getPinnedMessages(channelId).then(res => { - commit('setCurrentChannelPinnedMessages', res.data) - }) - }, - getCurrentChannelNotifications({ commit }, channelId) { - return client.getNotifications(channelId).then(res => { - commit('setCurrentChannelNotifications', res.data) - }) - }, - addChannel({ state, commit }, channelId) { - return client.getChannelInfo(channelId).then(res => { - const parent = state.channelData.find( - channel => channel.channelId === res.data.parent - ) - if (parent) { - if (parent.children) { - parent.children.push(channelId) - } else { - parent.children = [channelId] - } - } - commit('setChannelData', [res.data].concat(state.channelData)) - }) - }, - deleteChannel({ state, commit }, channelId) { - const parent = state.channel.find( - channel => channel.channelId === state.channelMap[channelId].parent - ) - if (parent) { - parent.children = parent.children.filter(c => c !== channelId) - } - commit( - 'setChannelData', - state.channelData.filter(channel => channel.channelId !== channelId) - ) - }, - updateChannel({ state, commit }, channelId) { - return client.getChannelInfo(channelId).then(res => { - commit( - 'setChannelData', - [res.data].concat( - state.channelData.filter(channel => channel.channelId !== channelId) - ) - ) - }) - }, - checkPinnedMessage({ state, dispatch }, messageId) { - if ( - state.currentChannelPinnedMessages.find( - pin => pin.message.messageId === messageId - ) - ) { - dispatch( - 'getCurrentChannelPinnedMessages', - state.currentChannel.channelId - ) - } - }, - updateUserOnline({ state, commit }, { userId, isOnline }) { - commit('setUserOnline', { userId, isOnline }) - if (state.modal.data && state.modal.data.userId === userId) { - commit('modal/setModalData', state.memberMap[userId]) - } - }, - updateChannelOpen({ state, commit }, { channelId, isOpen }) { - commit('setOpenChannel', { channelId, isOpen }) - return db.write('generalData', { - type: 'openChannels', - data: state.openChannels - }) - }, - updateUserListOpen({ state, commit }, { groupId, isOpen }) { - commit('setOpenUserList', { groupId, isOpen }) - return db.write('generalData', { - type: 'openUserLists', - data: state.openUserLists - }) - }, - loadSetting({ dispatch }) { - return Promise.all([ - dispatch('loadOpenMode'), - dispatch('loadOpenChannelId'), - dispatch('loadLastChannelId'), - dispatch('loadTheme'), - dispatch('loadOpenChannels'), - dispatch('loadFilterSubscribedActivity'), - dispatch('loadOpenUserLists'), - dispatch('loadChannelView'), - dispatch('loadMessageSendKey') - ]) - }, - loadOpenMode({ commit, dispatch }) { - return db - .read('browserSetting', 'openMode') - .then(data => { - commit('setOpenMode', data) - }) - .catch(async () => { - await dispatch('updateOpenMode', 'particular') - }) - }, - loadOpenChannelId({ commit, dispatch, getters }) { - return db - .read('browserSetting', 'openChannelId') - .then(data => { - commit('setOpenChannelId', data) - }) - .catch(async () => { - await dispatch( - 'updateOpenChannelId', - getters.getChannelByName('general').channelId - ) - }) - }, - loadLastChannelId({ commit, dispatch, getters }) { - return db - .read('browserSetting', 'lastChannelId') - .then(data => { - commit('setLastChannelId', data) - }) - .catch(async () => { - await dispatch( - 'updateLastChannelId', - getters.getChannelByName('general').channelId - ) - }) - }, - loadTheme({ commit, dispatch }) { - return db - .read('browserSetting', 'theme') - .then(data => { - commit('setTheme', data) - }) - .catch(async () => { - await dispatch('updateTheme', 'light') - }) - }, - loadOpenChannels({ commit }) { - return db - .read('generalData', 'openChannels') - .then(data => { - commit('setOpenChannels', data || {}) - }) - .catch(() => { - commit('setOpenChannels', {}) - }) - }, - loadOpenUserLists({ commit }) { - return db - .read('generalData', 'openUserLists') - .then(data => { - commit('setOpenUserLists', data || {}) - }) - .catch(() => { - commit('setOpenUserLists', {}) - }) - }, - loadMessageSendKey({ commit, dispatch }) { - return db - .read('browserSetting', 'messageSendKey') - .then(data => { - commit('setMessageSendKey', data) - }) - .catch(async () => { - await dispatch('updateMessageSendKey', 'modifier') - }) - }, - updateOpenMode({ commit }, mode) { - commit('setOpenMode', mode) - return db.write('browserSetting', { type: 'openMode', data: mode }) - }, - updateOpenChannelId({ commit }, channelId) { - commit('setOpenChannelId', channelId) - return db.write('browserSetting', { - type: 'openChannelId', - data: channelId - }) - }, - updateLastChannelId({ commit }, channelId) { - commit('setLastChannelId', channelId) - return db.write('browserSetting', { - type: 'lastChannelId', - data: channelId - }) - }, - updateTheme({ commit }, themeName) { - commit('setTheme', themeName) - return db.write('browserSetting', { type: 'theme', data: themeName }) - }, - async updateChannelActivity({ state, commit }) { - const filter = state.filterSubscribedActivity || false - const res = await client.getLatestMessages({ - limit: 50, - subscribe: filter - }) - commit('setActivityMessages', res.data) - }, - async updateMyNotifiedChannels({ commit }) { - const res = await client.getMyNotifiedChannels() - const data = res.data - if (!data) return - commit('setMyNotifiedChannels', data) - }, - async updateCurrentChannelNotifications({ state, dispatch }, { on, off }) { - await client.changeNotifications(state.currentChannel.channelId, { - on: on || [], - off: off || [] - }) - await dispatch( - 'getCurrentChannelNotifications', - state.currentChannel.channelId - ) - }, - async updateCurrentChannelTopic({ state, dispatch }, text) { - const channelId = state.currentChannel.channelId - await client.changeChannelTopic(channelId, { text }) - await dispatch('getChannelTopic', channelId) - }, - updateFilterSubscribedActivity({ commit }, filter) { - commit('setFilterSubscribedActivity', filter) - return db.write('browserSetting', { - type: 'filterSubscribedActivity', - data: filter - }) - }, - loadFilterSubscribedActivity({ commit, dispatch }) { - return db - .read('browserSetting', 'filterSubscribedActivity') - .then(data => { - commit('setFilterSubscribedActivity', data) - }) - .catch(async () => { - await dispatch('updateFilterSubscribedActivity', true) - }) - }, - readMessages({ dispatch }, channelId) { - return client.readMessages(channelId).then(() => { - dispatch('updateUnreadMessages') - }) - }, - updateChannelView({ commit }, mode) { - commit('setChannelView', mode) - return db.write('browserSetting', { type: 'channelView', data: mode }) - }, - loadChannelView({ commit, dispatch }) { - return db - .read('browserSetting', 'channelView') - .then(data => { - commit('setChannelView', data) - }) - .catch(async () => { - await dispatch('updateChannelView', 'tree') - }) - }, - updateMessageSendKey({ commit }, key) { - commit('setMessageSendKey', key) - return db.write('browserSetting', { type: 'messageSendKey', data: key }) - } + messageInput, + pickerModal } -}) +} as any) + +interface Window { + openUserModal: (string) => void + openGroupModal: (string) => void +} +declare var window: Window window.openUserModal = userId => { store.dispatch('openUserModal', userId) diff --git a/src/store/messageInput.ts b/src/store/messageInput.ts deleted file mode 100644 index 389164cf..00000000 --- a/src/store/messageInput.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Vue from 'vue' - -export default { - namespaced: true, - state: { - inputTextMap: {}, // channelId => textString´ - inputFilesMap: {} // channelId => filesArray - }, - getters: { - inputText: state => channelId => { - return state.inputTextMap[channelId] || '' - }, - inputFiles: state => channelId => { - return state.inputFilesMap[channelId] || [] - } - }, - mutations: { - setInputText(state, { channelId, inputText }) { - Vue.set(state.inputTextMap, channelId, inputText) - }, - setInputFiles(state, { channelId, files }) { - Vue.set(state.inputFilesMap, channelId, files) - }, - addStampToInputText(state, { stampName, channelId }) { - if (state.inputTextMap[channelId]) { - state.inputTextMap[channelId] += `:${stampName}:` - } else { - Vue.set(state.inputTextMap, channelId, `:${stampName}:`) - } - } - } -} diff --git a/src/store/messageInput/index.ts b/src/store/messageInput/index.ts new file mode 100644 index 00000000..0c9b1ef0 --- /dev/null +++ b/src/store/messageInput/index.ts @@ -0,0 +1,60 @@ +import Vue from 'vue' +import { S, G, M, A } from './type' +import { Getters, Mutations, Actions } from 'vuex' +import client from '@/bin/client' + +const state = (): S => ({ + inputTextMap: {}, // channelId => textString´ + inputFilesMap: {} // channelId => filesArray +}) + +const getters: Getters = { + inputText: state => channelId => { + return state.inputTextMap[channelId] || '' + }, + inputFiles: state => channelId => { + return state.inputFilesMap[channelId] || [] + } +} +const mutations: Mutations = { + setInputText(state, { channelId, inputText }) { + Vue.set(state.inputTextMap, channelId, inputText) + }, + setInputFiles(state, { channelId, files }) { + Vue.set(state.inputFilesMap, channelId, files) + }, + addStampToInputText(state, { stampName, channelId }) { + if (state.inputTextMap[channelId]) { + state.inputTextMap[channelId] += `:${stampName}:` + } else { + Vue.set(state.inputTextMap, channelId, `:${stampName}:`) + } + } +} + +const acions: Actions = { + addStampToMessage({ rootState }, stampId) { + client.stampMessage( + rootState.pickerModal.stampPickerModel.messageId, + stampId + ) + }, + execStamp({ state, commit, dispatch, rootState }, stamp) { + if (rootState.pickerModal.stampPickerMode === 'message') { + dispatch('addStampToMessage', stamp.id) + } else { + commit('addStampToInputText', { + stampName: stamp.name || '', + channelId: rootState.currentChannel.channelId || '' + }) + } + } +} + +export default { + namespaced: true, + state, + getters, + mutations, + acions +} diff --git a/src/store/messageInput/type.ts b/src/store/messageInput/type.ts new file mode 100644 index 00000000..3ef1bb6f --- /dev/null +++ b/src/store/messageInput/type.ts @@ -0,0 +1,38 @@ +import Schemas = Components.Schemas + +export interface S { + inputTextMap: { [channelId: string]: string } + inputFilesMap: { [channelId: string]: any[] } +} + +export interface G { + inputText: (channelId: string) => string + inputFiles: (channelId: string) => any[] +} + +export interface RG { + 'messageInput/inputText': G['inputText'] + 'messageInput/inputFiles': G['inputFiles'] +} + +export interface M { + setInputText: { channelId: string; inputText: string } + setInputFiles: { channelId: string; files: any[] } + addStampToInputText: { channelId: string; stampName: string } +} + +export interface RM { + 'messageInput/setInputText': M['setInputText'] + 'messageInput/setInputFiles': M['setInputFiles'] + 'messageInput/addStampToInputText': M['addStampToInputText'] +} + +export interface A { + execStamp: Schemas.Stamp + addStampToMessage: string +} + +export interface RA { + 'messageInput/execStamp': A['execStamp'] + 'messageInput/addStampToMessage': A['addStampToMessage'] +} diff --git a/src/store/modal.ts b/src/store/modal.ts deleted file mode 100644 index 82b472f3..00000000 --- a/src/store/modal.ts +++ /dev/null @@ -1,164 +0,0 @@ -import client from '@/bin/client' - -export default { - namespaced: true, - state: { - name: null, - data: null, - currentUserTags: [], - currentTagUserIds: [], - currentUserGroupIds: [], - lastUser: null, - qrLastLoad: null - }, - getters: { - isActive: state => !!state.name, - currentUserTagsSorted: state => { - return state.currentUserTags - }, - currentTagUsersSorted: state => { - return state.currentTagUserIds - }, - currentUserGroupsSorted: (state, _, rootState) => { - const currentIds = state.currentUserGroupIds - const current = currentIds.map(id => rootState.groupMap[id]) - return current - .filter(group => group.type === 'grade') - .concat(current.filter(group => group.type !== 'grade')) - } - }, - mutations: { - setQRCodeImage(state) { - if ( - !state.qrLastLoad || - new Date().getTime() - state.qrLastLoad > 1000 * 60 * 10 - ) { - state.qrLastLoad = new Date().getTime() - } - }, - setModalName(state, name) { - state.name = name - }, - setModalData(state, data) { - state.data = data - }, - setLastUser(state, user) { - state.lastUser = user - }, - setCurrentUserTags(state, tags) { - tags = tags || [] - state.currentUserTags = tags - }, - setCurrentTagUserIds(state, users) { - users = users || [] - state.currentTagUserIds = users - }, - setCurrentUserGroupIds(state, groups) { - groups = groups || [] - state.currentUserGroupIds = groups - } - }, - actions: { - updateCurrentUserTags({ state, commit }) { - return client.getUserTags(state.data.userId).then(res => { - commit('setCurrentUserTags', res.data) - }) - }, - updateCurrentUserGroupIds({ state, commit }) { - return client.getUserGroups(state.data.userId).then(res => { - commit('setCurrentUserGroupIds', res.data) - }) - }, - updateCurrentTagUserIds({ state, commit }) { - return client.getTag(state.data.tagId).then(res => { - commit('setCurrentTagUserIds', res.data.users) - }) - }, - openUserModal: { - root: true, - handler({ rootState, dispatch }, userId) { - if (/#/.test(rootState.memberMap[userId].name)) return - if (rootState.memberMap[userId].accountStatus === 0) return - dispatch('open', { - name: 'UserModal', - data: rootState.memberMap[userId] - }) - return Promise.all([ - dispatch('updateCurrentUserTags'), - dispatch('updateCurrentUserGroupIds') - ]) - } - }, - openGroupModal: { - root: true, - handler({ rootState, dispatch }, groupId) { - dispatch('open', { - name: 'GroupModal', - data: rootState.groupMap[groupId] - }) - } - }, - openTagModal: { - root: true, - handler({ dispatch }, tag) { - dispatch('open', { - name: 'TagModal', - data: tag - }) - return dispatch('updateCurrentTagUserIds') - } - }, - openFileModal: { - root: true, - handler({ dispatch }, data) { - dispatch('open', { name: 'FileModal', data }) - } - }, - openTourModal: { - root: true, - handler({ dispatch }, data) { - dispatch('open', { name: 'TourModal', data }) - } - }, - openCodeModal: { - root: true, - handler({ dispatch }, data) { - dispatch('open', { name: 'CodeModal', data }) - } - }, - openChannelCreateModal: { - root: true, - handler({ dispatch }) { - dispatch('open', { name: 'ChannelCreateModal' }) - } - }, - openChannelNotificationModal: { - root: true, - handler({ dispatch }) { - dispatch('open', { name: 'ChannelNotificationModal' }) - } - }, - openPinnedModal: { - root: true, - handler({ dispatch }, message) { - dispatch('open', { - name: 'PinnedModal', - data: message - }) - } - }, - open({ state, commit }, { name, data }) { - if (state.name === 'UserModal') { - // Transition from user modal - commit('setLastUser', state.data) - } - commit('setModalName', name) - commit('setModalData', data) - }, - close({ commit }) { - commit('setModalName', null) - commit('setLastUser', null) - commit('setModalData', null) - } - } -} diff --git a/src/store/modal/index.ts b/src/store/modal/index.ts new file mode 100644 index 00000000..4e4d3042 --- /dev/null +++ b/src/store/modal/index.ts @@ -0,0 +1,145 @@ +import client from '@/bin/client' +import { S, G, M, A } from './type' +import { Getters, Mutations, Actions } from 'vuex' + +const state = (): S => ({ + name: null, + data: null, + currentUserTags: [], + currentTagUserIds: [], + currentUserGroupIds: [], + lastUser: null, + qrLastLoad: null +}) + +const getters: Getters = { + isActive: state => !!state.name, + currentUserTagsSorted: state => { + return state.currentUserTags + }, + currentTagUsersSorted: state => { + return state.currentTagUserIds + }, + currentUserGroupsSorted: (state, _, rootState) => { + const currentIds = state.currentUserGroupIds + const current = currentIds.map(id => rootState.groupMap[id]) + return current + .filter(group => group.type === 'grade') + .concat(current.filter(group => group.type !== 'grade')) + } +} +const mutations: Mutations = { + setQRCodeImage(state) { + if ( + !state.qrLastLoad || + new Date().getTime() - state.qrLastLoad > 1000 * 60 * 10 + ) { + state.qrLastLoad = new Date().getTime() + } + }, + setModalName(state, name) { + state.name = name + }, + setModalData(state, data) { + state.data = data + }, + setLastUser(state, user) { + state.lastUser = user + }, + setCurrentUserTags(state, tags) { + tags = tags || [] + state.currentUserTags = tags + }, + setCurrentTagUserIds(state, users) { + users = users || [] + state.currentTagUserIds = users + }, + setCurrentUserGroupIds(state, groups) { + groups = groups || [] + state.currentUserGroupIds = groups + } +} +const actions: Actions = { + updateCurrentUserTags({ state, commit }) { + return client.getUserTags(state.data.userId).then(res => { + commit('setCurrentUserTags', res.data) + }) + }, + updateCurrentUserGroupIds({ state, commit }) { + return client.getUserGroups(state.data.userId).then(res => { + commit('setCurrentUserGroupIds', res.data) + }) + }, + updateCurrentTagUserIds({ state, commit }) { + return client.getTag(state.data.tagId).then(res => { + commit('setCurrentTagUserIds', res.data.users) + }) + }, + openUserModal({ rootState, dispatch }, userId) { + if (/#/.test(rootState.memberMap[userId].name || '')) return + if (rootState.memberMap[userId].accountStatus === 0) return + dispatch('open', { + name: 'UserModal', + data: rootState.memberMap[userId] + }) + return Promise.all([ + dispatch('updateCurrentUserTags'), + dispatch('updateCurrentUserGroupIds') + ]) + }, + openGroupModal({ rootState, dispatch }, groupId) { + dispatch('open', { + name: 'GroupModal', + data: rootState.groupMap[groupId] + }) + }, + openTagModal({ dispatch }, tag) { + dispatch('open', { + name: 'TagModal', + data: tag + }) + return dispatch('updateCurrentTagUserIds') + }, + openFileModal({ dispatch }, data) { + dispatch('open', { name: 'FileModal', data }) + }, + openTourModal({ dispatch }, data) { + dispatch('open', { name: 'TourModal', data }) + }, + openCodeModal({ dispatch }, data) { + dispatch('open', { name: 'CodeModal', data }) + }, + openChannelCreateModal({ dispatch }) { + dispatch('open', { name: 'ChannelCreateModal' }) + }, + openChannelNotificationModal({ dispatch }) { + dispatch('open', { name: 'ChannelNotificationModal' }) + }, + openPinnedModal({ dispatch }, message) { + dispatch('open', { + name: 'PinnedModal', + data: message + }) + }, + open({ state, commit }, { name, data }) { + if (state.name === 'UserModal') { + // Transition from user modal + commit('setLastUser', state.data) + } + commit('setModalName', name) + commit('setModalData', data) + }, + close({ commit }) { + commit('setModalName', null) + commit('setLastUser', null) + commit('setModalData', null) + } +} + +export default { + namespaced: true, + state, + getters, + mutations, + actions +} diff --git a/src/store/modal/type.ts b/src/store/modal/type.ts new file mode 100644 index 00000000..f61b2144 --- /dev/null +++ b/src/store/modal/type.ts @@ -0,0 +1,78 @@ +import Schemas = Components.Schemas + +export interface S { + name: null | string + data: any + currentUserTags: Schemas.Tag[] + currentTagUserIds: string[] + currentUserGroupIds: string[] + lastUser: Schemas.User | null + qrLastLoad: number | null +} + +export interface G { + isActive: boolean + currentUserTagsSorted: Schemas.Tag[] + currentTagUsersSorted: string[] + currentUserGroupsSorted: (Schemas.UserGroup & { type: string })[] +} + +export interface RG { + 'modal/isActive': G['isActive'] + 'modal/currentUserTagsSorted': G['currentUserTagsSorted'] + 'modal/currentTagUsersSorted': G['currentTagUsersSorted'] + 'modal/currentUserGroupsSorted': G['currentUserGroupsSorted'] +} + +export interface M { + setQRCodeImage: void + setModalName: null | string + setModalData: any + setLastUser: null | Schemas.User + setCurrentUserTags: null | Schemas.Tag[] + setCurrentTagUserIds: null | string[] + setCurrentUserGroupIds: null | string[] +} + +export interface RM { + 'modal/setQRCodeImage': M['setQRCodeImage'] + 'modal/setModalName': M['setModalName'] + 'modal/setModalData': M['setModalData'] + 'modal/setLastUser': M['setLastUser'] + 'modal/setCurrentUserTags': M['setCurrentUserTags'] + 'modal/setCurrentTagUserIds': M['setCurrentTagUserIds'] + 'modal/setCurrentUserGroupIds': M['setCurrentUserGroupIds'] +} + +export interface A { + updateCurrentUserTags: void + updateCurrentUserGroupIds: void + updateCurrentTagUserIds: void + openUserModal: string + openGroupModal: string + openTagModal: Schemas.Tag + openFileModal: any + openTourModal: any + openCodeModal: any + openChannelCreateModal: void + openChannelNotificationModal: void + openPinnedModal: Schemas.Message + open: { name: string; data?: any } + close: void +} + +export interface RA { + 'modal/updateCurrentUserTags': A['updateCurrentUserTags'] + 'modal/updateCurrentUserGroupIds': A['updateCurrentUserGroupIds'] + 'modal/updateCurrentTagUserIds': A['updateCurrentTagUserIds'] + 'modal/openUserModal': A['openUserModal'] + 'modal/openGroupModal': A['openGroupModal'] + 'modal/openTagModal': A['openTagModal'] + 'modal/openTourModal': A['openTourModal'] + 'modal/openCodeModal': A['openCodeModal'] + 'modal/openChannelCreateModal': A['openChannelCreateModal'] + 'modal/openChannelNotificationModal': A['openChannelNotificationModal'] + 'modal/openPinnedModal': A['openPinnedModal'] + 'modal/open': A['open'] + 'modal/close': A['close'] +} diff --git a/src/store/pickerModal.ts b/src/store/pickerModal.ts deleted file mode 100644 index 515fa5cf..00000000 --- a/src/store/pickerModal.ts +++ /dev/null @@ -1,47 +0,0 @@ -import client from '@/bin/client' - -export default { - namespaced: false, - state: { - stampPickerActive: false, - stampPickerMode: 'message', - stampPickerModel: null - }, - getters: { - stampPickerActive(state) { - return state.stampPickerActive - }, - stampPickerModel(state) { - return state.stampPickerModel - } - }, - mutations: { - setStampPickerModel(state, model) { - state.stampPickerModel = model - }, - setStampPickerActive(state, isActive) { - state.stampPickerActive = isActive - }, - setStampPickerModeAsMessage(state) { - state.stampPickerMode = 'message' - }, - setStampPickerModeAsInput(state) { - state.stampPickerMode = 'input' - } - }, - actions: { - execStamp({ state, commit, dispatch, rootState }, stamp) { - if (state.stampPickerMode === 'message') { - dispatch('addStampToMessage', stamp.id) - } else { - commit('messageInput/addStampToInputText', { - stampName: stamp.name, - channelId: rootState.currentChannel.channelId - }) - } - }, - addStampToMessage({ state }, stampId) { - client.stampMessage(state.stampPickerModel.messageId, stampId) - } - } -} diff --git a/src/store/pickerModal/index.ts b/src/store/pickerModal/index.ts new file mode 100644 index 00000000..0ec22020 --- /dev/null +++ b/src/store/pickerModal/index.ts @@ -0,0 +1,41 @@ +import client from '@/bin/client' +import { S, G, M, A } from './type' +import { Getters, Mutations, Actions } from 'vuex' + +const state = (): S => ({ + stampPickerActive: false, + stampPickerMode: 'message', + stampPickerModel: null +}) +const getters: Getters = { + stampPickerActive(state) { + return state.stampPickerActive + }, + stampPickerModel(state) { + return state.stampPickerModel + } +} +const mutations: Mutations = { + setStampPickerModel(state, model) { + state.stampPickerModel = model + }, + setStampPickerActive(state, isActive) { + state.stampPickerActive = isActive + }, + setStampPickerModeAsMessage(state) { + state.stampPickerMode = 'message' + }, + setStampPickerModeAsInput(state) { + state.stampPickerMode = 'input' + } +} + +const actions: Actions = {} + +export default { + namespaced: true, + state, + getters, + mutations, + actions +} diff --git a/src/store/pickerModal/type.ts b/src/store/pickerModal/type.ts new file mode 100644 index 00000000..0437f6a0 --- /dev/null +++ b/src/store/pickerModal/type.ts @@ -0,0 +1,35 @@ +import Schemas = Components.Schemas + +export interface S { + stampPickerActive: boolean + stampPickerMode: string + stampPickerModel: any +} + +export interface G { + stampPickerActive: boolean + stampPickerModel: any +} + +export interface RG { + 'pickerModal/stampPickerActive': G['stampPickerActive'] + 'pickerModal/stampPickerModel': G['stampPickerModel'] +} + +export interface M { + setStampPickerModel: any + setStampPickerActive: boolean + setStampPickerModeAsMessage: void + setStampPickerModeAsInput: void +} + +export interface RM { + 'pickerModal/setStampPickerModel': M['setStampPickerModel'] + 'pickerModal/setStampPickerActive': M['setStampPickerActive'] + 'pickerModal/setStampPickerModeAsMessage': M['setStampPickerModeAsMessage'] + 'pickerModal/setStampPickerModeAsInput': M['setStampPickerModeAsInput'] +} + +export interface A {} + +export interface RA {} diff --git a/src/types/vuex/impl.ts b/src/types/vuex/impl.ts new file mode 100644 index 00000000..38e1a931 --- /dev/null +++ b/src/types/vuex/impl.ts @@ -0,0 +1,17 @@ +import 'vuex' +import * as Root from '../../store/general/type' +import * as MessageInput from '../../store/messageInput/type' +import * as Modal from '../../store/modal/type' +import * as PickerModal from '../../store/PickerModal/type' + +declare module 'vuex' { + type RootState = Root.S & { + general: Root.S + messageInput: MessageInput.S + modal: Modal.S + pickerModal: PickerModal.S + } + type RootGetters = Root.RG & MessageInput.RG & Modal.RG & PickerModal.RG + type RootMutations = Root.RM & MessageInput.RM & Modal.RM & PickerModal.RM + type RootActions = Root.RA & MessageInput.RA & Modal.RA & PickerModal.RA +} diff --git a/src/types/vuex/index.d.ts b/src/types/vuex/index.d.ts new file mode 100644 index 00000000..5cd06395 --- /dev/null +++ b/src/types/vuex/index.d.ts @@ -0,0 +1,2 @@ +import './type' +import './impl' diff --git a/src/types/vuex/type.ts b/src/types/vuex/type.ts new file mode 100644 index 00000000..727c094e --- /dev/null +++ b/src/types/vuex/type.ts @@ -0,0 +1,46 @@ +import 'vuex' +import { RootMutations, RootActions } from 'vuex' + +declare module 'vuex' { + // ______________________________________________________ + // + type Getters = { + [K in keyof G]: ( + state: S, + getters: G, + rootState: RootState, + rootGetters: RootGetters + ) => G[K] + } + // ______________________________________________________ + // + type Mutations = { [K in keyof M]: (state: S, payload: M[K]) => void } + // ______________________________________________________ + // + type ExCommit = (type: T, payload?: M[T]) => void + type ExDispatch = (type: T, payload?: A[T]) => any + type ExActionContext = { + commit: ExCommit & ExCommit + dispatch: ExDispatch & ExDispatch + state: S + getters: G + rootState: RootState + rootGetters: RootGetters + } + type Actions = { + [K in keyof A]: (ctx: ExActionContext, payload: A[K]) => any + } + // ______________________________________________________ + // + interface ExStore extends Store { + getters: RootGetters + commit: ExCommit + dispatch: ExDispatch + } + type StoreContext = ExActionContext< + RootState, + RootActions, + RootGetters, + RootMutations + > +} From 3a30aaec5953462c24212d7b8950e13f0be2d338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Mon, 27 May 2019 15:40:04 +0900 Subject: [PATCH 08/12] =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=88=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88=E3=81=AETS?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{main.js => main.ts} | 7 ++++++- src/router/{index.js => index.ts} | 33 ++++++++++++++++++------------- src/store/index.ts | 4 ++-- vue.config.js | 2 +- 4 files changed, 28 insertions(+), 18 deletions(-) rename src/{main.js => main.ts} (87%) rename src/router/{index.js => index.ts} (88%) diff --git a/src/main.js b/src/main.ts similarity index 87% rename from src/main.js rename to src/main.ts index 5fe730aa..df7adbe7 100644 --- a/src/main.js +++ b/src/main.ts @@ -3,7 +3,7 @@ import Vue from 'vue' import Meta from 'vue-meta' import VueClipboard from 'vue-clipboard2' -import App from './App' +import App from './App.vue' import store from './store' import router from './router' import VueLazyload from 'vue-lazyload' @@ -14,6 +14,11 @@ Vue.use(Meta) Vue.use(VueClipboard) Vue.use(VueLazyload) +interface Window { + asyncLoadComponents: (any) => any +} +declare var window: Window + window.asyncLoadComponents = component => { return () => { return component.then(data => { diff --git a/src/router/index.js b/src/router/index.ts similarity index 88% rename from src/router/index.js rename to src/router/index.ts index b05d3478..f280b7ee 100644 --- a/src/router/index.js +++ b/src/router/index.ts @@ -21,34 +21,34 @@ const router = new Router({ { path: '/login', name: 'Login', - component: asyncLoadComponents(import('@/pages/Login/Login')) + component: asyncLoadComponents(import('@/pages/Login/Login.vue')) }, { path: '/consent', name: 'Consent', - component: asyncLoadComponents(import('@/pages/Consent/Consent')) + component: asyncLoadComponents(import('@/pages/Consent/Consent.vue')) }, { path: '/setting', name: 'Setting', - component: asyncLoadComponents(import('@/pages/Setting/Index')) + component: asyncLoadComponents(import('@/pages/Setting/Index.vue')) }, { path: '/', name: 'Index', - component: asyncLoadComponents(import('@/pages/Main/Main')) + component: asyncLoadComponents(import('@/pages/Main/Main.vue')) }, { path: '/channels/:channel(.*)', - component: asyncLoadComponents(import('@/pages/Main/Main')) + component: asyncLoadComponents(import('@/pages/Main/Main.vue')) }, { path: '/users/:user', - component: asyncLoadComponents(import('@/pages/Main/Main')) + component: asyncLoadComponents(import('@/pages/Main/Main.vue')) }, { path: '/register', - component: asyncLoadComponents(import('@/pages/Register/Register')) + component: asyncLoadComponents(import('@/pages/Register/Register.vue')) }, { path: '/pipeline', @@ -57,7 +57,7 @@ const router = new Router({ { path: '*', name: 'NotFound', - component: asyncLoadComponents(import('@/pages/NotFound')) + component: asyncLoadComponents(import('@/pages/NotFound.vue')) } ], mode: 'history' @@ -73,7 +73,7 @@ router.beforeEach(async (to, from, next) => { if (!store.state.me && navigator.onLine) { store.commit('loadEnd') if (to.path === '/login') { - next(true) + next() return } next('/login') @@ -127,11 +127,11 @@ router.beforeEach(async (to, from, next) => { const nextUser = store.getters.getUserByName(to.params.user) if (nextUser) { const member = [nextUser.userId] - if (store.state.me.userId !== nextUser.userId) { + if (store.state.me && store.state.me.userId !== nextUser.userId) { member.push(store.state.me.userId) } let channelId = nextUser.userId - if (nextUser.userId === store.state.me.userId) { + if (store.state.me && nextUser.userId === store.state.me.userId) { const channel = store.getters.getDirectMessageChannels.find( c => c.member.length === 1 ) @@ -159,7 +159,7 @@ router.beforeEach(async (to, from, next) => { store.commit('setCurrentChannelPinnedMessages', []) store.dispatch('getMessages') store.commit('loadEnd') - next(true) + next() return } else { next('/notfound') @@ -169,7 +169,7 @@ router.beforeEach(async (to, from, next) => { if (!to.params.channel) { store.commit('loadEnd') - next(true) + next() return } @@ -186,11 +186,16 @@ router.beforeEach(async (to, from, next) => { store.dispatch('getCurrentChannelPinnedMessages', nextChannel.channelId) store.dispatch('getCurrentChannelNotifications', nextChannel.channelId) }) - next(true) + next() } store.commit('loadEnd') }) +interface Window { + changeChannel: (channelPath: string) => void +} +declare var window: Window + window.changeChannel = channelPath => { router.push(`/channels/${channelPath}`) } diff --git a/src/store/index.ts b/src/store/index.ts index 25cdb953..f1f021ff 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,5 +1,5 @@ import Vue from 'vue' -import Vuex, { Store } from 'vuex' +import Vuex, { Store, RootState } from 'vuex' import general from './general' import modal from './modal' import messageInput from './messageInput' @@ -7,7 +7,7 @@ import pickerModal from './pickerModal' Vue.use(Vuex) -const store = new Store({ +const store = new Store({ ...general, modules: { modal, diff --git a/vue.config.js b/vue.config.js index 272a2147..a42e1e98 100644 --- a/vue.config.js +++ b/vue.config.js @@ -17,7 +17,7 @@ module.exports = { }, configureWebpack: { entry: { - app: './src/main.js' + app: './src/main.ts' }, resolve: { extensions: ['ts', 'js'], From b9905d32a628814bcf8f08a5c32a48fc9d874f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Mon, 27 May 2019 15:55:56 +0900 Subject: [PATCH 09/12] fix case-sensitive path --- src/types/vuex/impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/vuex/impl.ts b/src/types/vuex/impl.ts index 38e1a931..4185179d 100644 --- a/src/types/vuex/impl.ts +++ b/src/types/vuex/impl.ts @@ -2,7 +2,7 @@ import 'vuex' import * as Root from '../../store/general/type' import * as MessageInput from '../../store/messageInput/type' import * as Modal from '../../store/modal/type' -import * as PickerModal from '../../store/PickerModal/type' +import * as PickerModal from '../../store/pickerModal/type' declare module 'vuex' { type RootState = Root.S & { From d16374821f8e4736bc2fe32b88ad3f76665c2ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Mon, 27 May 2019 23:26:46 +0900 Subject: [PATCH 10/12] =?UTF-8?q?=E5=9E=8B=E3=81=8C=E5=8A=B9=E3=81=8F?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=AA=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/index.ts | 33 +++++++++++++++++---------------- src/store/index.ts | 9 +++++---- src/types/shims-vue.d.ts | 8 ++++++++ tsconfig.json | 3 ++- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/router/index.ts b/src/router/index.ts index f280b7ee..bb50cb15 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -125,37 +125,38 @@ router.beforeEach(async (to, from, next) => { if (to.params.user) { const nextUser = store.getters.getUserByName(to.params.user) + let channel: Components.Schemas.Channel | undefined if (nextUser) { - const member = [nextUser.userId] + const member = [nextUser.userId || ''] if (store.state.me && store.state.me.userId !== nextUser.userId) { - member.push(store.state.me.userId) + member.push(store.state.me.userId || '') } let channelId = nextUser.userId if (store.state.me && nextUser.userId === store.state.me.userId) { - const channel = store.getters.getDirectMessageChannels.find( - c => c.member.length === 1 + channel = store.getters.getDirectMessageChannels.find( + c => !!c.member && c.member.length === 1 ) if (channel) { channelId = channel.channelId } } else { - const channel = store.getters.getDirectMessageChannels.find(c => - c.member.some(userId => userId === nextUser.userId) + channel = store.getters.getDirectMessageChannels.find( + c => !!c.member && c.member.some(userId => userId === nextUser.userId) ) if (channel) { channelId = channel.channelId } } - store.commit('changeChannel', { - channelId: channelId, - name: nextUser.name, - parent: store.state.directMessageId, - children: [], - member: member, - visibility: true, - private: true, - dm: true - }) + if (channel) { + channel.name = nextUser.name + channel.parent = store.state.directMessageId + channel.children = [] + channel.member = member + channel.visibility = true + channel.private = true + channel.dm = true + store.commit('changeChannel', channel) + } store.commit('setCurrentChannelPinnedMessages', []) store.dispatch('getMessages') store.commit('loadEnd') diff --git a/src/store/index.ts b/src/store/index.ts index f1f021ff..b44150d5 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,5 +1,6 @@ import Vue from 'vue' -import Vuex, { Store, RootState } from 'vuex' +import Vuex, { Store, RootState, ExStore } from 'vuex' + import general from './general' import modal from './modal' import messageInput from './messageInput' @@ -7,7 +8,7 @@ import pickerModal from './pickerModal' Vue.use(Vuex) -const store = new Store({ +const store: ExStore = new Store({ ...general, modules: { modal, @@ -23,11 +24,11 @@ interface Window { declare var window: Window window.openUserModal = userId => { - store.dispatch('openUserModal', userId) + store.dispatch('modal/openUserModal', userId) } window.openGroupModal = groupId => { - store.dispatch('openGroupModal', groupId) + store.dispatch('modal/openGroupModal', groupId) } export default store diff --git a/src/types/shims-vue.d.ts b/src/types/shims-vue.d.ts index d9f24faa..bb45d754 100644 --- a/src/types/shims-vue.d.ts +++ b/src/types/shims-vue.d.ts @@ -1,3 +1,11 @@ +import { ExStore } from 'vuex' + +declare module 'vue/types/vue' { + interface Vue { + $store: ExStore + } +} + declare module '*.vue' { import Vue from 'vue' export default Vue diff --git a/tsconfig.json b/tsconfig.json index 617a5d5c..5f204a47 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,8 @@ "dom.iterable", "scripthost" ], - "skipLibCheck": true + "skipLibCheck": true, + "typeRoots": ["src/types", "node_modules/@types"] }, "include": [ "src/**/*.ts", From 19e625f3ac10623acbccac7425e200a60402fa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Tue, 28 May 2019 00:10:24 +0900 Subject: [PATCH 11/12] =?UTF-8?q?modal=E5=91=A8=E3=82=8A=E3=81=AE=E5=91=BC?= =?UTF-8?q?=E3=81=B3=E5=87=BA=E3=81=97=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InformationSidebar/SlimMemberElement.vue | 2 +- .../InformationSidebar/SlimMessageElement.vue | 2 +- .../MessageElement/MessageAttachedFiles.vue | 2 +- .../MessageElement/MessageAttachedMessages.vue | 2 +- .../Main/MessageView/MessageElement/MessageElement.vue | 10 +++++----- src/components/Main/MessageView/MessageInput.vue | 9 ++++++--- src/components/Main/MessageView/Titlebar.vue | 4 ++-- src/components/Main/MessageView/index.vue | 2 +- src/components/Main/Modal/BaseCommonModal.vue | 2 +- src/components/Main/Modal/GroupModal.vue | 2 +- src/components/Main/Modal/TagModal.vue | 2 +- .../Main/Modal/UserModal/UserModalGroups.vue | 2 +- src/components/Main/Modal/UserModal/UserModalTags.vue | 2 +- src/components/Main/Modal/Util/MemberChoice.vue | 2 +- src/components/Main/PickerModal/index.vue | 2 +- src/components/Main/Sidebar/Content/MemberElement.vue | 2 +- src/components/Main/Sidebar/Footer.vue | 4 ++-- 17 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/components/Main/MessageView/InformationSidebar/SlimMemberElement.vue b/src/components/Main/MessageView/InformationSidebar/SlimMemberElement.vue index 216608c1..762eacec 100644 --- a/src/components/Main/MessageView/InformationSidebar/SlimMemberElement.vue +++ b/src/components/Main/MessageView/InformationSidebar/SlimMemberElement.vue @@ -32,7 +32,7 @@ export default { }, methods: { openUserModal() { - this.$store.dispatch('openUserModal', this.userId) + this.$store.dispatch('modal/openUserModal', this.userId) }, getUserName(userId) { const user = this.$store.state.memberMap[userId] diff --git a/src/components/Main/MessageView/InformationSidebar/SlimMessageElement.vue b/src/components/Main/MessageView/InformationSidebar/SlimMessageElement.vue index 04f03045..a9a34bf7 100644 --- a/src/components/Main/MessageView/InformationSidebar/SlimMessageElement.vue +++ b/src/components/Main/MessageView/InformationSidebar/SlimMessageElement.vue @@ -50,7 +50,7 @@ export default { else return user.displayName }, openModal() { - this.$store.dispatch('openPinnedModal', this.message) + this.$store.dispatch('modal/openPinnedModal', this.message) } }, mounted() { diff --git a/src/components/Main/MessageView/MessageElement/MessageAttachedFiles.vue b/src/components/Main/MessageView/MessageElement/MessageAttachedFiles.vue index ddffc976..855e11d2 100644 --- a/src/components/Main/MessageView/MessageElement/MessageAttachedFiles.vue +++ b/src/components/Main/MessageView/MessageElement/MessageAttachedFiles.vue @@ -75,7 +75,7 @@ export default { isVideo, isAudio, onAttachedImageClick(file) { - this.$store.dispatch('openFileModal', file) + this.$store.dispatch('modal/openFileModal', file) }, backgroundImageStyle(url) { return { diff --git a/src/components/Main/MessageView/MessageElement/MessageAttachedMessages.vue b/src/components/Main/MessageView/MessageElement/MessageAttachedMessages.vue index 90678ef4..0d8afb71 100644 --- a/src/components/Main/MessageView/MessageElement/MessageAttachedMessages.vue +++ b/src/components/Main/MessageView/MessageElement/MessageAttachedMessages.vue @@ -39,7 +39,7 @@ export default { ...mapGetters(['userDisplayName', 'fileUrl']) }, methods: { - ...mapActions(['openUserModal']), + ...mapActions('modal', ['openUserModal']), userIconBackground(userId) { return { backgroundImage: `url(${this.fileUrl( diff --git a/src/components/Main/MessageView/MessageElement/MessageElement.vue b/src/components/Main/MessageView/MessageElement/MessageElement.vue index 180b27e4..b485ca37 100644 --- a/src/components/Main/MessageView/MessageElement/MessageElement.vue +++ b/src/components/Main/MessageView/MessageElement/MessageElement.vue @@ -117,18 +117,18 @@ export default { } }, methods: { - ...mapActions(['openUserModal']), + ...mapActions('modal', ['openUserModal']), detectFiles, activeDropMenu() { this.$store.commit('setActiveMessageContextMenu', this.model.messageId) this.isContextMenuActive = true }, showStampPicker() { - this.$store.commit('setStampPickerModeAsMessage') - this.$store.commit('setStampPickerModel', { + this.$store.commit('pickerModal/setStampPickerModeAsMessage') + this.$store.commit('pickerModal/setStampPickerModel', { messageId: this.model.messageId }) - this.$store.commit('setStampPickerActive', true) + this.$store.commit('pickerModal/setStampPickerActive', true) }, editKeydown(event) { if (withModifierKey(event)) { @@ -270,7 +270,7 @@ export default { handleStatusClick() { if (!this.isBot) { this.$store.dispatch( - 'openGroupModal', + 'modal/openGroupModal', this.grade(this.model.userId).groupId ) } diff --git a/src/components/Main/MessageView/MessageInput.vue b/src/components/Main/MessageView/MessageInput.vue index bb2f5a6e..27d589cb 100644 --- a/src/components/Main/MessageView/MessageInput.vue +++ b/src/components/Main/MessageView/MessageInput.vue @@ -458,8 +458,11 @@ export default { ) }, showStampPicker() { - this.$store.commit('setStampPickerModeAsInput') - this.$store.commit('setStampPickerActive', !this.stampPickerActive) + this.$store.commit('pickerModal/setStampPickerModeAsInput') + this.$store.commit( + 'pickerModal/setStampPickerActive', + !this.stampPickerActive + ) }, pasteImage(event) { const items = event.clipboardData.items @@ -474,7 +477,7 @@ export default { } }, computed: { - ...mapGetters(['stampPickerActive']), + ...mapGetters('pickerModal', ['stampPickerActive']), ...mapState(['messageSendKey']), showKeyGuide() { return ( diff --git a/src/components/Main/MessageView/Titlebar.vue b/src/components/Main/MessageView/Titlebar.vue index 7d06fe3d..229c8944 100644 --- a/src/components/Main/MessageView/Titlebar.vue +++ b/src/components/Main/MessageView/Titlebar.vue @@ -23,12 +23,12 @@ header.titlebar(ref="titlebar" :class="titlebarClass") icon-star(size="24") .titlebar-menu-button.border-left(v-show="!isDirectMessage && isStared" @click="unstarChannel") icon-star-fill(size="24") - .titlebar-menu-item(v-show="!isDirectMessage && !isNotificationForced" @click="$store.dispatch('openChannelNotificationModal')") + .titlebar-menu-item(v-show="!isDirectMessage && !isNotificationForced" @click="$store.dispatch('modal/openChannelNotificationModal')") .menu-icon icon-notification-fill(size="24") span | チャンネル通知設定 - .titlebar-menu-item(v-show="!isDirectMessage && channelDepth < 5" @click="$store.dispatch('openChannelCreateModal')") + .titlebar-menu-item(v-show="!isDirectMessage && channelDepth < 5" @click="$store.dispatch('modal/openChannelCreateModal')") .menu-icon icon-plus(size="24") span diff --git a/src/components/Main/MessageView/index.vue b/src/components/Main/MessageView/index.vue index 33c5e9cd..bd38f604 100644 --- a/src/components/Main/MessageView/index.vue +++ b/src/components/Main/MessageView/index.vue @@ -16,7 +16,7 @@ export default { }, mounted() { if (Date(this.$store.state.me.lastOnline).valueOf === 0) { - this.$store.dispatch('openTourModal') + this.$store.dispatch('modal/openTourModal') } } } diff --git a/src/components/Main/Modal/BaseCommonModal.vue b/src/components/Main/Modal/BaseCommonModal.vue index 9a4636f6..cabadd54 100644 --- a/src/components/Main/Modal/BaseCommonModal.vue +++ b/src/components/Main/Modal/BaseCommonModal.vue @@ -44,7 +44,7 @@ export default { handleHeaderClick() { if (this.enableBack) { this.$store.dispatch( - 'openUserModal', + 'modal/openUserModal', this.$store.state.modal.lastUser.userId ) } diff --git a/src/components/Main/Modal/GroupModal.vue b/src/components/Main/Modal/GroupModal.vue index c597bf6d..6b37b72a 100644 --- a/src/components/Main/Modal/GroupModal.vue +++ b/src/components/Main/Modal/GroupModal.vue @@ -33,7 +33,7 @@ export default { }, backToUserModal() { this.$store.dispatch( - 'openUserModal', + 'modal/openUserModal', this.$store.state.modal.lastUser.userId ) } diff --git a/src/components/Main/Modal/TagModal.vue b/src/components/Main/Modal/TagModal.vue index ccde1207..b1389a2b 100644 --- a/src/components/Main/Modal/TagModal.vue +++ b/src/components/Main/Modal/TagModal.vue @@ -33,7 +33,7 @@ export default { }, backToUserModal() { this.$store.dispatch( - 'openUserModal', + 'modal/openUserModal', this.$store.state.modal.lastUser.userId ) } diff --git a/src/components/Main/Modal/UserModal/UserModalGroups.vue b/src/components/Main/Modal/UserModal/UserModalGroups.vue index 228d3d15..0488de6c 100644 --- a/src/components/Main/Modal/UserModal/UserModalGroups.vue +++ b/src/components/Main/Modal/UserModal/UserModalGroups.vue @@ -36,7 +36,7 @@ export default { }, methods: { openGroupModal(group) { - this.$store.dispatch('openGroupModal', group.groupId) + this.$store.dispatch('modal/openGroupModal', group.groupId) } } } diff --git a/src/components/Main/Modal/UserModal/UserModalTags.vue b/src/components/Main/Modal/UserModal/UserModalTags.vue index 3789ce28..10094863 100644 --- a/src/components/Main/Modal/UserModal/UserModalTags.vue +++ b/src/components/Main/Modal/UserModal/UserModalTags.vue @@ -69,7 +69,7 @@ export default { }, methods: { openTagModal(tag) { - this.$store.dispatch('openTagModal', tag) + this.$store.dispatch('modal/openTagModal', tag) }, onInputChange(event) { if ( diff --git a/src/components/Main/Modal/Util/MemberChoice.vue b/src/components/Main/Modal/Util/MemberChoice.vue index f11df7ef..356d244f 100644 --- a/src/components/Main/Modal/Util/MemberChoice.vue +++ b/src/components/Main/Modal/Util/MemberChoice.vue @@ -53,7 +53,7 @@ export default { }, methods: { openUserModal() { - this.$store.dispatch('openUserModal', this.userId) + this.$store.dispatch('modal/openUserModal', this.userId) }, getUserName(userId) { const user = this.$store.state.memberMap[userId] diff --git a/src/components/Main/PickerModal/index.vue b/src/components/Main/PickerModal/index.vue index 3143a840..c0779a7a 100644 --- a/src/components/Main/PickerModal/index.vue +++ b/src/components/Main/PickerModal/index.vue @@ -21,7 +21,7 @@ export default { }, methods: { deactive() { - this.$store.commit('setStampPickerActive', false) + this.$store.commit('pickerModal/setStampPickerActive', false) }, listen: function(target, eventType, callback) { if (!this._eventRemovers) { diff --git a/src/components/Main/Sidebar/Content/MemberElement.vue b/src/components/Main/Sidebar/Content/MemberElement.vue index 22d0a917..b840d54c 100644 --- a/src/components/Main/Sidebar/Content/MemberElement.vue +++ b/src/components/Main/Sidebar/Content/MemberElement.vue @@ -25,7 +25,7 @@ export default { }, methods: { openUserModal() { - this.$store.dispatch('openUserModal', this.model.userId) + this.$store.dispatch('modal/openUserModal', this.model.userId) }, openDMChannel() { this.$store.commit('closeSidebar') diff --git a/src/components/Main/Sidebar/Footer.vue b/src/components/Main/Sidebar/Footer.vue index 69d74451..962b35fc 100644 --- a/src/components/Main/Sidebar/Footer.vue +++ b/src/components/Main/Sidebar/Footer.vue @@ -3,9 +3,9 @@ span.version-text | traQ R {{ version }} ul.footer-button-wrap - li.menu-button(@click.prevent="$store.dispatch('openTourModal')") + li.menu-button(@click.prevent="$store.dispatch('modal/openTourModal')") IconHelp - li.menu-button(@click="$store.dispatch('openCodeModal')") + li.menu-button(@click="$store.dispatch('modal/openCodeModal')") IconQRCode li.menu-button.theme(@click="changeTheme") IconCrescent(v-if="theme === 'light'") From 3721f9521dd04fc6bb7101398cd859c0e42e3105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=A8=E3=83=BC=E3=81=B5=E3=81=A8=E3=81=B5?= Date: Tue, 28 May 2019 15:47:00 +0900 Subject: [PATCH 12/12] =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E7=BE=A9=E3=81=8C?= =?UTF-8?q?=E5=8F=8D=E6=98=A0=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 ++- src/types/shims-vue.d.ts | 8 -------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 40bd425f..e29e940d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "lint": "vue-cli-service lint", "fix": "vue-cli-service lint --fix", "gen-unicode_emojis": "node build/gen-unicode_emojis", - "gen-swagger-type": "dtsgen --out src/types/swagger.d.ts --url https://traptitech.github.io/traQ/swagger.yaml && vue-cli-service lint --fix src/swagger.d.ts" + "gen-swagger-type": "dtsgen --out src/types/swagger.d.ts --url https://traptitech.github.io/traQ/swagger.yaml && vue-cli-service lint --fix src/swagger.d.ts", + "postinstall": "cat node_modules/vuex/types/vue.d.ts | (rm node_modules/vuex/types/vue.d.ts; sed -e 's/\\$store: Store/\\$store: ExStore/g' -e 's/{ Store }/{ Store, ExStore }/g' > node_modules/vuex/types/vue.d.ts)" }, "dependencies": { "dtsgenerator": "^2.0.7", diff --git a/src/types/shims-vue.d.ts b/src/types/shims-vue.d.ts index bb45d754..d9f24faa 100644 --- a/src/types/shims-vue.d.ts +++ b/src/types/shims-vue.d.ts @@ -1,11 +1,3 @@ -import { ExStore } from 'vuex' - -declare module 'vue/types/vue' { - interface Vue { - $store: ExStore - } -} - declare module '*.vue' { import Vue from 'vue' export default Vue