tooot/src/utils/slices/instancesSlice.ts

379 lines
13 KiB
TypeScript
Raw Normal View History

2021-01-07 19:13:09 +01:00
import analytics from '@components/analytics'
2021-02-20 19:12:44 +01:00
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2020-12-13 14:04:25 +01:00
import { RootState } from '@root/store'
2021-02-07 00:39:11 +01:00
import { ComposeStateDraft } from '@screens/Compose/utils/types'
import { findIndex } from 'lodash'
2021-02-20 19:12:44 +01:00
import addInstance from './instances/add'
import removeInstance from './instances/remove'
import { updateAccountPreferences } from './instances/updateAccountPreferences'
2021-05-30 23:39:07 +02:00
import { updateFilters } from './instances/updateFilters'
2021-02-27 16:33:54 +01:00
import { updateInstancePush } from './instances/updatePush'
import { updateInstancePushAlert } from './instances/updatePushAlert'
import { updateInstancePushDecode } from './instances/updatePushDecode'
2021-01-07 19:13:09 +01:00
2021-02-20 19:12:44 +01:00
export type Instance = {
active: boolean
2021-01-07 19:13:09 +01:00
appData: {
clientId: string
clientSecret: string
}
url: string
token: string
2021-01-17 22:37:05 +01:00
uri: Mastodon.Instance['uri']
urls: Mastodon.Instance['urls']
max_toot_chars: number
2021-01-07 19:13:09 +01:00
account: {
id: Mastodon.Account['id']
2021-01-23 02:41:50 +01:00
acct: Mastodon.Account['acct']
avatarStatic: Mastodon.Account['avatar_static']
2021-01-07 19:13:09 +01:00
preferences: Mastodon.Preferences
}
2021-05-30 23:39:07 +02:00
filters: Mastodon.Filter[]
2021-03-17 15:30:28 +01:00
notifications_filter: {
follow: boolean
favourite: boolean
reblog: boolean
mention: boolean
poll: boolean
follow_request: boolean
}
2021-02-27 16:33:54 +01:00
push:
| {
2021-03-16 23:18:02 +01:00
global: { loading: boolean; value: boolean }
decode: { loading: boolean; value: true }
2021-02-27 16:33:54 +01:00
alerts: {
follow: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['follow']
}
favourite: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['favourite']
}
reblog: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['reblog']
}
mention: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['mention']
}
poll: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['poll']
}
}
2021-03-17 15:30:28 +01:00
keys: {
auth: string
public: string
private: string
}
2021-02-27 16:33:54 +01:00
}
| {
2021-03-16 23:18:02 +01:00
global: { loading: boolean; value: boolean }
decode: { loading: boolean; value: false }
2021-02-27 16:33:54 +01:00
alerts: {
follow: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['follow']
}
favourite: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['favourite']
}
reblog: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['reblog']
}
mention: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['mention']
}
poll: {
loading: boolean
value: Mastodon.PushSubscription['alerts']['poll']
}
}
keys: undefined
}
2021-02-07 00:39:11 +01:00
drafts: ComposeStateDraft[]
2021-01-07 19:13:09 +01:00
}
2020-11-21 13:19:05 +01:00
export type InstancesState = {
2021-02-20 19:12:44 +01:00
instances: Instance[]
}
2021-01-07 19:13:09 +01:00
export const instancesInitialState: InstancesState = {
2021-02-20 19:12:44 +01:00
instances: []
2021-01-07 19:13:09 +01:00
}
2021-02-20 19:12:44 +01:00
const findInstanceActive = (state: Instance[]) =>
state.findIndex(instance => instance.active)
const instancesSlice = createSlice({
name: 'instances',
2021-01-07 19:13:09 +01:00
initialState: instancesInitialState,
2020-12-22 00:10:55 +01:00
reducers: {
2021-02-20 19:12:44 +01:00
updateInstanceActive: ({ instances }, action: PayloadAction<Instance>) => {
instances = instances.map(instance => {
instance.active =
2021-02-02 22:50:38 +01:00
instance.url === action.payload.url &&
instance.token === action.payload.token &&
instance.account.id === action.payload.account.id
2021-02-20 19:12:44 +01:00
return instance
})
2020-12-24 10:28:51 +01:00
},
2021-02-20 19:12:44 +01:00
updateInstanceAccount: (
{ instances },
action: PayloadAction<Pick<Instance['account'], 'acct' & 'avatarStatic'>>
2021-01-23 02:41:50 +01:00
) => {
2021-02-20 19:12:44 +01:00
const activeIndex = findInstanceActive(instances)
instances[activeIndex].account = {
...instances[activeIndex].account,
...action.payload
2021-01-23 02:41:50 +01:00
}
},
2021-03-17 15:30:28 +01:00
updateInstanceNotificationsFilter: (
{ instances },
action: PayloadAction<Instance['notifications_filter']>
) => {
const activeIndex = findInstanceActive(instances)
instances[activeIndex].notifications_filter = action.payload
},
2021-02-20 19:12:44 +01:00
updateInstanceDraft: (
{ instances },
action: PayloadAction<ComposeStateDraft>
) => {
const activeIndex = findInstanceActive(instances)
const draftIndex = findIndex(instances[activeIndex].drafts, [
'timestamp',
action.payload.timestamp
])
if (draftIndex === -1) {
instances[activeIndex].drafts.unshift(action.payload)
} else {
instances[activeIndex].drafts[draftIndex] = action.payload
2021-02-07 00:39:11 +01:00
}
},
2021-02-20 19:12:44 +01:00
removeInstanceDraft: (
{ instances },
2021-02-07 00:39:11 +01:00
action: PayloadAction<ComposeStateDraft['timestamp']>
2021-01-07 19:13:09 +01:00
) => {
2021-02-20 19:12:44 +01:00
const activeIndex = findInstanceActive(instances)
instances[activeIndex].drafts = instances[activeIndex].drafts?.filter(
draft => draft.timestamp !== action.payload
)
2021-03-04 01:03:53 +01:00
},
2021-03-23 23:16:01 +01:00
clearPushLoading: ({ instances }) => {
const activeIndex = findInstanceActive(instances)
instances[activeIndex].push.global.loading = false
instances[activeIndex].push.decode.loading = false
instances[activeIndex].push.alerts.favourite.loading = false
instances[activeIndex].push.alerts.follow.loading = false
instances[activeIndex].push.alerts.mention.loading = false
instances[activeIndex].push.alerts.poll.loading = false
instances[activeIndex].push.alerts.reblog.loading = false
},
2021-03-04 01:03:53 +01:00
disableAllPushes: ({ instances }) => {
instances = instances.map(instance => {
let newInstance = instance
newInstance.push.global.value = false
return newInstance
})
2020-12-22 00:10:55 +01:00
}
},
extraReducers: builder => {
builder
2021-02-20 19:12:44 +01:00
.addCase(addInstance.fulfilled, (state, action) => {
2021-01-10 02:12:14 +01:00
switch (action.payload.type) {
case 'add':
2021-02-20 19:12:44 +01:00
state.instances.length &&
(state.instances = state.instances.map(instance => {
instance.active = false
return instance
}))
state.instances.push(action.payload.data)
2021-01-10 02:12:14 +01:00
break
case 'overwrite':
2021-02-20 19:12:44 +01:00
state.instances = state.instances.map(instance => {
2021-01-10 02:12:14 +01:00
if (
instance.url === action.payload.data.url &&
instance.account.id === action.payload.data.account.id
) {
return action.payload.data
} else {
2021-02-20 19:12:44 +01:00
instance.active = false
2021-01-10 02:12:14 +01:00
return instance
}
})
}
2021-01-07 19:13:09 +01:00
analytics('login')
})
2021-02-20 19:12:44 +01:00
.addCase(addInstance.rejected, (state, action) => {
console.error(state.instances)
2021-01-07 19:13:09 +01:00
console.error(action.error)
})
2021-02-20 19:12:44 +01:00
.addCase(removeInstance.fulfilled, (state, action) => {
2021-03-01 00:28:14 +01:00
state.instances = state.instances.filter(instance => {
if (
instance.url === action.payload.url &&
instance.account.id === action.payload.account.id
) {
return false
} else {
return true
}
})
2021-02-20 19:12:44 +01:00
state.instances.length &&
(state.instances[state.instances.length - 1].active = true)
2021-01-07 19:13:09 +01:00
analytics('logout')
})
2021-02-20 19:12:44 +01:00
.addCase(removeInstance.rejected, (state, action) => {
console.error(state)
2021-01-07 19:13:09 +01:00
console.error(action.error)
2021-05-30 23:39:07 +02:00
})
// Update Instance Account Filters
.addCase(updateFilters.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].filters = action.payload
})
.addCase(updateFilters.rejected, (_, action) => {
console.error(action.error)
2021-01-07 19:13:09 +01:00
})
2021-02-27 16:33:54 +01:00
// Update Instance Account Preferences
2021-02-20 19:12:44 +01:00
.addCase(updateAccountPreferences.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].account.preferences = action.payload
2021-01-07 19:13:09 +01:00
})
2021-02-20 19:12:44 +01:00
.addCase(updateAccountPreferences.rejected, (_, action) => {
2021-01-07 19:13:09 +01:00
console.error(action.error)
})
2021-02-20 19:12:44 +01:00
2021-02-27 16:33:54 +01:00
// Update Instance Push Global
.addCase(updateInstancePush.fulfilled, (state, action) => {
2021-02-20 19:12:44 +01:00
const activeIndex = findInstanceActive(state.instances)
2021-02-27 16:33:54 +01:00
state.instances[activeIndex].push.global.loading = false
state.instances[activeIndex].push.global.value = action.meta.arg
state.instances[activeIndex].push.keys = action.payload
})
.addCase(updateInstancePush.rejected, state => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.global.loading = false
})
.addCase(updateInstancePush.pending, state => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.global.loading = true
})
// Update Instance Push Decode
.addCase(updateInstancePushDecode.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.decode.loading = false
2021-08-29 15:25:38 +02:00
state.instances[activeIndex].push.decode.value = action.payload.disable
2021-02-27 16:33:54 +01:00
})
.addCase(updateInstancePushDecode.rejected, state => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.decode.loading = false
})
.addCase(updateInstancePushDecode.pending, state => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.decode.loading = true
})
// Update Instance Push Individual Alert
.addCase(updateInstancePushAlert.fulfilled, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.alerts[
action.meta.arg.changed
].loading = false
state.instances[activeIndex].push.alerts = action.payload
})
.addCase(updateInstancePushAlert.rejected, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.alerts[
action.meta.arg.changed
].loading = false
})
.addCase(updateInstancePushAlert.pending, (state, action) => {
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].push.alerts[
action.meta.arg.changed
].loading = true
2021-02-20 19:12:44 +01:00
})
}
})
2021-02-20 19:12:44 +01:00
export const getInstanceActive = ({ instances: { instances } }: RootState) =>
findInstanceActive(instances)
export const getInstances = ({ instances: { instances } }: RootState) =>
instances
export const getInstance = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive] : null
}
export const getInstanceUrl = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].url : null
}
export const getInstanceUri = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].uri : null
}
export const getInstanceUrls = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].urls : null
}
export const getInstanceMaxTootChar = ({
instances: { instances }
}: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].max_toot_chars : 500
2021-02-20 19:12:44 +01:00
}
export const getInstanceAccount = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].account : null
}
2021-03-17 15:30:28 +01:00
export const getInstanceNotificationsFilter = ({
instances: { instances }
}: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1
? instances[instanceActive].notifications_filter
: null
}
2021-02-27 16:33:54 +01:00
export const getInstancePush = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].push : null
}
2021-02-20 19:12:44 +01:00
export const getInstanceDrafts = ({ instances: { instances } }: RootState) => {
const instanceActive = findInstanceActive(instances)
return instanceActive !== -1 ? instances[instanceActive].drafts : null
}
2021-01-07 19:13:09 +01:00
export const {
2021-02-20 19:12:44 +01:00
updateInstanceActive,
updateInstanceAccount,
2021-03-17 15:30:28 +01:00
updateInstanceNotificationsFilter,
2021-02-20 19:12:44 +01:00
updateInstanceDraft,
2021-03-04 01:03:53 +01:00
removeInstanceDraft,
2021-03-23 23:16:01 +01:00
clearPushLoading,
2021-03-04 01:03:53 +01:00
disableAllPushes
2021-01-07 19:13:09 +01:00
} = instancesSlice.actions
2020-12-22 00:10:55 +01:00
export default instancesSlice.reducer