From 94e3f57065898cefaff14bdc3782e765307b4a90 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Tue, 9 Apr 2019 22:49:20 +0900
Subject: [PATCH 01/11] refs #850 Replace Contents and Modals with typescript
---
.../{Contents.js => Contents.ts} | 0
src/renderer/store/TimelineSpace/Modals.js | 37 ---------------
src/renderer/store/TimelineSpace/Modals.ts | 46 +++++++++++++++++++
3 files changed, 46 insertions(+), 37 deletions(-)
rename src/renderer/store/TimelineSpace/{Contents.js => Contents.ts} (100%)
delete mode 100644 src/renderer/store/TimelineSpace/Modals.js
create mode 100644 src/renderer/store/TimelineSpace/Modals.ts
diff --git a/src/renderer/store/TimelineSpace/Contents.js b/src/renderer/store/TimelineSpace/Contents.ts
similarity index 100%
rename from src/renderer/store/TimelineSpace/Contents.js
rename to src/renderer/store/TimelineSpace/Contents.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.js b/src/renderer/store/TimelineSpace/Modals.js
deleted file mode 100644
index 9afe0d2e..00000000
--- a/src/renderer/store/TimelineSpace/Modals.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import NewToot from './Modals/NewToot'
-import ImageViewer from './Modals/ImageViewer'
-import Jump from './Modals/Jump'
-import ListMembership from './Modals/ListMembership'
-import AddListMember from './Modals/AddListMember'
-import MuteConfirm from './Modals/MuteConfirm'
-import Shortcut from './Modals/Shortcut'
-import Report from './Modals/Report'
-
-const Modals = {
- namespaced: true,
- modules: {
- ImageViewer,
- NewToot,
- Jump,
- ListMembership,
- AddListMember,
- MuteConfirm,
- Shortcut,
- Report
- },
- getters: {
- modalOpened: (state, getters, rootState) => {
- const imageViewer = rootState.TimelineSpace.Modals.ImageViewer.modalOpen
- const newToot = rootState.TimelineSpace.Modals.NewToot.modalOpen
- const jump = rootState.TimelineSpace.Modals.Jump.modalOpen
- const listMembership = rootState.TimelineSpace.Modals.ListMembership.modalOpen
- const addListMember = rootState.TimelineSpace.Modals.AddListMember.modalOpen
- const shortcut = rootState.TimelineSpace.Modals.Shortcut.modalOpen
- const muteConfirm = rootState.TimelineSpace.Modals.MuteConfirm.modalOpen
- const report = rootState.TimelineSpace.Modals.Report.modalOpen
- return imageViewer || newToot || jump || listMembership || addListMember || shortcut || muteConfirm || report
- }
- }
-}
-
-export default Modals
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
new file mode 100644
index 00000000..6bfb4685
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -0,0 +1,46 @@
+import NewToot from './Modals/NewToot'
+import ImageViewer from './Modals/ImageViewer'
+import Jump from './Modals/Jump'
+import ListMembership from './Modals/ListMembership'
+import AddListMember from './Modals/AddListMember'
+import MuteConfirm from './Modals/MuteConfirm'
+import Shortcut from './Modals/Shortcut'
+import Report from './Modals/Report'
+import { Module, GetterTree } from 'vuex'
+
+export interface ModalsState {}
+
+const state = (): ModalsState => ({})
+
+// TODO: use type of rootState
+const getters: GetterTree = {
+ modalOpened: (_state, _getters, rootState) => {
+ const imageViewer = rootState.TimelineSpace.Modals.ImageViewer.modalOpen
+ const newToot = rootState.TimelineSpace.Modals.NewToot.modalOpen
+ const jump = rootState.TimelineSpace.Modals.Jump.modalOpen
+ const listMembership = rootState.TimelineSpace.Modals.ListMembership.modalOpen
+ const addListMember = rootState.TimelineSpace.Modals.AddListMember.modalOpen
+ const shortcut = rootState.TimelineSpace.Modals.Shortcut.modalOpen
+ const muteConfirm = rootState.TimelineSpace.Modals.MuteConfirm.modalOpen
+ const report = rootState.TimelineSpace.Modals.Report.modalOpen
+ return imageViewer || newToot || jump || listMembership || addListMember || shortcut || muteConfirm || report
+ }
+}
+
+const Modals: Module = {
+ namespaced: true,
+ modules: {
+ ImageViewer,
+ NewToot,
+ Jump,
+ ListMembership,
+ AddListMember,
+ MuteConfirm,
+ Shortcut,
+ Report
+ },
+ state: state,
+ getters: getters
+}
+
+export default Modals
From 1bb938e0a6936497c3fcb3a8e85851d608bdf760 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Tue, 9 Apr 2019 23:15:15 +0900
Subject: [PATCH 02/11] refs #850 Replace Jump with typescript
---
.../store/TimelineSpace/Modals/Jump.spec.ts | 9 +-
.../store/TimelineSpace/Modals/Jump.spec.ts | 92 ++++++------
.../store/TimelineSpace/Modals/Jump.js | 99 -------------
.../store/TimelineSpace/Modals/Jump.ts | 133 ++++++++++++++++++
4 files changed, 183 insertions(+), 150 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/Jump.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/Jump.ts
diff --git a/spec/renderer/integration/store/TimelineSpace/Modals/Jump.spec.ts b/spec/renderer/integration/store/TimelineSpace/Modals/Jump.spec.ts
index 37974cfd..6b5497f1 100644
--- a/spec/renderer/integration/store/TimelineSpace/Modals/Jump.spec.ts
+++ b/spec/renderer/integration/store/TimelineSpace/Modals/Jump.spec.ts
@@ -2,9 +2,9 @@ import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import i18n from '~/src/config/i18n'
import router from '@/router'
-import Jump from '~/src/renderer/store/TimelineSpace/Modals/Jump'
+import Jump, { JumpState, Channel } from '~/src/renderer/store/TimelineSpace/Modals/Jump'
-const state = () => {
+const state = (): JumpState => {
return {
modalOpen: true,
channel: '',
@@ -93,10 +93,11 @@ describe('Jump', () => {
describe('jump', () => {
it('should be changed', () => {
- store.dispatch('Jump/jump', {
+ const channel: Channel = {
name: 'public',
path: 'public'
- })
+ }
+ store.dispatch('Jump/jump', channel)
expect(store.state.Jump.modalOpen).toEqual(false)
expect(router.push).toHaveBeenCalledWith({ path: '/0/public' })
})
diff --git a/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts b/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
index 17b4a87b..54418239 100644
--- a/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
+++ b/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
@@ -1,9 +1,11 @@
import i18n from '~/src/config/i18n'
-import Jump from '@/store/TimelineSpace/Modals/Jump'
+import Jump, { JumpState, MUTATION_TYPES, Channel } from '@/store/TimelineSpace/Modals/Jump'
+import Hashtag from '~/src/types/hashtag'
+import { List } from 'megalodon'
describe('TimelineSpace/Modals/Jump', () => {
describe('mutations', () => {
- let state
+ let state: JumpState
beforeEach(() => {
state = {
modalOpen: true,
@@ -53,59 +55,55 @@ describe('TimelineSpace/Modals/Jump', () => {
describe('updateListChannel', () => {
it('should be updated', () => {
- const channelList = [
- {
- id: '0',
+ const admin: List = {
+ id: 0,
title: 'admin'
- },
- {
- id: '1',
+ }
+ const engineer: List = {
+ id: 1,
title: 'engineer'
- },
- {
- id: '2',
+ }
+ const designer: List = {
+ id: 2,
title: 'designer'
- }
- ]
- Jump.mutations.updateListChannel(state, channelList)
- expect(state.listChannelList).toEqual([
- {
- path: 'lists/0',
- name: '#admin'
- },
- {
- path: 'lists/1',
- name: '#engineer'
- },
- {
- path: 'lists/2',
- name: '#designer'
- }
- ])
+ }
+ const channelList = [admin, engineer, designer]
+ Jump.mutations![MUTATION_TYPES.UPDATE_LIST_CHANNEL](state, channelList)
+ const adminChannel: Channel = {
+ path: 'lists/0',
+ name: '#admin'
+ }
+ const engineerChannel: Channel = {
+ path: 'lists/1',
+ name: '#engineer'
+ }
+ const designerChannel: Channel = {
+ path: 'lists/2',
+ name: '#designer'
+ }
+ expect(state.listChannelList).toEqual([adminChannel, engineerChannel, designerChannel])
})
})
describe('updateTagChannel', () => {
it('should be updated', () => {
- const channelList = [
- {
- tagName: 'whalebird'
- },
- {
- tagName: 'tqrk'
- }
- ]
- Jump.mutations.updateTagChannel(state, channelList)
- expect(state.tagChannelList).toEqual([
- {
- name: '#whalebird',
- path: 'hashtag/whalebird'
- },
- {
- name: '#tqrk',
- path: 'hashtag/tqrk'
- }
- ])
+ const whalebird: Hashtag = {
+ tagName: 'whalebird'
+ }
+ const tqrk: Hashtag = {
+ tagName: 'tqrk'
+ }
+ const channelList = [whalebird, tqrk]
+ Jump.mutations![MUTATION_TYPES.UPDATE_TAG_CHANNEL](state, channelList)
+ const whalebirdChannel: Channel = {
+ name: '#whalebird',
+ path: 'hashtag/whalebird'
+ }
+ const tqrkChannel: Channel = {
+ name: '#tqrk',
+ path: 'hashtag/tqrk'
+ }
+ expect(state.tagChannelList).toEqual([whalebirdChannel, tqrkChannel])
})
})
})
diff --git a/src/renderer/store/TimelineSpace/Modals/Jump.js b/src/renderer/store/TimelineSpace/Modals/Jump.js
deleted file mode 100644
index 586e03f0..00000000
--- a/src/renderer/store/TimelineSpace/Modals/Jump.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import router from '@/router'
-import i18n from '~/src/config/i18n'
-
-const Jump = {
- namespaced: true,
- state: {
- modalOpen: false,
- channel: '',
- defaultChannelList: [
- {
- name: i18n.t('side_menu.home'),
- path: 'home'
- },
- {
- name: i18n.t('side_menu.notification'),
- path: 'notifications'
- },
- {
- name: i18n.t('side_menu.mention'),
- path: 'mentions'
- },
- {
- name: i18n.t('side_menu.favourite'),
- path: 'favourites'
- },
- {
- name: i18n.t('side_menu.local'),
- path: 'local'
- },
- {
- name: i18n.t('side_menu.public'),
- path: 'public'
- },
- {
- name: i18n.t('side_menu.hashtag'),
- path: 'hashtag'
- },
- {
- name: i18n.t('side_menu.search'),
- path: 'search'
- },
- {
- name: i18n.t('side_menu.direct'),
- path: 'direct-messages'
- }
- ],
- listChannelList: [],
- tagChannelList: [],
- selectedChannel: {
- name: i18n.t('side_menu.home'),
- path: 'home'
- }
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- updateChannel (state, value) {
- state.channel = value
- },
- changeSelected (state, value) {
- state.selectedChannel = value
- },
- updateListChannel (state, list) {
- state.listChannelList = list.map((l) => {
- return {
- name: `#${l.title}`,
- path: `lists/${l.id}`
- }
- })
- },
- updateTagChannel (state, tags) {
- state.tagChannelList = tags.map(t => {
- return {
- name: `#${t.tagName}`,
- path: `hashtag/${t.tagName}`
- }
- })
- }
- },
- actions: {
- jumpCurrentSelected ({ state, commit, rootState }) {
- commit('changeModal', false)
- router.push({ path: `/${rootState.TimelineSpace.account._id}/${state.selectedChannel.path}` })
- },
- jump ({ commit, rootState }, channel) {
- commit('changeModal', false)
- router.push({ path: `/${rootState.TimelineSpace.account._id}/${channel.path}` })
- },
- syncListChannel ({ commit, rootState }) {
- commit('updateListChannel', rootState.TimelineSpace.SideMenu.lists)
- },
- syncTagChannel ({ commit, rootState }) {
- commit('updateTagChannel', rootState.TimelineSpace.SideMenu.tags)
- }
- }
-}
-
-export default Jump
diff --git a/src/renderer/store/TimelineSpace/Modals/Jump.ts b/src/renderer/store/TimelineSpace/Modals/Jump.ts
new file mode 100644
index 00000000..c4aef049
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/Jump.ts
@@ -0,0 +1,133 @@
+import router from '@/router'
+import i18n from '~/src/config/i18n'
+import { Module, MutationTree, ActionTree } from 'vuex'
+import { List } from 'megalodon'
+import Hashtag from '~/src/types/hashtag'
+
+export interface Channel {
+ name: string,
+ path: string
+}
+
+export interface JumpState {
+ modalOpen: boolean,
+ channel: string,
+ defaultChannelList: Array,
+ listChannelList: Array,
+ tagChannelList: Array,
+ selectedChannel: Channel
+}
+
+const state = (): JumpState => ({
+ modalOpen: false,
+ channel: '',
+ defaultChannelList: [
+ {
+ name: i18n.t('side_menu.home'),
+ path: 'home'
+ },
+ {
+ name: i18n.t('side_menu.notification'),
+ path: 'notifications'
+ },
+ {
+ name: i18n.t('side_menu.mention'),
+ path: 'mentions'
+ },
+ {
+ name: i18n.t('side_menu.favourite'),
+ path: 'favourites'
+ },
+ {
+ name: i18n.t('side_menu.local'),
+ path: 'local'
+ },
+ {
+ name: i18n.t('side_menu.public'),
+ path: 'public'
+ },
+ {
+ name: i18n.t('side_menu.hashtag'),
+ path: 'hashtag'
+ },
+ {
+ name: i18n.t('side_menu.search'),
+ path: 'search'
+ },
+ {
+ name: i18n.t('side_menu.direct'),
+ path: 'direct-messages'
+ }
+ ],
+ listChannelList: [],
+ tagChannelList: [],
+ selectedChannel: {
+ name: i18n.t('side_menu.home'),
+ path: 'home'
+ }
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ UPDATE_CHANNEL: 'updateChannel',
+ CHANGE_SELECTED: 'changeSelected',
+ UPDATE_LIST_CHANNEL: 'updateListChannel',
+ UPDATE_TAG_CHANNEL: 'updateTagChannel'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.UPDATE_CHANNEL]: (state, channel: string) => {
+ state.channel = channel
+ },
+ [MUTATION_TYPES.CHANGE_SELECTED]: (state, channel: Channel) => {
+ state.selectedChannel = channel
+ },
+ [MUTATION_TYPES.UPDATE_LIST_CHANNEL]: (state, lists: Array) => {
+ state.listChannelList = lists.map((l) => {
+ const channel: Channel = {
+ name: `#${l.title}`,
+ path: `lists/${l.id}`
+ }
+ return channel
+ })
+ },
+ [MUTATION_TYPES.UPDATE_TAG_CHANNEL]: (state, tags: Array) => {
+ state.tagChannelList = tags.map(t => {
+ const channel: Channel = {
+ name: `#${t.tagName}`,
+ path: `hashtag/${t.tagName}`
+ }
+ return channel
+ })
+ }
+}
+
+// TODO: use type of rootState
+const actions: ActionTree = {
+ jumpCurrentSelected: ({ state, commit, rootState }) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, false)
+ router.push({ path: `/${rootState.TimelineSpace.account._id}/${state.selectedChannel.path}` })
+ },
+ jump: ({ commit, rootState }, channel: Channel) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, false)
+ router.push({ path: `/${rootState.TimelineSpace.account._id}/${channel.path}` })
+ },
+ syncListChannel: ({ commit, rootState }) => {
+ commit(MUTATION_TYPES.UPDATE_LIST_CHANNEL, rootState.TimelineSpace.SideMenu.lists)
+ },
+ syncTagChannel: ({ commit, rootState }) => {
+ commit(MUTATION_TYPES.UPDATE_TAG_CHANNEL, rootState.TimelineSpace.SideMenu.tags)
+ }
+}
+
+const Jump: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+}
+
+export default Jump
From 9670ee1dc8ef8d606cb0402f5e0dea1893bd79da Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Wed, 10 Apr 2019 20:58:11 +0900
Subject: [PATCH 03/11] refs #850 Replace AddListMember with typescript
---
.../store/TimelineSpace/Modals/Jump.spec.ts | 12 ++--
src/renderer/store/Preferences.ts | 18 +++--
src/renderer/store/Settings.ts | 9 ++-
src/renderer/store/TimelineSpace.ts | 13 +++-
src/renderer/store/TimelineSpace/Modals.ts | 16 +++--
.../TimelineSpace/Modals/AddListMember.js | 49 -------------
.../TimelineSpace/Modals/AddListMember.ts | 70 +++++++++++++++++++
src/renderer/store/index.ts | 27 ++++---
src/renderer/store/molecules.ts | 3 +
9 files changed, 139 insertions(+), 78 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/AddListMember.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/AddListMember.ts
diff --git a/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts b/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
index 54418239..a33349d0 100644
--- a/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
+++ b/spec/renderer/unit/store/TimelineSpace/Modals/Jump.spec.ts
@@ -56,16 +56,16 @@ describe('TimelineSpace/Modals/Jump', () => {
describe('updateListChannel', () => {
it('should be updated', () => {
const admin: List = {
- id: 0,
- title: 'admin'
+ id: 0,
+ title: 'admin'
}
const engineer: List = {
- id: 1,
- title: 'engineer'
+ id: 1,
+ title: 'engineer'
}
const designer: List = {
- id: 2,
- title: 'designer'
+ id: 2,
+ title: 'designer'
}
const channelList = [admin, engineer, designer]
Jump.mutations![MUTATION_TYPES.UPDATE_LIST_CHANNEL](state, channelList)
diff --git a/src/renderer/store/Preferences.ts b/src/renderer/store/Preferences.ts
index db7fa6b3..20e497eb 100644
--- a/src/renderer/store/Preferences.ts
+++ b/src/renderer/store/Preferences.ts
@@ -1,14 +1,22 @@
-import General from './Preferences/General'
-import Account from './Preferences/Account'
-import Language from './Preferences/Language'
-import Notification from './Preferences/Notification'
-import Appearance from './Preferences/Appearance'
+import General, { GeneralState } from './Preferences/General'
+import Account, { AccountState } from './Preferences/Account'
+import Language, { LanguageState } from './Preferences/Language'
+import Appearance, { AppearanceState } from './Preferences/Appearance'
+import Notification, { NotificationState } from './Preferences/Notification'
import { Module } from 'vuex'
export interface PreferencesState {}
const state = (): PreferencesState => ({})
+export interface PreferencesModuleState extends PreferencesState {
+ General: GeneralState,
+ Account: AccountState,
+ Language: LanguageState,
+ Notification: NotificationState,
+ Appearance: AppearanceState
+}
+
// TODO: use type of rootState
const Preferences: Module = {
namespaced: true,
diff --git a/src/renderer/store/Settings.ts b/src/renderer/store/Settings.ts
index 6eb8d2b7..902e8566 100644
--- a/src/renderer/store/Settings.ts
+++ b/src/renderer/store/Settings.ts
@@ -1,5 +1,5 @@
-import General from './Settings/General'
-import Timeline from './Settings/Timeline'
+import General, { GeneralState } from './Settings/General'
+import Timeline, { TimelineState } from './Settings/Timeline'
import { Module, MutationTree } from 'vuex'
export interface SettingsState {
@@ -20,6 +20,11 @@ const mutations: MutationTree = {
}
}
+export interface SettingsModuleState extends SettingsState {
+ General: GeneralState,
+ Timeline: TimelineState,
+}
+
// TODO: use type of rootState
const Settings: Module = {
namespaced: true,
diff --git a/src/renderer/store/TimelineSpace.ts b/src/renderer/store/TimelineSpace.ts
index d8fbae10..409fcf2f 100644
--- a/src/renderer/store/TimelineSpace.ts
+++ b/src/renderer/store/TimelineSpace.ts
@@ -1,9 +1,9 @@
import sanitizeHtml from 'sanitize-html'
import { ipcRenderer } from 'electron'
import Mastodon, { Account, Emoji, Instance, Status, Notification as NotificationType } from 'megalodon'
-import SideMenu from './TimelineSpace/SideMenu'
-import HeaderMenu from './TimelineSpace/HeaderMenu'
-import Modals from './TimelineSpace/Modals'
+import SideMenu, { SideMenuState } from './TimelineSpace/SideMenu'
+import HeaderMenu, { HeaderMenuState } from './TimelineSpace/HeaderMenu'
+import Modals, { ModalsModuleState } from './TimelineSpace/Modals'
import Contents from './TimelineSpace/Contents'
import router from '@/router'
import unreadSettings from '~/src/constants/unreadNotification'
@@ -416,6 +416,13 @@ const actions: ActionTree = {
}
}
+export interface TimelineSpaceModuleState extends TimelineSpaceState {
+ SideMenu: SideMenuState,
+ HeaderMenu: HeaderMenuState,
+ Modals: ModalsModuleState
+ // TODO: Contents: ContentsState
+}
+
const TimelineSpace: Module = {
namespaced: true,
modules: {
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 6bfb4685..65ae9d9e 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -1,19 +1,25 @@
import NewToot from './Modals/NewToot'
import ImageViewer from './Modals/ImageViewer'
-import Jump from './Modals/Jump'
+import Jump, { JumpState } from './Modals/Jump'
import ListMembership from './Modals/ListMembership'
-import AddListMember from './Modals/AddListMember'
+import AddListMember, { AddListMemberState } from './Modals/AddListMember'
import MuteConfirm from './Modals/MuteConfirm'
import Shortcut from './Modals/Shortcut'
import Report from './Modals/Report'
import { Module, GetterTree } from 'vuex'
+import { RootState } from '@/store/index'
export interface ModalsState {}
+export interface ModalsModuleState extends ModalsState {
+ Jump: JumpState,
+ AddListMember: AddListMemberState
+}
+
const state = (): ModalsState => ({})
-// TODO: use type of rootState
-const getters: GetterTree = {
+
+const getters: GetterTree = {
modalOpened: (_state, _getters, rootState) => {
const imageViewer = rootState.TimelineSpace.Modals.ImageViewer.modalOpen
const newToot = rootState.TimelineSpace.Modals.NewToot.modalOpen
@@ -27,7 +33,7 @@ const getters: GetterTree = {
}
}
-const Modals: Module = {
+const Modals: Module = {
namespaced: true,
modules: {
ImageViewer,
diff --git a/src/renderer/store/TimelineSpace/Modals/AddListMember.js b/src/renderer/store/TimelineSpace/Modals/AddListMember.js
deleted file mode 100644
index b0368fdb..00000000
--- a/src/renderer/store/TimelineSpace/Modals/AddListMember.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import Mastodon from 'megalodon'
-
-export default {
- namespaced: true,
- state: {
- modalOpen: false,
- accounts: [],
- targetListId: null
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- updateAccounts (state, accounts) {
- state.accounts = accounts
- },
- setListId (state, id) {
- state.targetListId = id
- }
- },
- actions: {
- changeModal ({ commit }, value) {
- commit('changeModal', value)
- },
- search ({ commit, rootState }, name) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.get('/accounts/search', {
- q: name,
- following: true
- })
- .then(res => {
- commit('updateAccounts', res.data)
- return res.data
- })
- },
- add ({ state, rootState }, account) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.post(`/lists/${state.targetListId}/accounts`, {
- account_ids: [account.id]
- })
- }
- }
-}
diff --git a/src/renderer/store/TimelineSpace/Modals/AddListMember.ts b/src/renderer/store/TimelineSpace/Modals/AddListMember.ts
new file mode 100644
index 00000000..84ccad6a
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/AddListMember.ts
@@ -0,0 +1,70 @@
+import Mastodon, { Account, Response } from 'megalodon'
+import { Module, MutationTree, ActionTree } from 'vuex'
+
+export interface AddListMemberState {
+ modalOpen: boolean,
+ accounts: Array,
+ targetListId: number | null
+}
+
+const state = (): AddListMemberState => ({
+ modalOpen: false,
+ accounts: [],
+ targetListId: null
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ UPDATE_ACCOUNTS: 'updateAccounts',
+ SET_LIST_ID: 'setListId'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.UPDATE_ACCOUNTS]: (state, accounts: Array) => {
+ state.accounts = accounts
+ },
+ [MUTATION_TYPES.SET_LIST_ID]: (state, id: number) => {
+ state.targetListId = id
+ }
+}
+
+// TODO: use type of rootState
+const actions: ActionTree = {
+ changeModal: ({ commit }, value: boolean) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, value)
+ },
+ search: async ({ commit, rootState }, name: string): Promise> => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response> = await client.get>('/accounts/search', {
+ q: name,
+ following: true
+ })
+ commit(MUTATION_TYPES.UPDATE_ACCOUNTS, res.data)
+ return res.data
+ },
+ add: async ({ state, rootState }, account: Account): Promise<{}> => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response<{}> = await client.post<{}>(`/lists/${state.targetListId}/accounts`, {
+ account_ids: [account.id]
+ })
+ return res.data
+ }
+}
+
+const AddListMember: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+}
+
+export default AddListMember
diff --git a/src/renderer/store/index.ts b/src/renderer/store/index.ts
index 4e0e0f29..dd830f07 100644
--- a/src/renderer/store/index.ts
+++ b/src/renderer/store/index.ts
@@ -2,17 +2,28 @@ import Vue from 'vue'
import Vuex from 'vuex'
import createLogger from 'vuex/dist/logger'
-import App from './App'
-import GlobalHeader from './GlobalHeader'
-import Login from './Login'
-import Authorize from './Authorize'
-import TimelineSpace from './TimelineSpace'
-import Preferences from './Preferences'
-import Settings from './Settings'
-import molecules from './molecules'
+import App, { AppState } from './App'
+import GlobalHeader, { GlobalHeaderState } from './GlobalHeader'
+import Login, { LoginState } from './Login'
+import Authorize, { AuthorizeState } from './Authorize'
+import TimelineSpace, { TimelineSpaceModuleState } from './TimelineSpace'
+import Preferences, { PreferencesModuleState } from './Preferences'
+import Settings, { SettingsModuleState } from './Settings'
+import molecules, { MoleculesModuleState } from './molecules'
Vue.use(Vuex)
+export interface RootState {
+ App: AppState,
+ GlobalHeader: GlobalHeaderState,
+ Login: LoginState,
+ Authorize: AuthorizeState,
+ TimelineSpace: TimelineSpaceModuleState,
+ Preferences: PreferencesModuleState,
+ Settings: SettingsModuleState,
+ molecules: MoleculesModuleState
+}
+
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
plugins: process.env.NODE_ENV !== 'production'
diff --git a/src/renderer/store/molecules.ts b/src/renderer/store/molecules.ts
index f0ee7f2a..82fbdfe9 100644
--- a/src/renderer/store/molecules.ts
+++ b/src/renderer/store/molecules.ts
@@ -1,5 +1,8 @@
import Toot from './molecules/Toot'
+export interface MoleculesModuleState {
+}
+
export default {
namespaced: true,
modules: {
From 7c01aa877a3647aa6283626740267e62f9fa2d68 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Wed, 10 Apr 2019 21:18:22 +0900
Subject: [PATCH 04/11] refs #850 Replace ImageViewer with typescript
---
src/renderer/store/TimelineSpace/Modals.ts | 5 +-
.../store/TimelineSpace/Modals/ImageViewer.js | 78 -------------
.../store/TimelineSpace/Modals/ImageViewer.ts | 108 ++++++++++++++++++
3 files changed, 111 insertions(+), 80 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/ImageViewer.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 65ae9d9e..4fc079de 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -1,5 +1,5 @@
import NewToot from './Modals/NewToot'
-import ImageViewer from './Modals/ImageViewer'
+import ImageViewer, { ImageViewerState } from './Modals/ImageViewer'
import Jump, { JumpState } from './Modals/Jump'
import ListMembership from './Modals/ListMembership'
import AddListMember, { AddListMemberState } from './Modals/AddListMember'
@@ -13,7 +13,8 @@ export interface ModalsState {}
export interface ModalsModuleState extends ModalsState {
Jump: JumpState,
- AddListMember: AddListMemberState
+ AddListMember: AddListMemberState,
+ ImageViewer: ImageViewerState
}
const state = (): ModalsState => ({})
diff --git a/src/renderer/store/TimelineSpace/Modals/ImageViewer.js b/src/renderer/store/TimelineSpace/Modals/ImageViewer.js
deleted file mode 100644
index d0cd2d7b..00000000
--- a/src/renderer/store/TimelineSpace/Modals/ImageViewer.js
+++ /dev/null
@@ -1,78 +0,0 @@
-const ImageViewer = {
- namespaced: true,
- state: {
- modalOpen: false,
- currentIndex: -1,
- mediaList: [],
- loading: false
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- changeCurrentIndex (state, currentIndex) {
- state.currentIndex = currentIndex
- },
- changeMedliaList (state, mediaList) {
- state.mediaList = mediaList
- },
- incrementIndex (state) {
- state.currentIndex++
- },
- decrementIndex (state) {
- state.currentIndex--
- },
- loading (state, value) {
- state.loading = value
- }
- },
- actions: {
- openModal ({ commit }, { currentIndex, mediaList }) {
- commit('changeModal', true)
- commit('changeCurrentIndex', currentIndex)
- commit('changeMedliaList', mediaList)
- commit('loading', true)
- },
- closeModal ({ commit }) {
- commit('changeModal', false)
- commit('changeCurrentIndex', -1)
- commit('changeMedliaList', [])
- commit('loading', false)
- },
- incrementIndex ({ commit }) {
- commit('incrementIndex')
- commit('loading', true)
- },
- decrementIndex ({ commit }) {
- commit('decrementIndex')
- commit('loading', true)
- },
- async loaded ({ commit }) {
- commit('loading', false)
- }
- },
- getters: {
- imageURL (state) {
- if (state.currentIndex >= 0) {
- return state.mediaList[state.currentIndex].url
- }
- },
- imageType (state) {
- if (state.currentIndex >= 0) {
- return state.mediaList[state.currentIndex].type
- }
- },
- showLeft (state) {
- const notFirst = (state.currentIndex > 0)
- const isManyItem = (state.mediaList.length > 1)
- return (notFirst && isManyItem)
- },
- showRight (state) {
- const notLast = (state.currentIndex < (state.mediaList.length - 1))
- const isManyItem = (state.mediaList.length > 1)
- return (notLast && isManyItem)
- }
- }
-}
-
-export default ImageViewer
diff --git a/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts b/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
new file mode 100644
index 00000000..8fd7270b
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
@@ -0,0 +1,108 @@
+import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'
+import { Attachment } from 'megalodon'
+import { RootState } from '@/store';
+
+export interface ImageViewerState {
+ modalOpen: boolean,
+ currentIndex: number,
+ mediaList: Array,
+ loading: boolean
+}
+
+const state = (): ImageViewerState => ({
+ modalOpen: false,
+ currentIndex: -1,
+ mediaList: [],
+ loading: false
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ CHANGE_CURRENT_INDEX: 'changeCurrentIndex',
+ CHANGE_MEDIA_LIST: 'changeMediaList',
+ INCREMENT_INDEX: 'incrementIndex',
+ DECREMENT_INDEX: 'decrementIndex',
+ CHANGE_LOADING: 'changeLoading'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.CHANGE_CURRENT_INDEX]: (state, currentIndex: number) => {
+ state.currentIndex = currentIndex
+ },
+ [MUTATION_TYPES.CHANGE_MEDIA_LIST]: (state, mediaList: Array) => {
+ state.mediaList = mediaList
+ },
+ [MUTATION_TYPES.INCREMENT_INDEX]: (state) => {
+ state.currentIndex++
+ },
+ [MUTATION_TYPES.DECREMENT_INDEX]: (state) => {
+ state.currentIndex--
+ },
+ [MUTATION_TYPES.CHANGE_LOADING]: (state, value: boolean) => {
+ state.loading = value
+ }
+}
+
+const actions: ActionTree = {
+ openModal: ({ commit }, { currentIndex, mediaList }) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, true)
+ commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, currentIndex as number)
+ commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, mediaList as Array)
+ commit(MUTATION_TYPES.CHANGE_LOADING, true)
+ },
+ closeModal: ({ commit }) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, false)
+ commit(MUTATION_TYPES.CHANGE_CURRENT_INDEX, -1)
+ commit(MUTATION_TYPES.CHANGE_MEDIA_LIST, [])
+ commit(MUTATION_TYPES.CHANGE_LOADING, false)
+ },
+ incrementIndex: ({ commit }) => {
+ commit(MUTATION_TYPES.INCREMENT_INDEX)
+ commit(MUTATION_TYPES.CHANGE_LOADING, true)
+ },
+ decrementIndex: ({ commit }) => {
+ commit(MUTATION_TYPES.DECREMENT_INDEX)
+ commit(MUTATION_TYPES.CHANGE_LOADING, true)
+ },
+ loaded: ({ commit }) => {
+ commit(MUTATION_TYPES.CHANGE_LOADING, false)
+ }
+}
+
+const getters: GetterTree = {
+ imageURL: (state): string | null => {
+ if (state.currentIndex >= 0) {
+ return state.mediaList[state.currentIndex].url
+ }
+ return null
+ },
+ imageType: (state): string | null => {
+ if (state.currentIndex >= 0) {
+ return state.mediaList[state.currentIndex].type
+ }
+ return null
+ },
+ showLeft: (state): boolean => {
+ const notFirst = (state.currentIndex > 0)
+ const isManyItem = (state.mediaList.length > 1)
+ return (notFirst && isManyItem)
+ },
+ showRight: (state): boolean => {
+ const notLast = (state.currentIndex < (state.mediaList.length - 1))
+ const isManyItem = (state.mediaList.length > 1)
+ return (notLast && isManyItem)
+ }
+}
+
+const ImageViewer: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions,
+ getters: getters
+}
+
+export default ImageViewer
From 921d3f07e334f90883932d823164539224ca1e60 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Wed, 10 Apr 2019 21:57:37 +0900
Subject: [PATCH 05/11] refs #850 Replace ListMembership with typescript
---
package-lock.json | 12 ++-
package.json | 3 +-
src/renderer/store/TimelineSpace/Modals.ts | 1 -
.../store/TimelineSpace/Modals/ImageViewer.ts | 2 +-
.../TimelineSpace/Modals/ListMembership.js | 80 ---------------
.../TimelineSpace/Modals/ListMembership.ts | 98 +++++++++++++++++++
6 files changed, 110 insertions(+), 86 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/ListMembership.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/ListMembership.ts
diff --git a/package-lock.json b/package-lock.json
index e513cfe6..6dab7ad2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2003,6 +2003,12 @@
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.123",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz",
+ "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==",
+ "dev": true
+ },
"@types/node": {
"version": "11.11.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.4.tgz",
@@ -13466,9 +13472,9 @@
"dev": true
},
"megalodon": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/megalodon/-/megalodon-0.6.2.tgz",
- "integrity": "sha512-EmNs0M6e2AiX9hutoiXo0FUkghZ1HdyLpS8mVkrMMN8btBR2x1hVrAF/8WAFePeJQrEMYjRyQSEJfykJ/4rwaQ==",
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/megalodon/-/megalodon-0.6.3.tgz",
+ "integrity": "sha512-rxh9Kbbwm9Hnn/e8xdzH2Fw5kD/TamgyGFEzOcsnKCqF4iI2qHuojCBm7KeWohgRlwJ9oq7QYVReEVTipqI8kQ==",
"requires": {
"@types/oauth": "0.9.1",
"@types/request": "2.48.1",
diff --git a/package.json b/package.json
index 381b43ec..2865afcc 100644
--- a/package.json
+++ b/package.json
@@ -145,7 +145,7 @@
"i18next-sync-fs-backend": "^1.1.0",
"is-empty": "^1.2.0",
"lodash": "^4.17.11",
- "megalodon": "0.6.2",
+ "megalodon": "0.6.3",
"moment": "^2.21.0",
"mousetrap": "^1.6.2",
"nedb": "^1.8.0",
@@ -173,6 +173,7 @@
"@mapbox/stylelint-processor-arbitrary-tags": "^0.2.0",
"@types/i18next": "^12.1.0",
"@types/jest": "^24.0.11",
+ "@types/lodash": "^4.14.123",
"@types/node": "^11.11.4",
"@typescript-eslint/eslint-plugin": "^1.5.0",
"@typescript-eslint/parser": "^1.5.0",
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 4fc079de..f72b2027 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -19,7 +19,6 @@ export interface ModalsModuleState extends ModalsState {
const state = (): ModalsState => ({})
-
const getters: GetterTree = {
modalOpened: (_state, _getters, rootState) => {
const imageViewer = rootState.TimelineSpace.Modals.ImageViewer.modalOpen
diff --git a/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts b/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
index 8fd7270b..498cb2ae 100644
--- a/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
+++ b/src/renderer/store/TimelineSpace/Modals/ImageViewer.ts
@@ -1,6 +1,6 @@
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'
import { Attachment } from 'megalodon'
-import { RootState } from '@/store';
+import { RootState } from '@/store'
export interface ImageViewerState {
modalOpen: boolean,
diff --git a/src/renderer/store/TimelineSpace/Modals/ListMembership.js b/src/renderer/store/TimelineSpace/Modals/ListMembership.js
deleted file mode 100644
index 9d2249cb..00000000
--- a/src/renderer/store/TimelineSpace/Modals/ListMembership.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import Mastodon from 'megalodon'
-import _ from 'lodash'
-
-const ListMembership = {
- namespaced: true,
- state: {
- modalOpen: false,
- account: null,
- lists: [],
- belongToLists: []
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- changeAccount (state, account) {
- state.account = account
- },
- changeBelongToLists (state, lists) {
- state.belongToLists = lists
- },
- changeLists (state, lists) {
- state.lists = lists
- }
- },
- actions: {
- changeModal ({ commit }, value) {
- commit('changeModal', value)
- },
- setAccount ({ commit }, account) {
- commit('changeAccount', account)
- },
- fetchListMembership ({ commit, rootState }, account) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.get(`/accounts/${account.id}/lists`)
- .then(res => {
- commit('changeBelongToLists', res.data.map(l => l.id))
- return res.data
- })
- },
- fetchLists ({ commit, rootState }) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.get('/lists')
- .then(res => {
- commit('changeLists', res.data)
- return res.data
- })
- },
- async changeBelongToLists ({ rootState, commit, state }, belongToLists) {
- // Calcurate diff
- const removedLists = _.difference(state.belongToLists, belongToLists)
- const addedLists = _.difference(belongToLists, state.belongToLists)
- commit('changeBelongToLists', belongToLists)
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- const removedPromise = removedLists.map(id => {
- return client.del(`/lists/${id}/accounts`, {
- account_ids: [state.account.id]
- })
- })
- const addedPromise = addedLists.map(id => {
- return client.post(`/lists/${id}/accounts`, {
- account_ids: [state.account.id]
- })
- })
- const res = await Promise.all(removedPromise.concat(addedPromise))
- return res
- }
- }
-}
-
-export default ListMembership
diff --git a/src/renderer/store/TimelineSpace/Modals/ListMembership.ts b/src/renderer/store/TimelineSpace/Modals/ListMembership.ts
new file mode 100644
index 00000000..68d5e6df
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/ListMembership.ts
@@ -0,0 +1,98 @@
+import Mastodon, { Account, List, Response } from 'megalodon'
+import lodash from 'lodash'
+import { Module, MutationTree, ActionTree } from 'vuex'
+import { RootState } from '@/store'
+
+export interface ListMembershipState {
+ modalOpen: boolean,
+ account: Account | null,
+ lists: Array,
+ belongToLists: Array
+}
+
+const state = (): ListMembershipState => ({
+ modalOpen: false,
+ account: null,
+ lists: [],
+ belongToLists: []
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ CHANGE_ACCOUNT: 'changeAccount',
+ CHANGE_BELONG_TO_LISTS: 'changeBelongToLists',
+ CHANGE_LISTS: 'changeLists'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.CHANGE_ACCOUNT]: (state, account: Account) => {
+ state.account = account
+ },
+ [MUTATION_TYPES.CHANGE_BELONG_TO_LISTS]: (state, lists: Array) => {
+ state.belongToLists = lists
+ },
+ [MUTATION_TYPES.CHANGE_LISTS]: (state, lists: Array) => {
+ state.lists = lists
+ }
+}
+
+const actions: ActionTree = {
+ changeModal: ({ commit }, value: boolean) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, value)
+ },
+ setAccount: ({ commit }, account: Account) => {
+ commit(MUTATION_TYPES.CHANGE_ACCOUNT, account)
+ },
+ fetchListMembership: async ({ commit, rootState }, account: Account) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response> = await client.get>(`/accounts/${account.id}/lists`)
+ commit(MUTATION_TYPES.CHANGE_BELONG_TO_LISTS, res.data.map(l => l.id))
+ return res.data
+ },
+ fetchLists: async ({ commit, rootState }) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response> = await client.get>('/lists')
+ commit(MUTATION_TYPES.CHANGE_LISTS, res.data)
+ return res.data
+ },
+ changeBelongToLists: async ({ rootState, commit, state }, belongToLists: Array) => {
+ // Calcurate diff
+ const removedLists = lodash.difference(state.belongToLists, belongToLists)
+ const addedLists = lodash.difference(belongToLists, state.belongToLists)
+ commit(MUTATION_TYPES.CHANGE_BELONG_TO_LISTS, belongToLists)
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const removedPromise = removedLists.map(id => {
+ return client.del<{}>(`/lists/${id}/accounts`, {
+ account_ids: [state.account!.id]
+ })
+ })
+ const addedPromise = addedLists.map(id => {
+ return client.post<{}>(`/lists/${id}/accounts`, {
+ account_ids: [state.account!.id]
+ })
+ })
+ const res = await Promise.all(removedPromise.concat(addedPromise))
+ return res
+ }
+}
+
+const ListMembership: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+}
+
+export default ListMembership
From 20f3dcba227bc100877439b5ef6b54b5c429ffad Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Wed, 10 Apr 2019 22:07:02 +0900
Subject: [PATCH 06/11] refs #850 Replace MuteConfirm with typescript
---
src/renderer/store/TimelineSpace/Modals.ts | 8 ++-
.../store/TimelineSpace/Modals/MuteConfirm.js | 39 -------------
.../store/TimelineSpace/Modals/MuteConfirm.ts | 57 +++++++++++++++++++
3 files changed, 62 insertions(+), 42 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/MuteConfirm.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/MuteConfirm.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index f72b2027..3baf45a8 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -1,9 +1,9 @@
import NewToot from './Modals/NewToot'
import ImageViewer, { ImageViewerState } from './Modals/ImageViewer'
import Jump, { JumpState } from './Modals/Jump'
-import ListMembership from './Modals/ListMembership'
+import ListMembership, { ListMembershipState } from './Modals/ListMembership'
import AddListMember, { AddListMemberState } from './Modals/AddListMember'
-import MuteConfirm from './Modals/MuteConfirm'
+import MuteConfirm, { MuteConfirmState } from './Modals/MuteConfirm'
import Shortcut from './Modals/Shortcut'
import Report from './Modals/Report'
import { Module, GetterTree } from 'vuex'
@@ -14,7 +14,9 @@ export interface ModalsState {}
export interface ModalsModuleState extends ModalsState {
Jump: JumpState,
AddListMember: AddListMemberState,
- ImageViewer: ImageViewerState
+ ImageViewer: ImageViewerState,
+ ListMembership: ListMembershipState,
+ MuteConfirm: MuteConfirmState
}
const state = (): ModalsState => ({})
diff --git a/src/renderer/store/TimelineSpace/Modals/MuteConfirm.js b/src/renderer/store/TimelineSpace/Modals/MuteConfirm.js
deleted file mode 100644
index c3934245..00000000
--- a/src/renderer/store/TimelineSpace/Modals/MuteConfirm.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Mastodon from 'megalodon'
-
-export default {
- namespaced: true,
- state: {
- modalOpen: false,
- account: {}
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- changeAccount (state, account) {
- state.account = account
- }
- },
- actions: {
- changeModal ({ commit }, value) {
- commit('changeModal', value)
- },
- changeAccount ({ commit }, account) {
- commit('changeAccount', account)
- },
- async submit ({ state, rootState, dispatch }, notify) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.post(`/accounts/${state.account.id}/mute`, {
- notifications: notify
- })
- .then(res => {
- // Reload relationship
- dispatch('TimelineSpace/Contents/SideBar/AccountProfile/fetchRelationship', state.account, { root: true })
- return res.data
- })
- }
- }
-}
diff --git a/src/renderer/store/TimelineSpace/Modals/MuteConfirm.ts b/src/renderer/store/TimelineSpace/Modals/MuteConfirm.ts
new file mode 100644
index 00000000..3ef17944
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/MuteConfirm.ts
@@ -0,0 +1,57 @@
+import Mastodon, { Account, Response, Relationship } from 'megalodon'
+import { Module, MutationTree, ActionTree } from 'vuex'
+import { RootState } from '@/store'
+
+export interface MuteConfirmState {
+ modalOpen: boolean,
+ account: Account | null
+}
+
+const state = (): MuteConfirmState => ({
+ modalOpen: false,
+ account: null
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ CHANGE_ACCOUNT: 'changeAccount'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.CHANGE_ACCOUNT]: (state, account: Account) => {
+ state.account = account
+ }
+}
+
+const actions: ActionTree = {
+ changeModal: ({ commit }, value: boolean) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, value)
+ },
+ changeAccount: ({ commit }, account: Account) => {
+ commit(MUTATION_TYPES.CHANGE_ACCOUNT, account)
+ },
+ submit: async ({ state, rootState, dispatch }, notify: boolean) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response = await client.post(`/accounts/${state.account!.id}/mute`, {
+ notifications: notify
+ })
+ // Reload relationship
+ dispatch('TimelineSpace/Contents/SideBar/AccountProfile/fetchRelationship', state.account, { root: true })
+ return res.data
+ }
+}
+
+const MuteConfirm: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+}
+
+export default MuteConfirm
From 0208e7c22ac6a3236b1bf65198325f091ff3b9bc Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Apr 2019 00:06:43 +0900
Subject: [PATCH 07/11] refs #850 Replace NewToot and Status with typescript
---
src/renderer/store/TimelineSpace/Modals.ts | 5 +-
.../store/TimelineSpace/Modals/NewToot.js | 204 --------------
.../store/TimelineSpace/Modals/NewToot.ts | 249 ++++++++++++++++++
.../TimelineSpace/Modals/NewToot/Status.js | 73 -----
.../TimelineSpace/Modals/NewToot/Status.ts | 104 ++++++++
tsconfig.json | 6 +-
6 files changed, 361 insertions(+), 280 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/NewToot.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/NewToot.ts
delete mode 100644 src/renderer/store/TimelineSpace/Modals/NewToot/Status.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 3baf45a8..5c0392ae 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -1,4 +1,4 @@
-import NewToot from './Modals/NewToot'
+import NewToot, { NewTootModuleState } from './Modals/NewToot'
import ImageViewer, { ImageViewerState } from './Modals/ImageViewer'
import Jump, { JumpState } from './Modals/Jump'
import ListMembership, { ListMembershipState } from './Modals/ListMembership'
@@ -16,7 +16,8 @@ export interface ModalsModuleState extends ModalsState {
AddListMember: AddListMemberState,
ImageViewer: ImageViewerState,
ListMembership: ListMembershipState,
- MuteConfirm: MuteConfirmState
+ MuteConfirm: MuteConfirmState,
+ NewToot: NewTootModuleState
}
const state = (): ModalsState => ({})
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot.js b/src/renderer/store/TimelineSpace/Modals/NewToot.js
deleted file mode 100644
index 4150b724..00000000
--- a/src/renderer/store/TimelineSpace/Modals/NewToot.js
+++ /dev/null
@@ -1,204 +0,0 @@
-import Mastodon from 'megalodon'
-import { ipcRenderer } from 'electron'
-import Visibility from '~/src/constants/visibility'
-import Status from './NewToot/Status'
-
-const NewToot = {
- namespaced: true,
- modules: {
- Status
- },
- state: {
- modalOpen: false,
- initialStatus: '',
- initialSpoiler: '',
- replyToMessage: null,
- blockSubmit: false,
- attachedMedias: [],
- visibility: Visibility.Public.value,
- sensitive: false,
- attachedMediaId: 0,
- pinedHashtag: false,
- hashtags: []
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- },
- setReplyTo (state, message) {
- state.replyToMessage = message
- },
- updateInitialStatus (state, status) {
- state.initialStatus = status
- },
- updateInitialSpoiler (state, cw) {
- state.initialSpoiler = cw
- },
- changeBlockSubmit (state, value) {
- state.blockSubmit = value
- },
- appendAttachedMedias (state, media) {
- state.attachedMedias = state.attachedMedias.concat([media])
- },
- clearAttachedMedias (state) {
- state.attachedMedias = []
- },
- removeMedia (state, media) {
- state.attachedMedias = state.attachedMedias.filter(m => m.id !== media.id)
- },
- /**
- * changeVisibilityValue
- * Update visibility using direct value
- * @param state vuex state object
- * @param value visibility value
- */
- changeVisibilityValue (state, value) {
- state.visibility = value
- },
- changeSensitive (state, value) {
- state.sensitive = value
- },
- updateMediaId (state, value) {
- state.attachedMediaId = value
- },
- changePinedHashtag (state, value) {
- state.pinedHashtag = value
- },
- updateHashtags (state, tags) {
- state.hashtags = tags
- }
- },
- getters: {
- hashtagInserting (state) {
- return !state.replyToMessage && state.pinedHashtag
- }
- },
- actions: {
- async updateMedia ({ rootState }, media) {
- if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
- throw new AuthenticationError()
- }
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return Promise.all(
- Object.keys(media).map(async id => {
- return client.put(`/media/${id}`, { description: media[id] })
- }
- )).catch(err => {
- console.error(err)
- throw err
- })
- },
- async postToot ({ state, commit, rootState }, form) {
- if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
- throw new AuthenticationError()
- }
- if (state.blockSubmit) {
- return
- }
- commit('changeBlockSubmit', true)
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.post('/statuses', form)
- .then(res => {
- ipcRenderer.send('toot-action-sound')
- return res.data
- })
- .finally(() => {
- commit('changeBlockSubmit', false)
- })
- },
- openReply ({ commit, rootState }, message) {
- commit('setReplyTo', message)
- const mentionAccounts = [message.account.acct].concat(message.mentions.map(a => a.acct))
- .filter((a, i, self) => self.indexOf(a) === i)
- .filter((a) => a !== rootState.TimelineSpace.account.username)
- commit('updateInitialStatus', `${mentionAccounts.map(m => `@${m}`).join(' ')} `)
- commit('updateInitialSpoiler', message.spoiler_text)
- commit('changeModal', true)
- let value = Visibility.Public.value
- Object.keys(Visibility).map(key => {
- const target = Visibility[key]
- if (target.key === message.visibility) {
- value = target.value
- }
- })
- commit('changeVisibilityValue', value)
- },
- openModal ({ dispatch, commit, state }) {
- if (!state.replyToMessage && state.pinedHashtag) {
- commit('updateInitialStatus', state.hashtags.map(t => ` #${t.name}`).join())
- }
- commit('changeModal', true)
- dispatch('fetchVisibility')
- },
- closeModal ({ commit }) {
- commit('changeModal', false)
- commit('updateInitialStatus', '')
- commit('updateInitialSpoiler', '')
- commit('setReplyTo', null)
- commit('changeBlockSubmit', false)
- commit('clearAttachedMedias')
- commit('changeSensitive', false)
- commit('changeVisibilityValue', Visibility.Public.value)
- },
- uploadImage ({ commit, rootState }, image) {
- commit('changeBlockSubmit', true)
- if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
- throw new AuthenticationError()
- }
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- const formData = new FormData()
- formData.append('file', image)
- return client.post('/media', formData)
- .then(res => {
- commit('changeBlockSubmit', false)
- if (res.data.type === 'unknown') throw new UnknownTypeError()
- commit('appendAttachedMedias', res.data)
- return res.data
- })
- .catch(err => {
- commit('changeBlockSubmit', false)
- console.error(err)
- throw err
- })
- },
- incrementMediaId ({ commit, state }) {
- commit('updateMediaId', state.attachedMediaId + 1)
- },
- resetMediaId ({ commit }) {
- commit('updateMediaId', 0)
- },
- updateHashtags ({ commit, state }, tags) {
- if (state.pinedHashtag) {
- commit('updateHashtags', tags)
- }
- },
- fetchVisibility ({ commit, rootState }) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.get('/accounts/verify_credentials')
- .then(res => {
- const visibility = Object.values(Visibility).find((v) => {
- return v.key === res.data.source.privacy
- })
- commit('changeVisibilityValue', visibility.value)
- return res.data
- })
- }
- }
-}
-
-export default NewToot
-
-class AuthenticationError {}
-class UnknownTypeError {}
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot.ts b/src/renderer/store/TimelineSpace/Modals/NewToot.ts
new file mode 100644
index 00000000..68f16c4e
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/NewToot.ts
@@ -0,0 +1,249 @@
+import Mastodon, { Status, Attachment, Tag, Response, Account } from 'megalodon'
+import { ipcRenderer } from 'electron'
+import Visibility from '~/src/constants/visibility'
+import TootStatus, { StatusState } from './NewToot/Status'
+import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'
+import { RootState } from '@/store'
+import VisibilityType from '~/src/types/visibility'
+
+export interface NewTootState {
+ modalOpen: boolean,
+ initialStatus: string,
+ initialSpoiler: string,
+ replyToMessage: Status | null,
+ blockSubmit: boolean,
+ attachedMedias: Array,
+ visibility: number,
+ sensitive: boolean,
+ attachedMediaId: number,
+ pinedHashtag: boolean,
+ hashtags: Array
+}
+
+export interface NewTootModuleState extends NewTootState {
+ Status: StatusState
+}
+
+const state = (): NewTootState => ({
+ modalOpen: false,
+ initialStatus: '',
+ initialSpoiler: '',
+ replyToMessage: null,
+ blockSubmit: false,
+ attachedMedias: [],
+ visibility: Visibility.Public.value,
+ sensitive: false,
+ attachedMediaId: 0,
+ pinedHashtag: false,
+ hashtags: []
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal',
+ SET_REPLY_TO: 'setReplyTo',
+ UPDATE_INITIAL_STATUS: 'updateInitialStatus',
+ UPDATE_INITIAL_SPOILER: 'updateInitialSpoiler',
+ CHANGE_BLOCK_SUBMIT: 'changeBlockSubmit',
+ APPEND_ATTACHED_MEDIAS: 'appendAttachedMedias',
+ CLEAR_ATTACHED_MEDIAS: 'clearAttachedMedias',
+ REMOVE_MEDIA: 'removeMedia',
+ CHANGE_VISIBILITY_VALUE: 'changeVisibilityValue',
+ CHANGE_SENSITIVE: 'changeSensitive',
+ UPDATE_MEDIA_ID: 'updateMediaId',
+ CHANGE_PINED_HASHTAG: 'changePinedHashtag',
+ UPDATE_HASHTAGS: 'updateHashtags'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.SET_REPLY_TO]: (state, message: Status) => {
+ state.replyToMessage = message
+ },
+ [MUTATION_TYPES.UPDATE_INITIAL_STATUS]: (state, status: string) => {
+ state.initialStatus = status
+ },
+ [MUTATION_TYPES.UPDATE_INITIAL_SPOILER]: (state, cw: string) => {
+ state.initialSpoiler = cw
+ },
+ [MUTATION_TYPES.CHANGE_BLOCK_SUBMIT]: (state, value: boolean) => {
+ state.blockSubmit = value
+ },
+ [MUTATION_TYPES.APPEND_ATTACHED_MEDIAS]: (state, media: Attachment) => {
+ state.attachedMedias = state.attachedMedias.concat([media])
+ },
+ [MUTATION_TYPES.CLEAR_ATTACHED_MEDIAS]: (state) => {
+ state.attachedMedias = []
+ },
+ [MUTATION_TYPES.REMOVE_MEDIA]: (state, media: Attachment) => {
+ state.attachedMedias = state.attachedMedias.filter(m => m.id !== media.id)
+ },
+ /**
+ * changeVisibilityValue
+ * Update visibility using direct value
+ * @param state vuex state object
+ * @param value visibility value
+ */
+ [MUTATION_TYPES.CHANGE_VISIBILITY_VALUE]: (state, value: number) => {
+ state.visibility = value
+ },
+ [MUTATION_TYPES.CHANGE_SENSITIVE]: (state, value: boolean) => {
+ state.sensitive = value
+ },
+ [MUTATION_TYPES.UPDATE_MEDIA_ID]: (state, value: number) => {
+ state.attachedMediaId = value
+ },
+ [MUTATION_TYPES.CHANGE_PINED_HASHTAG]: (state, value: boolean) => {
+ state.pinedHashtag = value
+ },
+ [MUTATION_TYPES.UPDATE_HASHTAGS]: (state, tags: Array) => {
+ state.hashtags = tags
+ }
+}
+
+const actions: ActionTree = {
+ updateMedia: async ({ rootState }, media: Attachment) => {
+ if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
+ throw new AuthenticationError()
+ }
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ return Promise.all(
+ Object.keys(media).map(async id => {
+ return client.put(`/media/${id}`, { description: media[id] })
+ })).catch(err => {
+ console.error(err)
+ throw err
+ })
+ },
+ postToot: async ({ state, commit, rootState }, form) => {
+ if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
+ throw new AuthenticationError()
+ }
+ if (state.blockSubmit) {
+ return
+ }
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, true)
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ return client.post('/statuses', form)
+ .then((res: Response) => {
+ ipcRenderer.send('toot-action-sound')
+ return res.data
+ })
+ .finally(() => {
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
+ })
+ },
+ openReply: ({ commit, rootState }, message: Status) => {
+ commit(MUTATION_TYPES.SET_REPLY_TO, message)
+ const mentionAccounts = [message.account.acct].concat(message.mentions.map(a => a.acct))
+ .filter((a, i, self) => self.indexOf(a) === i)
+ .filter((a) => a !== rootState.TimelineSpace.account.username)
+ commit(MUTATION_TYPES.UPDATE_INITIAL_STATUS, `${mentionAccounts.map(m => `@${m}`).join(' ')} `)
+ commit(MUTATION_TYPES.UPDATE_INITIAL_SPOILER, message.spoiler_text)
+ commit(MUTATION_TYPES.CHANGE_MODAL, true)
+ let value: number = Visibility.Public.value
+ Object.keys(Visibility).map(key => {
+ const target = Visibility[key]
+ if (target.key === message.visibility) {
+ value = target.value
+ }
+ })
+ commit(MUTATION_TYPES.CHANGE_VISIBILITY_VALUE, value)
+ },
+ openModal: ({ dispatch, commit, state }) => {
+ if (!state.replyToMessage && state.pinedHashtag) {
+ commit(MUTATION_TYPES.UPDATE_INITIAL_STATUS, state.hashtags.map(t => ` #${t.name}`).join())
+ }
+ commit(MUTATION_TYPES.CHANGE_MODAL, true)
+ dispatch('fetchVisibility')
+ },
+ closeModal: ({ commit }) => {
+ commit(MUTATION_TYPES.CHANGE_MODAL, false)
+ commit(MUTATION_TYPES.UPDATE_INITIAL_STATUS, '')
+ commit(MUTATION_TYPES.UPDATE_INITIAL_SPOILER, '')
+ commit(MUTATION_TYPES.SET_REPLY_TO, null)
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
+ commit(MUTATION_TYPES.CLEAR_ATTACHED_MEDIAS)
+ commit(MUTATION_TYPES.CHANGE_SENSITIVE, false)
+ commit(MUTATION_TYPES.CHANGE_VISIBILITY_VALUE, Visibility.Public.value)
+ },
+ uploadImage: async ({ commit, rootState }, image: any) => {
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, true)
+ if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
+ throw new AuthenticationError()
+ }
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const formData = new FormData()
+ formData.append('file', image)
+ return client.post('/media', formData)
+ .then(res => {
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
+ if (res.data.type === 'unknown') throw new UnknownTypeError()
+ commit(MUTATION_TYPES.APPEND_ATTACHED_MEDIAS, res.data)
+ return res.data
+ })
+ .catch(err => {
+ commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
+ console.error(err)
+ throw err
+ })
+ },
+ incrementMediaId: ({ commit, state }) => {
+ commit(MUTATION_TYPES.UPDATE_MEDIA_ID, state.attachedMediaId + 1)
+ },
+ resetMediaId: ({ commit }) => {
+ commit(MUTATION_TYPES.UPDATE_MEDIA_ID, 0)
+ },
+ updateHashtags: ({ commit, state }, tags: Array) => {
+ if (state.pinedHashtag) {
+ commit(MUTATION_TYPES.UPDATE_HASHTAGS, tags)
+ }
+ },
+ fetchVisibility: async ({ commit, rootState }) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response = await client.get('/accounts/verify_credentials')
+ const visibility: VisibilityType = Object.values(Visibility as Array).find((v) => {
+ return v.key === res.data.source!.privacy
+ })
+ if (visibility === undefined) {
+ throw new Error('Visibility value is invalid')
+ }
+ commit(MUTATION_TYPES.CHANGE_VISIBILITY_VALUE, visibility.value)
+ return res.data
+ }
+}
+
+const getters: GetterTree = {
+ hashtagInserting: (state) => {
+ return !state.replyToMessage && state.pinedHashtag
+ }
+}
+
+const NewToot: Module = {
+ namespaced: true,
+ modules: {
+ Status: TootStatus
+ },
+ state: state,
+ mutations: mutations,
+ getters: getters,
+ actions: actions
+}
+
+export default NewToot
+
+class AuthenticationError {}
+class UnknownTypeError {}
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot/Status.js b/src/renderer/store/TimelineSpace/Modals/NewToot/Status.js
deleted file mode 100644
index 802a7fbe..00000000
--- a/src/renderer/store/TimelineSpace/Modals/NewToot/Status.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import Mastodon from 'megalodon'
-
-const Status = {
- namespaced: true,
- state: {
- filteredAccounts: [],
- filteredHashtags: []
- },
- mutations: {
- updateFilteredAccounts (state, accounts) {
- state.filteredAccounts = accounts.map((a) => {
- return {
- name: `@${a.acct}`,
- image: null
- }
- })
- },
- clearFilteredAccounts (state) {
- state.filteredAccounts = []
- },
- updateFilteredHashtags (state, tags) {
- state.filteredHashtags = tags.map((t) => {
- return {
- name: `#${t}`,
- image: null
- }
- })
- },
- clearFilteredHashtags (state) {
- state.filteredHashtags = []
- }
- },
- actions: {
- async searchAccount ({ commit, rootState }, word) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- const res = await client.get('/search', { q: word, resolve: false })
- commit('updateFilteredAccounts', res.data.accounts)
- if (res.data.accounts.length === 0) throw new Error('Empty')
- return res.data.accounts
- },
- async searchHashtag ({ commit, rootState }, word) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- const res = await client.get('/search', { q: word })
- commit('updateFilteredHashtags', res.data.hashtags)
- if (res.data.hashtags.length === 0) throw new Error('Empty')
- return res.data.hashtags
- }
- },
- getters: {
- pickerEmojis: (state, getters, rootState) => {
- return rootState.TimelineSpace.emojis.filter((e, i, array) => {
- return (array.findIndex(ar => e.name === ar.name) === i)
- }).map(e => {
- return {
- name: e.name,
- short_names: [e.name],
- text: e.name,
- emoticons: [],
- keywords: [e.name],
- imageUrl: e.image
- }
- })
- }
- }
-}
-
-export default Status
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts b/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
new file mode 100644
index 00000000..227149a2
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
@@ -0,0 +1,104 @@
+import Mastodon, { Account, Tag, Response, Results } from 'megalodon'
+import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'
+import { RootState } from '@/store/index'
+
+interface Suggest {
+ name: string,
+ image: string | null
+}
+
+interface SuggestAccount extends Suggest {}
+
+interface SuggestHashtag extends Suggest {}
+
+export interface StatusState {
+ filteredAccounts: Array,
+ filteredHashtags: Array
+}
+
+const state = (): StatusState => ({
+ filteredAccounts: [],
+ filteredHashtags: []
+})
+
+export const MUTATION_TYPES = {
+ UPDATE_FILTERED_ACCOUNTS: 'updateFilteredAccounts',
+ CLEAR_FILTERED_ACCOUNTS: 'clearFilteredAccounts',
+ UPDATE_FILTERED_HASHTAGS: 'updateFilteredHashtags',
+ CLAER_FILTERED_HASHTAGS: 'clearFilteredHashtags'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.UPDATE_FILTERED_ACCOUNTS]: (state, accounts: Array) => {
+ state.filteredAccounts = accounts.map((a) => {
+ return {
+ name: `@${a.acct}`,
+ image: null
+ }
+ })
+ },
+ [MUTATION_TYPES.CLEAR_FILTERED_ACCOUNTS]: (state) => {
+ state.filteredAccounts = []
+ },
+ [MUTATION_TYPES.UPDATE_FILTERED_HASHTAGS]: (state, tags: Array) => {
+ state.filteredHashtags = tags.map((t) => {
+ return {
+ name: `#${t}`,
+ image: null
+ }
+ })
+ },
+ [MUTATION_TYPES.CLEAR_FILTERED_ACCOUNTS]: (state) => {
+ state.filteredHashtags = []
+ }
+}
+
+const actions: ActionTree = {
+ searchAccount: async ({ commit, rootState }, word: string) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response = await client.get('/search', { q: word, resolve: false })
+ commit(MUTATION_TYPES.UPDATE_FILTERED_ACCOUNTS, res.data.accounts)
+ if (res.data.accounts.length === 0) throw new Error('Empty')
+ return res.data.accounts
+ },
+ searchHashtag: async ({ commit, rootState }, word: string) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ const res: Response = await client.get('/search', { q: word })
+ commit(MUTATION_TYPES.UPDATE_FILTERED_HASHTAGS, res.data.hashtags)
+ if (res.data.hashtags.length === 0) throw new Error('Empty')
+ return res.data.hashtags
+ }
+}
+
+const getters: GetterTree = {
+ pickerEmojis: (_state, _getters, rootState) => {
+ return rootState.TimelineSpace.emojis.filter((e, i, array) => {
+ return (array.findIndex(ar => e.name === ar.name) === i)
+ }).map(e => {
+ return {
+ name: e.name,
+ short_names: [e.name],
+ text: e.name,
+ emoticons: [],
+ keywords: [e.name],
+ imageUrl: e.image
+ }
+ })
+ }
+}
+
+const Status: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions,
+ getters: getters
+}
+
+export default Status
diff --git a/tsconfig.json b/tsconfig.json
index 821b00f6..0d48eb32 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,7 +2,11 @@
"compilerOptions": {
"target": "es5",
"module": "es2015",
- "lib": ["es6"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "es6"
+ ],
"sourceMap": true,
"downlevelIteration": true,
"strict": true,
From ac215112366934a0185877da6bcf94b063bbbe5c Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Apr 2019 00:15:12 +0900
Subject: [PATCH 08/11] refs #850 Replace Report with typescript
---
src/renderer/store/TimelineSpace/Modals.ts | 5 +-
.../store/TimelineSpace/Modals/Report.js | 34 ------------
.../store/TimelineSpace/Modals/Report.ts | 52 +++++++++++++++++++
3 files changed, 55 insertions(+), 36 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/Report.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/Report.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 5c0392ae..11b31bb9 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -5,7 +5,7 @@ import ListMembership, { ListMembershipState } from './Modals/ListMembership'
import AddListMember, { AddListMemberState } from './Modals/AddListMember'
import MuteConfirm, { MuteConfirmState } from './Modals/MuteConfirm'
import Shortcut from './Modals/Shortcut'
-import Report from './Modals/Report'
+import Report, { ReportState } from './Modals/Report'
import { Module, GetterTree } from 'vuex'
import { RootState } from '@/store/index'
@@ -17,7 +17,8 @@ export interface ModalsModuleState extends ModalsState {
ImageViewer: ImageViewerState,
ListMembership: ListMembershipState,
MuteConfirm: MuteConfirmState,
- NewToot: NewTootModuleState
+ NewToot: NewTootModuleState,
+ Report: ReportState
}
const state = (): ModalsState => ({})
diff --git a/src/renderer/store/TimelineSpace/Modals/Report.js b/src/renderer/store/TimelineSpace/Modals/Report.js
deleted file mode 100644
index 73a526f6..00000000
--- a/src/renderer/store/TimelineSpace/Modals/Report.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import Mastodon from 'megalodon'
-
-export default {
- namespaced: true,
- state: {
- modalOpen: false,
- message: {}
- },
- mutations: {
- changeModalOpen (state, value) {
- state.modalOpen = value
- },
- changeMessage (state, value) {
- state.message = value
- }
- },
- actions: {
- openReport ({ commit }, message) {
- commit('changeMessage', message)
- commit('changeModalOpen', true)
- },
- submit ({ rootState }, payload) {
- const client = new Mastodon(
- rootState.TimelineSpace.account.accessToken,
- rootState.TimelineSpace.account.baseURL + '/api/v1'
- )
- return client.post(`/reports`, {
- account_id: payload.account_id,
- status_ids: [payload.status_id],
- comment: payload.comment
- })
- }
- }
-}
diff --git a/src/renderer/store/TimelineSpace/Modals/Report.ts b/src/renderer/store/TimelineSpace/Modals/Report.ts
new file mode 100644
index 00000000..0fa77a50
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/Report.ts
@@ -0,0 +1,52 @@
+import Mastodon, { Status } from 'megalodon'
+import { Module, MutationTree, ActionTree } from 'vuex'
+import { RootState } from '@/store'
+
+export interface ReportState {
+ modalOpen: boolean,
+ message: Status | null
+}
+
+const state = (): ReportState => ({
+ modalOpen: false,
+ message: null
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL_OPEN: 'changeModalOpen',
+ CHANGE_MESSAGE: 'changeMessage'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL_OPEN]: (state, value: boolean) => {
+ state.modalOpen = value
+ },
+ [MUTATION_TYPES.CHANGE_MESSAGE]: (state, message: Status) => {
+ state.message = message
+ }
+}
+
+const actions: ActionTree = {
+ openReport: ({ commit }, message: Status) => {
+ commit(MUTATION_TYPES.CHANGE_MESSAGE, message)
+ commit(MUTATION_TYPES.CHANGE_MODAL_OPEN, true)
+ },
+ submit: async ({ rootState }, { account_id, status_id, comment }) => {
+ const client = new Mastodon(
+ rootState.TimelineSpace.account.accessToken!,
+ rootState.TimelineSpace.account.baseURL + '/api/v1'
+ )
+ return client.post<{}>(`/reports`, {
+ account_id: account_id,
+ status_ids: [status_id],
+ comment: comment
+ })
+ }
+}
+
+export default {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+} as Module
From b9941e71c345ae1f0c02495b99b1e47da7e3d1e5 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Apr 2019 00:19:25 +0900
Subject: [PATCH 09/11] refs #850 Replace Shortcut with typescript
---
src/renderer/store/TimelineSpace/Modals.ts | 5 ++--
.../store/TimelineSpace/Modals/Shortcut.js | 11 --------
.../store/TimelineSpace/Modals/Shortcut.ts | 26 +++++++++++++++++++
3 files changed, 29 insertions(+), 13 deletions(-)
delete mode 100644 src/renderer/store/TimelineSpace/Modals/Shortcut.js
create mode 100644 src/renderer/store/TimelineSpace/Modals/Shortcut.ts
diff --git a/src/renderer/store/TimelineSpace/Modals.ts b/src/renderer/store/TimelineSpace/Modals.ts
index 11b31bb9..67ca9139 100644
--- a/src/renderer/store/TimelineSpace/Modals.ts
+++ b/src/renderer/store/TimelineSpace/Modals.ts
@@ -4,7 +4,7 @@ import Jump, { JumpState } from './Modals/Jump'
import ListMembership, { ListMembershipState } from './Modals/ListMembership'
import AddListMember, { AddListMemberState } from './Modals/AddListMember'
import MuteConfirm, { MuteConfirmState } from './Modals/MuteConfirm'
-import Shortcut from './Modals/Shortcut'
+import Shortcut, { ShortcutState } from './Modals/Shortcut'
import Report, { ReportState } from './Modals/Report'
import { Module, GetterTree } from 'vuex'
import { RootState } from '@/store/index'
@@ -18,7 +18,8 @@ export interface ModalsModuleState extends ModalsState {
ListMembership: ListMembershipState,
MuteConfirm: MuteConfirmState,
NewToot: NewTootModuleState,
- Report: ReportState
+ Report: ReportState,
+ Shortcut: ShortcutState
}
const state = (): ModalsState => ({})
diff --git a/src/renderer/store/TimelineSpace/Modals/Shortcut.js b/src/renderer/store/TimelineSpace/Modals/Shortcut.js
deleted file mode 100644
index 081d3354..00000000
--- a/src/renderer/store/TimelineSpace/Modals/Shortcut.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default {
- namespaced: true,
- state: {
- modalOpen: false
- },
- mutations: {
- changeModal (state, value) {
- state.modalOpen = value
- }
- }
-}
diff --git a/src/renderer/store/TimelineSpace/Modals/Shortcut.ts b/src/renderer/store/TimelineSpace/Modals/Shortcut.ts
new file mode 100644
index 00000000..7d19097f
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Modals/Shortcut.ts
@@ -0,0 +1,26 @@
+import { Module, MutationTree } from 'vuex'
+import { RootState } from '@/store'
+
+export interface ShortcutState {
+ modalOpen: boolean
+}
+
+const state = (): ShortcutState => ({
+ modalOpen: false
+})
+
+export const MUTATION_TYPES = {
+ CHANGE_MODAL: 'changeModal'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.CHANGE_MODAL]: (state, value: boolean) => {
+ state.modalOpen = value
+ }
+}
+
+export default {
+ namespaced: true,
+ state: state,
+ mutations: mutations
+} as Module
From 21605412cf47d3580fc7af7d06feb7ca75b37031 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Apr 2019 00:24:34 +0900
Subject: [PATCH 10/11] [eslint] refs #850 Fix indent spaces for NewToot
---
.../store/TimelineSpace/Modals/NewToot.ts | 9 ++++----
.../TimelineSpace/Modals/NewToot/Status.ts | 22 ++++++++-----------
2 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot.ts b/src/renderer/store/TimelineSpace/Modals/NewToot.ts
index 68f16c4e..02ba061b 100644
--- a/src/renderer/store/TimelineSpace/Modals/NewToot.ts
+++ b/src/renderer/store/TimelineSpace/Modals/NewToot.ts
@@ -111,10 +111,11 @@ const actions: ActionTree = {
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
- return Promise.all(
- Object.keys(media).map(async id => {
- return client.put(`/media/${id}`, { description: media[id] })
- })).catch(err => {
+ const attachments = Object.keys(media).map(async id => {
+ return client.put(`/media/${id}`, { description: media[id] })
+ })
+ return Promise.all(attachments)
+ .catch(err => {
console.error(err)
throw err
})
diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts b/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
index 227149a2..697bf16e 100644
--- a/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
+++ b/src/renderer/store/TimelineSpace/Modals/NewToot/Status.ts
@@ -30,23 +30,19 @@ export const MUTATION_TYPES = {
const mutations: MutationTree = {
[MUTATION_TYPES.UPDATE_FILTERED_ACCOUNTS]: (state, accounts: Array) => {
- state.filteredAccounts = accounts.map((a) => {
- return {
- name: `@${a.acct}`,
- image: null
- }
- })
+ state.filteredAccounts = accounts.map(a => ({
+ name: `@${a.acct}`,
+ image: null
+ }))
},
[MUTATION_TYPES.CLEAR_FILTERED_ACCOUNTS]: (state) => {
state.filteredAccounts = []
},
[MUTATION_TYPES.UPDATE_FILTERED_HASHTAGS]: (state, tags: Array) => {
- state.filteredHashtags = tags.map((t) => {
- return {
- name: `#${t}`,
- image: null
- }
- })
+ state.filteredHashtags = tags.map(t => ({
+ name: `#${t}`,
+ image: null
+ }))
},
[MUTATION_TYPES.CLEAR_FILTERED_ACCOUNTS]: (state) => {
state.filteredHashtags = []
@@ -70,7 +66,7 @@ const actions: ActionTree = {
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
const res: Response = await client.get('/search', { q: word })
- commit(MUTATION_TYPES.UPDATE_FILTERED_HASHTAGS, res.data.hashtags)
+ commit(MUTATION_TYPES.UPDATE_FILTERED_HASHTAGS, res.data.hashtags)
if (res.data.hashtags.length === 0) throw new Error('Empty')
return res.data.hashtags
}
From 2304b98260b07a889b1c4fb2292701950a1724ad Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Thu, 11 Apr 2019 00:30:54 +0900
Subject: [PATCH 11/11] refs #850 Fix spec for Modals
---
.../Modals/AddListMember.spec.ts | 6 ++--
.../TimelineSpace/Modals/ImageViewer.spec.ts | 4 +--
.../Modals/ListMembership.spec.ts | 32 +++++++++++++++----
3 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/spec/renderer/integration/store/TimelineSpace/Modals/AddListMember.spec.ts b/spec/renderer/integration/store/TimelineSpace/Modals/AddListMember.spec.ts
index 5f5c1b06..67ae6446 100644
--- a/spec/renderer/integration/store/TimelineSpace/Modals/AddListMember.spec.ts
+++ b/spec/renderer/integration/store/TimelineSpace/Modals/AddListMember.spec.ts
@@ -2,7 +2,7 @@ import { Response, Account } from 'megalodon'
import mockedMegalodon from '~/spec/mock/megalodon'
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
-import AddListMember from '~/src/renderer/store/TimelineSpace/Modals/AddListMember'
+import AddListMember, { AddListMemberState } from '@/store/TimelineSpace/Modals/AddListMember'
jest.mock('megalodon')
@@ -28,7 +28,7 @@ const account: Account = {
bot: false
}
-const state = () => {
+const state = (): AddListMemberState => {
return {
modalOpen: false,
accounts: [],
@@ -121,7 +121,7 @@ describe('AddListMember', () => {
mockedMegalodon.mockImplementation(() => mockClient)
const result = await store.dispatch('AddListMember/add', 'akira')
- expect(result.data).toEqual({})
+ expect(result).toEqual({})
})
})
})
diff --git a/spec/renderer/integration/store/TimelineSpace/Modals/ImageViewer.spec.ts b/spec/renderer/integration/store/TimelineSpace/Modals/ImageViewer.spec.ts
index 52681ee3..b3a3a21d 100644
--- a/spec/renderer/integration/store/TimelineSpace/Modals/ImageViewer.spec.ts
+++ b/spec/renderer/integration/store/TimelineSpace/Modals/ImageViewer.spec.ts
@@ -1,8 +1,8 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
-import ImageViewer from '~/src/renderer/store/TimelineSpace/Modals/ImageViewer'
+import ImageViewer, { ImageViewerState } from '~/src/renderer/store/TimelineSpace/Modals/ImageViewer'
-const state = () => {
+const state = (): ImageViewerState => {
return {
modalOpen: false,
currentIndex: -1,
diff --git a/spec/renderer/integration/store/TimelineSpace/Modals/ListMembership.spec.ts b/spec/renderer/integration/store/TimelineSpace/Modals/ListMembership.spec.ts
index 8e8003d7..843e95c0 100644
--- a/spec/renderer/integration/store/TimelineSpace/Modals/ListMembership.spec.ts
+++ b/spec/renderer/integration/store/TimelineSpace/Modals/ListMembership.spec.ts
@@ -1,11 +1,33 @@
-import { Response, List } from 'megalodon'
+import { Response, List, Account } from 'megalodon'
import mockedMegalodon from '~/spec/mock/megalodon'
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
-import ListMembership from '~/src/renderer/store/TimelineSpace/Modals/ListMembership'
+import ListMembership, { ListMembershipState } from '@/store/TimelineSpace/Modals/ListMembership'
jest.mock('megalodon')
+const account: Account = {
+ id: 1,
+ username: 'h3poteto',
+ acct: 'h3poteto@pleroma.io',
+ display_name: 'h3poteto',
+ locked: false,
+ created_at: '2019-03-26T21:30:32',
+ followers_count: 10,
+ following_count: 10,
+ statuses_count: 100,
+ note: 'engineer',
+ url: 'https://pleroma.io',
+ avatar: '',
+ avatar_static: '',
+ header: '',
+ header_static: '',
+ emojis: [],
+ moved: null,
+ fields: null,
+ bot: false
+}
+
const list1: List = {
id: 1,
title: 'list1'
@@ -16,7 +38,7 @@ const list2: List = {
title: 'list2'
}
-let state: any = () => {
+let state = (): ListMembershipState => {
return {
modalOpen: false,
account: null,
@@ -116,9 +138,7 @@ describe('ListMembership', () => {
state = () => {
return {
modalOpen: false,
- account: {
- id: 65
- },
+ account: account,
lists: [],
belongToLists: [
list2