diff --git a/ts/components/dialog/debug/DebugMenuModal.tsx b/ts/components/dialog/debug/DebugMenuModal.tsx
index cb855c63b..864933d3c 100644
--- a/ts/components/dialog/debug/DebugMenuModal.tsx
+++ b/ts/components/dialog/debug/DebugMenuModal.tsx
@@ -7,6 +7,7 @@ import { updateDebugMenuModal } from '../../../state/ducks/modalDialog';
import { AboutInfo, DebugActions, OtherInfo } from './components';
import { SessionWrapperModal } from '../../SessionWrapperModal';
import { FeatureFlags } from './FeatureFlags';
+import { ReleaseChannel } from './ReleaseChannel';
const StyledContent = styled(Flex)`
padding-inline: var(--margins-sm);
@@ -50,7 +51,9 @@ export function DebugMenuModal() {
-
+
+
+
diff --git a/ts/components/dialog/debug/ReleaseChannel.tsx b/ts/components/dialog/debug/ReleaseChannel.tsx
new file mode 100644
index 000000000..7d8848a1d
--- /dev/null
+++ b/ts/components/dialog/debug/ReleaseChannel.tsx
@@ -0,0 +1,93 @@
+import { capitalize } from 'lodash';
+import { useDispatch } from 'react-redux';
+import useUpdate from 'react-use/lib/useUpdate';
+import { localize } from '../../../localization/localeTools';
+import { updateConfirmModal } from '../../../state/ducks/modalDialog';
+import { Flex } from '../../basic/Flex';
+import { SessionButtonColor } from '../../basic/SessionButton';
+import { SessionRadioGroup } from '../../basic/SessionRadioGroup';
+import { HintText } from '../../basic/Text';
+import { ALPHA_CHANNEL, LATEST_CHANNEL, type ReleaseChannels } from '../../../updater/types';
+import { Storage } from '../../../util/storage';
+
+const items = [
+ {
+ label: capitalize(LATEST_CHANNEL),
+ value: LATEST_CHANNEL,
+ inputDataTestId: `input-releases-${LATEST_CHANNEL}` as const,
+ labelDataTestId: `label-releases-${LATEST_CHANNEL}` as const,
+ },
+ {
+ label: capitalize(ALPHA_CHANNEL),
+ value: ALPHA_CHANNEL,
+ inputDataTestId: `input-releases-${ALPHA_CHANNEL}` as const,
+ labelDataTestId: `label-releases-${ALPHA_CHANNEL}` as const,
+ },
+];
+
+export const ReleaseChannel = () => {
+ const forceUpdate = useUpdate();
+ const releaseChannel = Storage.get('releaseChannel') as ReleaseChannels;
+
+ const dispatch = useDispatch();
+
+ const changeReleaseChannel = (channel: ReleaseChannels) => {
+ window.log.debug(
+ `WIP: [debugMenu] release channel to ${channel} was ${Storage.get('releaseChannel') || 'not set'}`
+ );
+ if (Storage.get('releaseChannel') === channel) {
+ return;
+ }
+ dispatch(
+ updateConfirmModal({
+ title: localize('warning').toString(),
+ i18nMessage: { token: 'settingsRestartDescription' },
+ okTheme: SessionButtonColor.Danger,
+ okText: localize('restart').toString(),
+ onClickOk: async () => {
+ try {
+ await Storage.put('releaseChannel', channel);
+ } catch (error) {
+ window.log.warn(
+ `[debugMenu] Something went wrong when changing the release channel to ${channel} was ${Storage.get('releaseChannel') || 'not set'}:`,
+ error && error.stack ? error.stack : error
+ );
+ } finally {
+ window.restart();
+ }
+ },
+ onClickCancel: () => {
+ window.inboxStore?.dispatch(updateConfirmModal(null));
+ forceUpdate();
+ },
+ })
+ );
+ };
+
+ return (
+
+
+ Release Channel
+ Experimental
+
+ {
+ if (value === LATEST_CHANNEL || value === ALPHA_CHANNEL) {
+ changeReleaseChannel(value);
+ }
+ }}
+ style={{ margin: 0 }}
+ />
+
+ );
+};
diff --git a/ts/react.d.ts b/ts/react.d.ts
index 5ebfcde11..d3b5fc139 100644
--- a/ts/react.d.ts
+++ b/ts/react.d.ts
@@ -252,7 +252,11 @@ declare module 'react' {
| 'module-message-search-result__header__name__profile-name'
| 'module-message__author__profile-name'
| 'module-contact-name__profile-name'
- | 'delete-from-details';
+ | 'delete-from-details'
+ | 'input-releases-latest'
+ | 'input-releases-alpha'
+ | 'label-releases-latest'
+ | 'label-releases-alpha';
interface HTMLAttributes {
'data-testid'?: SessionDataTestId;
diff --git a/ts/updater/types.ts b/ts/updater/types.ts
new file mode 100644
index 000000000..8a49355ee
--- /dev/null
+++ b/ts/updater/types.ts
@@ -0,0 +1,4 @@
+export const LATEST_CHANNEL = 'latest' as const;
+export const ALPHA_CHANNEL = 'alpha' as const;
+
+export type ReleaseChannels = typeof LATEST_CHANNEL | typeof ALPHA_CHANNEL;