167 lines
5.0 KiB
TypeScript
167 lines
5.0 KiB
TypeScript
import * as q from '../../../backend/src/Model'
|
|
import { ActionTypes, SettingsStateModel, TopicOrder } from '../reducers/Settings'
|
|
import { AppState } from '../reducers'
|
|
import { autoExpandLimitSet } from '../components/SettingsDrawer/Settings'
|
|
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
|
import { batchActions } from 'redux-batched-actions'
|
|
import { default as persistentStorage, StorageIdentifier } from '../utils/PersistentStorage'
|
|
import { Dispatch } from 'redux'
|
|
import { globalActions } from './'
|
|
import { showError } from './Global'
|
|
import { showTree } from './Tree'
|
|
import { TopicViewModel } from '../model/TopicViewModel'
|
|
|
|
const settingsIdentifier: StorageIdentifier<Partial<SettingsStateModel>> = {
|
|
id: 'Settings',
|
|
}
|
|
|
|
export const loadSettings = () => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
|
try {
|
|
const settings = (await persistentStorage.load(settingsIdentifier)) || {}
|
|
dispatch({
|
|
settings: getState().settings.merge(settings),
|
|
type: ActionTypes.SETTINGS_DID_LOAD_SETTINGS,
|
|
})
|
|
} catch (error) {
|
|
dispatch(showError(error))
|
|
}
|
|
dispatch(globalActions.didLaunch())
|
|
}
|
|
|
|
export const storeSettings = () => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
|
const settings = {
|
|
...getState().settings.toJS(),
|
|
autoExpandLimit: undefined,
|
|
topicFilter: undefined,
|
|
visible: undefined,
|
|
}
|
|
|
|
try {
|
|
await persistentStorage.store(settingsIdentifier, settings)
|
|
} catch (error) {
|
|
dispatch(showError(error))
|
|
}
|
|
}
|
|
|
|
export const setAutoExpandLimit = (autoExpandLimit: number = 0) => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
autoExpandLimit,
|
|
type: ActionTypes.SETTINGS_SET_AUTO_EXPAND_LIMIT,
|
|
})
|
|
}
|
|
|
|
export const setTimeLocale = (timeLocale: string) => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
timeLocale,
|
|
type: ActionTypes.SETTINGS_SET_TIME_LOCALE,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|
|
|
|
export const selectTopicWithMouseOver = (doSelect: boolean) => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
selectTopicWithMouseOver: doSelect,
|
|
type: ActionTypes.SETTINGS_SET_SELECT_TOPIC_WITH_MOUSE_OVER,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|
|
|
|
export const setValueDisplayMode = (valueRendererDisplayMode: 'diff' | 'raw') => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
valueRendererDisplayMode,
|
|
type: ActionTypes.SETTINGS_SET_VALUE_RENDERER_DISPLAY_MODE,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|
|
|
|
export const toggleHighlightTopicUpdates = () => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
type: ActionTypes.SETTINGS_TOGGLE_HIGHLIGHT_ACTIVITY,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|
|
|
|
export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none) => (dispatch: Dispatch<any>) => {
|
|
dispatch({
|
|
topicOrder,
|
|
type: ActionTypes.SETTINGS_SET_TOPIC_ORDER,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|
|
|
|
export const filterTopics = (filterStr: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
|
const { tree } = getState().connection
|
|
|
|
dispatch({
|
|
topicFilter: filterStr,
|
|
type: ActionTypes.SETTINGS_FILTER_TOPICS,
|
|
})
|
|
|
|
if (!filterStr || !tree) {
|
|
dispatch(batchActions([setAutoExpandLimit(0), showTree(tree) as any]))
|
|
return
|
|
}
|
|
|
|
const topicFilter = filterStr.toLowerCase()
|
|
|
|
const nodeFilter = (node: q.TreeNode<TopicViewModel>): boolean => {
|
|
const topicMatches = node.path().toLowerCase().indexOf(topicFilter) !== -1
|
|
if (topicMatches) {
|
|
return true
|
|
}
|
|
|
|
const messageMatches =
|
|
node.message &&
|
|
node.message.payload &&
|
|
Base64Message.toUnicodeString(node.message.payload).toLowerCase().indexOf(filterStr) !== -1
|
|
|
|
return Boolean(messageMatches)
|
|
}
|
|
|
|
const resultTree = tree
|
|
.childTopics()
|
|
.filter(nodeFilter)
|
|
.map((node: q.TreeNode<TopicViewModel>) => {
|
|
const clone = node.unconnectedClone()
|
|
q.TreeNodeFactory.insertNodeAtPosition(node.path().split('/'), clone)
|
|
return clone.firstNode()
|
|
})
|
|
.reduce((a: q.TreeNode<TopicViewModel>, b: q.TreeNode<TopicViewModel>) => {
|
|
a.updateWithNode(b)
|
|
return a
|
|
}, new q.Tree<TopicViewModel>())
|
|
|
|
const nextTree: q.Tree<TopicViewModel> = resultTree as q.Tree<TopicViewModel>
|
|
if (tree.updateSource && tree.connectionId) {
|
|
nextTree.updateWithConnection(tree.updateSource, tree.connectionId, nodeFilter)
|
|
}
|
|
|
|
dispatch(batchActions([setAutoExpandLimit(autoExpandLimitForTree(nextTree)), showTree(nextTree) as any]))
|
|
}
|
|
|
|
function autoExpandLimitForTree(tree: q.Tree<TopicViewModel>) {
|
|
if (!tree) {
|
|
return 0
|
|
}
|
|
|
|
function closestExistingLimit(i: number): number {
|
|
const sorted = [...autoExpandLimitSet].sort((a, b) => Math.abs(a.limit - i) - Math.abs(b.limit - i))
|
|
return sorted[0].limit
|
|
}
|
|
|
|
const count = tree.childTopicCount()
|
|
const calculatedLimit = Math.max(7 - Math.log(count), 0) * 2
|
|
|
|
return closestExistingLimit(calculatedLimit)
|
|
}
|
|
|
|
export const toggleTheme = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
|
dispatch({
|
|
type:
|
|
getState().settings.get('theme') === 'light'
|
|
? ActionTypes.SETTINGS_SET_THEME_DARK
|
|
: ActionTypes.SETTINGS_SET_THEME_LIGHT,
|
|
})
|
|
dispatch(storeSettings())
|
|
}
|