feat: move timer options out of redux

pull/2971/head
William Grant 2 years ago
parent 73cceab31f
commit b471900a18

@ -1,12 +1,12 @@
import { fromPairs, map } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import React from 'react'; import React from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import styled from 'styled-components'; import useMount from 'react-use/lib/useMount';
import { fromPairs, map } from 'lodash'; import useUpdate from 'react-use/lib/useUpdate';
import { persistStore } from 'redux-persist'; import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react'; import { PersistGate } from 'redux-persist/integration/react';
import useUpdate from 'react-use/lib/useUpdate'; import styled from 'styled-components';
import useMount from 'react-use/lib/useMount';
import { LeftPane } from './leftpane/LeftPane'; import { LeftPane } from './leftpane/LeftPane';
// moment does not support es-419 correctly (and cause white screen on app start) // moment does not support es-419 correctly (and cause white screen on app start)
@ -26,10 +26,8 @@ import { initialSearchState } from '../state/ducks/search';
import { initialSectionState } from '../state/ducks/section'; import { initialSectionState } from '../state/ducks/section';
import { getEmptyStagedAttachmentsState } from '../state/ducks/stagedAttachments'; import { getEmptyStagedAttachmentsState } from '../state/ducks/stagedAttachments';
import { initialThemeState } from '../state/ducks/theme'; import { initialThemeState } from '../state/ducks/theme';
import { TimerOptionsArray } from '../state/ducks/timerOptions';
import { initialUserConfigState } from '../state/ducks/userConfig'; import { initialUserConfigState } from '../state/ducks/userConfig';
import { StateType } from '../state/reducer'; import { StateType } from '../state/reducer';
import { ExpirationTimerOptions } from '../util/expiringMessages';
import { SessionMainPanel } from './SessionMainPanel'; import { SessionMainPanel } from './SessionMainPanel';
import { SettingsKey } from '../data/settings-key'; import { SettingsKey } from '../data/settings-key';
@ -64,7 +62,6 @@ function createSessionInboxStore() {
.getConversations() .getConversations()
.map(conversation => conversation.getConversationModelProps()); .map(conversation => conversation.getConversationModelProps());
const timerOptions: TimerOptionsArray = ExpirationTimerOptions.getTimerSecondsWithName();
const initialState: StateType = { const initialState: StateType = {
conversations: { conversations: {
...getEmptyConversationState(), ...getEmptyConversationState(),
@ -82,9 +79,6 @@ function createSessionInboxStore() {
onionPaths: initialOnionPathState, onionPaths: initialOnionPathState,
modals: initialModalState, modals: initialModalState,
userConfig: initialUserConfigState, userConfig: initialUserConfigState,
timerOptions: {
timerOptions,
},
stagedAttachments: getEmptyStagedAttachmentsState(), stagedAttachments: getEmptyStagedAttachmentsState(),
call: initialCallState, call: initialCallState,
sogsRoomInfo: initialSogsRoomInfoState, sogsRoomInfo: initialSogsRoomInfoState,

@ -1,6 +1,6 @@
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import React from 'react'; import React from 'react';
import { TimerOptionsArray } from '../../../../../state/ducks/timerOptions'; import { TimerOptionsArray } from '../../../../../util/expiringMessages';
import { PanelButtonGroup, PanelLabel } from '../../../../buttons/PanelButton'; import { PanelButtonGroup, PanelLabel } from '../../../../buttons/PanelButton';
import { PanelRadioButton } from '../../../../buttons/PanelRadioButton'; import { PanelRadioButton } from '../../../../buttons/PanelRadioButton';

@ -1,4 +1,5 @@
import { compact, isEmpty, isFinite, isNumber } from 'lodash'; import { compact, isEmpty, isFinite, isNumber } from 'lodash';
import { useMemo } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { import {
hasValidIncomingRequestValues, hasValidIncomingRequestValues,
@ -9,8 +10,16 @@ import { CONVERSATION } from '../session/constants';
import { PubKey } from '../session/types'; import { PubKey } from '../session/types';
import { UserUtils } from '../session/utils'; import { UserUtils } from '../session/utils';
import { StateType } from '../state/reducer'; import { StateType } from '../state/reducer';
import { getMessageReactsProps, getMessageExpirationProps } from '../state/selectors/conversations'; import { getMessageExpirationProps, getMessageReactsProps } from '../state/selectors/conversations';
import { isPrivateAndFriend } from '../state/selectors/selectedConversation'; import { isPrivateAndFriend } from '../state/selectors/selectedConversation';
import {
DELETE_AFTER_READ_OPTIONS,
DELETE_AFTER_SEND_OPTIONS,
DELETE_LEGACY_OPTIONS,
ExpirationTimerOptions,
TIMER_OPTIONS,
TimerOptionsArray,
} from '../util/expiringMessages';
export function useAvatarPath(convoId: string | undefined) { export function useAvatarPath(convoId: string | undefined) {
const convoProps = useConversationPropsById(convoId); const convoProps = useConversationPropsById(convoId);
@ -280,63 +289,46 @@ export function useMessageExpirationPropsById(messageId?: string) {
}); });
} }
// TODO use env variable to toggle test values?
// https://github.com/oxen-io/session-desktop/pull/2660/files#r1174823750
export function useTimerOptionsByMode(disappearingMessageMode?: string, hasOnlyOneMode?: boolean) { export function useTimerOptionsByMode(disappearingMessageMode?: string, hasOnlyOneMode?: boolean) {
return useSelector((state: StateType) => { return useMemo(() => {
const options = state.timerOptions.timerOptions; const options: TimerOptionsArray = [];
if (hasOnlyOneMode) {
options.push({
name: ExpirationTimerOptions.getName(TIMER_OPTIONS[0]),
value: TIMER_OPTIONS[0],
});
}
switch (disappearingMessageMode) { switch (disappearingMessageMode) {
// TODO legacy messages support will be removed in a future release // TODO legacy messages support will be removed in a future release
case 'legacy': case 'legacy':
return options.filter(option => { options.push(
return ( ...DELETE_LEGACY_OPTIONS.map(option => ({
(hasOnlyOneMode && option.value === 0) || name: ExpirationTimerOptions.getName(option),
option.value === 5 || // 5 seconds value: option,
option.value === 10 || // 10 seconds }))
option.value === 30 || // 30 seconds );
option.value === 60 || // 1 minute break;
option.value === 300 || // 5 minutes
option.value === 1800 || // 30 minutes
option.value === 3600 || // 1 hour
option.value === 21600 || // 6 hours
option.value === 43200 || // 12 hours
option.value === 86400 || // 1 day
option.value === 604800 // 1 week
);
});
case 'deleteAfterSend':
return options.filter(option => {
return (
(hasOnlyOneMode && option.value === 0) ||
// option.value === 10 || // 10 seconds (for development)
// option.value === 30 || // 30 seconds (for development)
option.value === 60 || // 1 minute (for testing)
option.value === 43200 || // 12 hours
option.value === 86400 || // 1 day
option.value === 604800 || // 1 week
option.value === 1209600 // 2 weeks
);
});
case 'deleteAfterRead': case 'deleteAfterRead':
return options.filter(option => { options.push(
return ( ...DELETE_AFTER_READ_OPTIONS.map(option => ({
(hasOnlyOneMode && option.value === 0) || name: ExpirationTimerOptions.getName(option),
// option.value === 10 || // 10 seconds (for development) value: option,
// option.value === 30 || // 30 seconds (for development) }))
option.value === 60 || // 1 minute (for testing) );
option.value === 300 || // 5 minutes break;
option.value === 3600 || // 1 hour case 'deleteAfterSend':
option.value === 43200 || // 12 hours options.push(
option.value === 86400 || // 1 day ...DELETE_AFTER_SEND_OPTIONS.map(option => ({
option.value === 604800 || // 1 week name: ExpirationTimerOptions.getName(option),
option.value === 1209600 // 2 weeks value: option,
); }))
}); );
break;
default: default:
return []; return [];
} }
}); return options;
}, [disappearingMessageMode, hasOnlyOneMode]);
} }
export function useQuoteAuthorName( export function useQuoteAuthorName(

@ -1,30 +0,0 @@
/**
* This slice is intended for the user configurable settings for the client such as appearance, autoplaying of links etc.
* Anything setting under the cog wheel tab.
*/
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
type TimerOptionsEntry = { name: string; value: number };
export type TimerOptionsArray = Array<TimerOptionsEntry>;
export type TimerOptionsState = {
timerOptions: TimerOptionsArray;
};
export const initialTimerOptionsState: TimerOptionsState = {
timerOptions: [],
};
const timerOptionSlice = createSlice({
name: 'timerOptions',
initialState: initialTimerOptionsState,
reducers: {
updateTimerOptions: (state, action: PayloadAction<TimerOptionsArray>) => {
return { ...state, timerOptions: action.payload };
},
},
});
const { actions, reducer } = timerOptionSlice;
export const { updateTimerOptions } = actions;
export const timerOptionReducer = reducer;

@ -1,25 +1,24 @@
import { combineReducers } from '@reduxjs/toolkit'; import { combineReducers } from '@reduxjs/toolkit';
import { reducer as search, SearchStateType } from './ducks/search'; import { callReducer as call, CallStateType } from './ducks/call';
import { ConversationsStateType, reducer as conversations } from './ducks/conversations'; import { reducer as conversations, ConversationsStateType } from './ducks/conversations';
import { reducer as user, UserStateType } from './ducks/user'; import { defaultRoomReducer as defaultRooms, DefaultRoomsState } from './ducks/defaultRooms';
import { reducer as theme } from './ducks/theme';
import { reducer as primaryColor } from './ducks/primaryColor'; import { reducer as primaryColor } from './ducks/primaryColor';
import { reducer as search, SearchStateType } from './ducks/search';
import { reducer as section, SectionStateType } from './ducks/section'; import { reducer as section, SectionStateType } from './ducks/section';
import { defaultRoomReducer as defaultRooms, DefaultRoomsState } from './ducks/defaultRooms';
import { ReduxSogsRoomInfos, SogsRoomInfoState } from './ducks/sogsRoomInfo'; import { ReduxSogsRoomInfos, SogsRoomInfoState } from './ducks/sogsRoomInfo';
import { callReducer as call, CallStateType } from './ducks/call'; import { reducer as theme } from './ducks/theme';
import { reducer as user, UserStateType } from './ducks/user';
import { defaultOnionReducer as onionPaths, OnionState } from './ducks/onion'; import { PrimaryColorStateType, ThemeStateType } from '../themes/constants/colors';
import { modalReducer as modals, ModalState } from './ducks/modalDialog'; import { modalReducer as modals, ModalState } from './ducks/modalDialog';
import { userConfigReducer as userConfig, UserConfigState } from './ducks/userConfig'; import { defaultOnionReducer as onionPaths, OnionState } from './ducks/onion';
import { timerOptionReducer as timerOptions, TimerOptionsState } from './ducks/timerOptions'; import { settingsReducer, SettingsState } from './ducks/settings';
import { import {
reducer as stagedAttachments, reducer as stagedAttachments,
StagedAttachmentsStateType, StagedAttachmentsStateType,
} from './ducks/stagedAttachments'; } from './ducks/stagedAttachments';
import { PrimaryColorStateType, ThemeStateType } from '../themes/constants/colors'; import { userConfigReducer as userConfig, UserConfigState } from './ducks/userConfig';
import { settingsReducer, SettingsState } from './ducks/settings';
export type StateType = { export type StateType = {
search: SearchStateType; search: SearchStateType;
@ -32,7 +31,6 @@ export type StateType = {
onionPaths: OnionState; onionPaths: OnionState;
modals: ModalState; modals: ModalState;
userConfig: UserConfigState; userConfig: UserConfigState;
timerOptions: TimerOptionsState;
stagedAttachments: StagedAttachmentsStateType; stagedAttachments: StagedAttachmentsStateType;
call: CallStateType; call: CallStateType;
sogsRoomInfo: SogsRoomInfoState; sogsRoomInfo: SogsRoomInfoState;
@ -50,7 +48,6 @@ export const reducers = {
onionPaths, onionPaths,
modals, modals,
userConfig, userConfig,
timerOptions,
stagedAttachments, stagedAttachments,
call, call,
sogsRoomInfo: ReduxSogsRoomInfos.sogsRoomInfoReducer, sogsRoomInfo: ReduxSogsRoomInfos.sogsRoomInfoReducer,

@ -7,7 +7,6 @@ import * as SearchSelectors from './search';
import * as SectionSelectors from './section'; import * as SectionSelectors from './section';
import * as StagedAttachmentSelectors from './stagedAttachments'; import * as StagedAttachmentSelectors from './stagedAttachments';
import * as ThemeSelectors from './theme'; import * as ThemeSelectors from './theme';
import * as TimerOptionsSelectors from './timerOptions';
import * as UserSelectors from './user'; import * as UserSelectors from './user';
import * as UserConfigSelectors from './userConfig'; import * as UserConfigSelectors from './userConfig';
@ -21,7 +20,6 @@ export {
SectionSelectors, SectionSelectors,
StagedAttachmentSelectors, StagedAttachmentSelectors,
ThemeSelectors, ThemeSelectors,
TimerOptionsSelectors,
UserConfigSelectors, UserConfigSelectors,
UserSelectors, UserSelectors,
}; };

@ -1,4 +0,0 @@
import { StateType } from '../reducer';
import { TimerOptionsState } from '../ducks/timerOptions';
export const getTimerOptions = (state: StateType): TimerOptionsState => state.timerOptions;

@ -1,7 +1,6 @@
import { throttle, uniq } from 'lodash'; import { throttle, uniq } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import { messagesExpired } from '../state/ducks/conversations'; import { messagesExpired } from '../state/ducks/conversations';
import { TimerOptionsArray } from '../state/ducks/timerOptions';
import { LocalizerKeys } from '../types/LocalizerKeys'; import { LocalizerKeys } from '../types/LocalizerKeys';
import { initWallClockListener } from './wallClockListener'; import { initWallClockListener } from './wallClockListener';
@ -31,12 +30,6 @@ export const DisappearingMessageConversationModes = [
] as const; ] as const;
export type DisappearingMessageConversationModeType = typeof DisappearingMessageConversationModes[number]; // TODO we should make this type a bit more hardcoded than being just resolved as a string export type DisappearingMessageConversationModeType = typeof DisappearingMessageConversationModes[number]; // TODO we should make this type a bit more hardcoded than being just resolved as a string
export const DEFAULT_TIMER_OPTION = {
DELETE_AFTER_READ: 43200, // 12 hours
DELETE_AFTER_SEND: 86400, // 1 day
LEGACY: 86400, // 1 day
};
// TODO legacy messages support will be removed in a future release // TODO legacy messages support will be removed in a future release
// expirationType and lastDisappearingMessageChangeTimestamp will no longer have an undefined option // expirationType and lastDisappearingMessageChangeTimestamp will no longer have an undefined option
/** Used for setting disappearing messages in conversations */ /** Used for setting disappearing messages in conversations */
@ -185,15 +178,7 @@ const updateExpiringMessagesCheck = () => {
void throttledCheckExpiringMessages(); void throttledCheckExpiringMessages();
}; };
function getTimerOptionName(time: number, unit: moment.DurationInputArg2) { // #region Timer Options
return (
window.i18n(['timerOption', time, unit].join('_') as LocalizerKeys) ||
moment.duration(time, unit).humanize()
);
}
function getTimerOptionAbbreviated(time: number, unit: string) {
return window.i18n(['timerOption', time, unit, 'abbreviated'].join('_') as LocalizerKeys);
}
const timerOptionsDurations: Array<{ const timerOptionsDurations: Array<{
time: number; time: number;
@ -222,6 +207,17 @@ const timerOptionsDurations: Array<{
}; };
}); });
function getTimerOptionName(time: number, unit: moment.DurationInputArg2) {
return (
window.i18n(['timerOption', time, unit].join('_') as LocalizerKeys) ||
moment.duration(time, unit).humanize()
);
}
function getTimerOptionAbbreviated(time: number, unit: string) {
return window.i18n(['timerOption', time, unit, 'abbreviated'].join('_') as LocalizerKeys);
}
function getName(seconds = 0) { function getName(seconds = 0) {
const o = timerOptionsDurations.find(m => m.seconds === seconds); const o = timerOptionsDurations.find(m => m.seconds === seconds);
@ -230,6 +226,7 @@ function getName(seconds = 0) {
} }
return [seconds, 'seconds'].join(' '); return [seconds, 'seconds'].join(' ');
} }
function getAbbreviated(seconds = 0) { function getAbbreviated(seconds = 0) {
const o = timerOptionsDurations.find(m => m.seconds === seconds); const o = timerOptionsDurations.find(m => m.seconds === seconds);
@ -240,20 +237,72 @@ function getAbbreviated(seconds = 0) {
return [seconds, 's'].join(''); return [seconds, 's'].join('');
} }
function getTimerSecondsWithName(): TimerOptionsArray { type TimerOptionsEntry = { name: string; value: number };
return timerOptionsDurations.map(t => { export type TimerOptionsArray = Array<TimerOptionsEntry>;
return { name: getName(t.seconds), value: t.seconds };
}); export const TIMER_OPTIONS: Array<number> = timerOptionsDurations.map(t => {
} return t.seconds;
});
export const DELETE_AFTER_READ_OPTIONS = TIMER_OPTIONS.filter(option => {
return (
option === 10 || // 10 seconds (for development or qa)
option === 30 || // 30 seconds (for development or qa)
option === 60 || // 1 minute (for testing)
option === 300 || // 5 minutes
option === 3600 || // 1 hour
option === 43200 || // 12 hours
option === 86400 || // 1 day
option === 604800 || // 1 week
option === 1209600 // 2 weeks
);
});
export const DELETE_AFTER_SEND_OPTIONS = TIMER_OPTIONS.filter(option => {
return (
option === 10 || // 10 seconds (for development or qa)
option === 30 || // 30 seconds (for development or qa)
option === 60 || // 1 minute (for testing)
option === 43200 || // 12 hours
option === 86400 || // 1 day
option === 604800 || // 1 week
option === 1209600 // 2 weeks
);
});
// TODO legacy messages support will be removed in a future release
export const DELETE_LEGACY_OPTIONS = TIMER_OPTIONS.filter(option => {
return (
option === 5 || // 5 seconds
option === 10 || // 10 seconds
option === 30 || // 30 seconds
option === 60 || // 1 minute
option === 300 || // 5 minutes
option === 1800 || // 30 minutes
option === 3600 || // 1 hour
option === 21600 || // 6 hours
option === 43200 || // 12 hours
option === 86400 || // 1 day
option === 604800 // 1 week
);
});
export const DEFAULT_TIMER_OPTION = {
DELETE_AFTER_READ: 43200, // 12 hours
DELETE_AFTER_SEND: 86400, // 1 day
// TODO legacy messages support will be removed in a future release
LEGACY: 86400, // 1 day
};
export const ExpirationTimerOptions = { export const ExpirationTimerOptions = {
getName, getName,
getAbbreviated, getAbbreviated,
updateExpiringMessagesCheck, updateExpiringMessagesCheck,
initExpiringMessageListener, initExpiringMessageListener,
getTimerSecondsWithName,
}; };
// #endregion Timer Options
export function setExpirationStartTimestamp( export function setExpirationStartTimestamp(
mode: DisappearingMessageConversationModeType, mode: DisappearingMessageConversationModeType,
timestamp?: number, timestamp?: number,

Loading…
Cancel
Save