From 290cc5f8fee94c740fe4fdbe69e1f1f3a272bb82 Mon Sep 17 00:00:00 2001 From: yougotwill Date: Mon, 17 Feb 2025 15:15:52 +1100 Subject: [PATCH 1/3] feat: have a user method to toggle the debug menu new redux slice for debug state --- ts/components/SessionInboxView.tsx | 2 ++ ts/components/leftpane/ActionsPanel.tsx | 4 +++- ts/components/settings/SessionSettings.tsx | 17 ++++++++++++++- ts/state/ducks/debug.tsx | 24 ++++++++++++++++++++++ ts/state/reducer.ts | 3 +++ ts/state/selectors/debug.ts | 10 +++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 ts/state/ducks/debug.tsx create mode 100644 ts/state/selectors/debug.ts diff --git a/ts/components/SessionInboxView.tsx b/ts/components/SessionInboxView.tsx index c1e7c5c4d..f1da22b84 100644 --- a/ts/components/SessionInboxView.tsx +++ b/ts/components/SessionInboxView.tsx @@ -41,6 +41,7 @@ import { UserGroupsWrapperActions } from '../webworker/workers/browser/libsessio import { NoticeBanner } from './NoticeBanner'; import { Flex } from './basic/Flex'; import { initialReleasedFeaturesState } from '../state/ducks/releasedFeatures'; +import { initialDebugState } from '../state/ducks/debug'; function makeLookup(items: Array, key: string): { [key: string]: T } { // Yep, we can't index into item without knowing what it is. True. But we want to. @@ -90,6 +91,7 @@ async function createSessionInboxStore() { groups: initialGroupState, userGroups: { userGroups }, releasedFeatures: initialReleasedFeaturesState, + debug: initialDebugState, }; return createStore(initialState); diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx index 2a3c2e0b8..4cfd49d34 100644 --- a/ts/components/leftpane/ActionsPanel.tsx +++ b/ts/components/leftpane/ActionsPanel.tsx @@ -54,6 +54,7 @@ import { getIsModalVisible } from '../../state/selectors/modal'; import { ReleasedFeatures } from '../../util/releaseFeature'; import { MessageQueue } from '../../session/sending'; import { useRefreshReleasedFeaturesTimestamp } from '../../hooks/useRefreshReleasedFeaturesTimestamp'; +import { useDebugMode } from '../../state/selectors/debug'; const Section = (props: { type: SectionType }) => { const ourNumber = useSelector(getOurNumber); @@ -259,7 +260,7 @@ function useUpdateBadgeCount() { export const ActionsPanel = () => { const [startCleanUpMedia, setStartCleanUpMedia] = useState(false); const ourPrimaryConversation = useSelector(getOurPrimaryConversation); - const showDebugMenu = window?.sessionFeatureFlags?.debug?.debugLogging; + const showDebugMenu = useDebugMode(); // this maxi useEffect is called only once: when the component is mounted. // For the action panel, it means this is called only one per app start/with a user logged in @@ -322,6 +323,7 @@ export const ActionsPanel = () => { window?.log?.warn('ActionsPanel: ourPrimaryConversation is not set'); return null; } + return ( <> diff --git a/ts/components/settings/SessionSettings.tsx b/ts/components/settings/SessionSettings.tsx index e49151921..aacc61036 100644 --- a/ts/components/settings/SessionSettings.tsx +++ b/ts/components/settings/SessionSettings.tsx @@ -20,6 +20,7 @@ import { SettingsCategoryHelp } from './section/CategoryHelp'; import { SettingsCategoryPermissions } from './section/CategoryPermissions'; import { SettingsCategoryPrivacy } from './section/CategoryPrivacy'; import { SettingsCategoryRecoveryPassword } from './section/CategoryRecoveryPassword'; +import { setDebugMode } from '../../state/ducks/debug'; export function displayPasswordModal( passwordAction: PasswordAction, @@ -68,6 +69,10 @@ const StyledSpanSessionInfo = styled.span` `; const SessionInfo = () => { + const [clickCount, setClickCount] = useState(0); + + const dispatch = useDispatch(); + return ( { }} /> - {window.versionInfo.commitHash} + { + setClickCount(clickCount + 1); + if (clickCount === 10) { + dispatch(setDebugMode(true)); + setClickCount(0); + } + }} + > + {window.versionInfo.commitHash} + ); }; diff --git a/ts/state/ducks/debug.tsx b/ts/state/ducks/debug.tsx new file mode 100644 index 000000000..f263b833b --- /dev/null +++ b/ts/state/ducks/debug.tsx @@ -0,0 +1,24 @@ +import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; + +export interface DebugState { + debugMode: boolean; +} + +export const initialDebugState = { + debugMode: false, +}; + +const debugSlice = createSlice({ + name: 'debug', + initialState: initialDebugState, + reducers: { + setDebugMode: (state, action: PayloadAction) => { + (window as Window).sessionFeatureFlags.debug.debugLogging = action.payload; + return { ...state, debugMode: action.payload }; + }, + }, +}); + +const { actions, reducer } = debugSlice; +export const { setDebugMode } = actions; +export const debugReducer = reducer; diff --git a/ts/state/reducer.ts b/ts/state/reducer.ts index 9b6620679..d5f4336d5 100644 --- a/ts/state/reducer.ts +++ b/ts/state/reducer.ts @@ -22,6 +22,7 @@ import { import { userConfigReducer as userConfig, UserConfigState } from './ducks/userConfig'; import { userGroupReducer, UserGroupState } from './ducks/userGroups'; import { releasedFeaturesReducer, ReleasedFeaturesState } from './ducks/releasedFeatures'; +import { debugReducer, type DebugState } from './ducks/debug'; export type StateType = { search: SearchStateType; @@ -41,6 +42,7 @@ export type StateType = { groups: GroupState; userGroups: UserGroupState; releasedFeatures: ReleasedFeaturesState; + debug: DebugState; }; const reducers = { @@ -61,6 +63,7 @@ const reducers = { groups: groupReducer, userGroups: userGroupReducer, releasedFeatures: releasedFeaturesReducer, + debug: debugReducer, }; // Making this work would require that our reducer signature supported AnyAction, not diff --git a/ts/state/selectors/debug.ts b/ts/state/selectors/debug.ts new file mode 100644 index 000000000..7a79d83c0 --- /dev/null +++ b/ts/state/selectors/debug.ts @@ -0,0 +1,10 @@ +import { useSelector } from 'react-redux'; +import type { StateType } from '../reducer'; + +const getDebugMode = (state: StateType): boolean => { + return window.sessionFeatureFlags.debug.debugLogging || state.debug.debugMode; +}; + +export const useDebugMode = (): boolean => { + return useSelector(getDebugMode); +}; From c9ed54b1d89de9fdf73e0064627072fb01645f2d Mon Sep 17 00:00:00 2001 From: yougotwill Date: Mon, 17 Feb 2025 15:32:45 +1100 Subject: [PATCH 2/3] feat: added exit debug mode button to modal --- ts/components/dialog/debug/components.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ts/components/dialog/debug/components.tsx b/ts/components/dialog/debug/components.tsx index cdbe37823..05c76d7ab 100644 --- a/ts/components/dialog/debug/components.tsx +++ b/ts/components/dialog/debug/components.tsx @@ -3,6 +3,7 @@ import useUpdate from 'react-use/lib/useUpdate'; import useAsync from 'react-use/lib/useAsync'; import { shell } from 'electron'; import useBoolean from 'react-use/lib/useBoolean'; +import { useDispatch } from 'react-redux'; import type { SessionFeatureFlagsKeys } from '../../../window'; import { Flex } from '../../basic/Flex'; import { SessionToggle } from '../../basic/SessionToggle'; @@ -11,14 +12,18 @@ import { localize } from '../../../localization/localeTools'; import { CopyToClipboardIcon } from '../../buttons'; import { saveLogToDesktop } from '../../../util/logging'; import { Localizer } from '../../basic/Localizer'; -import { SessionButton } from '../../basic/SessionButton'; +import { SessionButton, SessionButtonColor } from '../../basic/SessionButton'; import { ToastUtils, UserUtils } from '../../../session/utils'; import { getLatestReleaseFromFileServer } from '../../../session/apis/file_server_api/FileServerApi'; import { SessionSpinner } from '../../loading'; +import { setDebugMode } from '../../../state/ducks/debug'; +import { updateDebugMenuModal } from '../../../state/ducks/modalDialog'; export const DebugActions = () => { const [loadingLatestRelease, setLoadingLatestRelease] = useBoolean(false); + const dispatch = useDispatch(); + return ( <>

Actions

@@ -31,6 +36,16 @@ export const DebugActions = () => { flexWrap="wrap" flexGap="var(--margins-md) var(--margins-lg)" > + { + dispatch(setDebugMode(false)); + dispatch(updateDebugMenuModal(null)); + }} + > + Exit Debug Mode + + { void saveLogToDesktop(); From 181432b0d4ca11e906144e497f72c90bd30d3eeb Mon Sep 17 00:00:00 2001 From: yougotwill Date: Mon, 17 Feb 2025 16:31:16 +1100 Subject: [PATCH 3/3] fix: addressed review feedback no changes just refactoring --- ts/state/ducks/debug.tsx | 3 ++- ts/state/selectors/debug.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ts/state/ducks/debug.tsx b/ts/state/ducks/debug.tsx index f263b833b..e0ed552ea 100644 --- a/ts/state/ducks/debug.tsx +++ b/ts/state/ducks/debug.tsx @@ -14,7 +14,8 @@ const debugSlice = createSlice({ reducers: { setDebugMode: (state, action: PayloadAction) => { (window as Window).sessionFeatureFlags.debug.debugLogging = action.payload; - return { ...state, debugMode: action.payload }; + state.debugMode = action.payload; + return state; }, }, }); diff --git a/ts/state/selectors/debug.ts b/ts/state/selectors/debug.ts index 7a79d83c0..28ddde742 100644 --- a/ts/state/selectors/debug.ts +++ b/ts/state/selectors/debug.ts @@ -2,7 +2,7 @@ import { useSelector } from 'react-redux'; import type { StateType } from '../reducer'; const getDebugMode = (state: StateType): boolean => { - return window.sessionFeatureFlags.debug.debugLogging || state.debug.debugMode; + return window.sessionFeatureFlags?.debug?.debugLogging || state?.debug?.debugMode || false; }; export const useDebugMode = (): boolean => {