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-02-27 16:33:54 +01:00
|
|
|
import { updateInstancePush } from './instances/updatePush'
|
|
|
|
import { updateInstancePushAlert } from './instances/updatePushAlert'
|
|
|
|
import { updateInstancePushDecode } from './instances/updatePushDecode'
|
|
|
|
|
|
|
|
export const PUSH_SERVER = __DEV__ ? 'testpush.tooot.app' : 'push.tooot.app'
|
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']
|
2021-02-08 23:19:55 +01:00
|
|
|
urls: Mastodon.Instance['urls']
|
2021-02-05 13:45:02 +01:00
|
|
|
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-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 00:40:55 +01:00
|
|
|
|
2020-11-21 13:19:05 +01:00
|
|
|
export type InstancesState = {
|
2021-02-20 19:12:44 +01:00
|
|
|
instances: Instance[]
|
2020-11-21 00:40:55 +01:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
2020-11-21 00:40:55 +01:00
|
|
|
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
|
|
|
},
|
|
|
|
disableAllPushes: ({ instances }) => {
|
|
|
|
instances = instances.map(instance => {
|
|
|
|
let newInstance = instance
|
|
|
|
newInstance.push.global.value = false
|
|
|
|
return newInstance
|
|
|
|
})
|
2020-12-22 00:10:55 +01:00
|
|
|
}
|
|
|
|
},
|
2020-11-21 00:40:55 +01:00
|
|
|
extraReducers: builder => {
|
2020-12-22 01:09:34 +01:00
|
|
|
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')
|
2020-12-22 01:09:34 +01:00
|
|
|
})
|
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-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)
|
2020-12-22 01:09:34 +01:00
|
|
|
})
|
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
|
|
|
|
state.instances[activeIndex].push.decode.value = action.payload
|
|
|
|
})
|
|
|
|
.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
|
|
|
})
|
2020-11-21 00:40:55 +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)
|
2021-02-27 17:25:01 +01:00
|
|
|
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,
|
|
|
|
disableAllPushes
|
2021-01-07 19:13:09 +01:00
|
|
|
} = instancesSlice.actions
|
2020-12-22 00:10:55 +01:00
|
|
|
|
2020-11-21 00:40:55 +01:00
|
|
|
export default instancesSlice.reducer
|