TelegramPWA/src/components/left/main/LeftSideMenuItems.tsx
2025-09-19 14:25:30 +02:00

281 lines
8.2 KiB
TypeScript

import type React from '../../../lib/teact/teact';
import { memo, useMemo } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiUser } from '../../../api/types';
import type { GlobalState } from '../../../global/types';
import type { AnimationLevel, ThemeKey } from '../../../types';
import {
ANIMATION_LEVEL_MAX,
ANIMATION_LEVEL_MIN,
ARCHIVED_FOLDER_ID,
BETA_CHANGELOG_URL,
FEEDBACK_URL,
IS_BETA,
IS_TEST,
PRODUCTION_HOSTNAME,
WEB_VERSION_BASE,
} from '../../../config';
import {
INITIAL_PERFORMANCE_STATE_MAX,
INITIAL_PERFORMANCE_STATE_MED,
INITIAL_PERFORMANCE_STATE_MIN,
} from '../../../global/initialState';
import { selectTabState, selectTheme, selectUser } from '../../../global/selectors';
import { selectPremiumLimit } from '../../../global/selectors/limits';
import { selectSharedSettings } from '../../../global/selectors/sharedState';
import { IS_MULTIACCOUNT_SUPPORTED } from '../../../util/browser/globalEnvironment';
import { IS_TAURI } from '../../../util/browser/globalEnvironment';
import { getPromptInstall } from '../../../util/installPrompt';
import { switchPermanentWebVersion } from '../../../util/permanentWebVersion';
import { useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManager';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import AttachBotItem from '../../middle/composer/AttachBotItem';
import MenuItem from '../../ui/MenuItem';
import MenuSeparator from '../../ui/MenuSeparator';
import Switcher from '../../ui/Switcher';
import Toggle from '../../ui/Toggle';
import AccountMenuItems from './AccountMenuItems';
type OwnProps = {
onSelectSettings: NoneToVoidFunction;
onSelectContacts: NoneToVoidFunction;
onSelectArchived: NoneToVoidFunction;
onBotMenuOpened: NoneToVoidFunction;
onBotMenuClosed: NoneToVoidFunction;
};
type StateProps = {
animationLevel: AnimationLevel;
currentUser?: ApiUser;
theme: ThemeKey;
canInstall?: boolean;
attachBots: GlobalState['attachMenu']['bots'];
accountsTotalLimit: number;
} & Pick<GlobalState, 'currentUserId' | 'archiveSettings'>;
const LeftSideMenuItems = ({
currentUserId,
archiveSettings,
animationLevel,
theme,
canInstall,
attachBots,
currentUser,
accountsTotalLimit,
onSelectArchived,
onSelectContacts,
onSelectSettings,
onBotMenuOpened,
onBotMenuClosed,
}: OwnProps & StateProps) => {
const {
openChat,
setSharedSettingOption,
updatePerformanceSettings,
openChatByUsername,
openUrl,
openChatWithInfo,
} = getActions();
const lang = useLang();
const animationLevelValue = animationLevel !== ANIMATION_LEVEL_MIN
? (animationLevel === ANIMATION_LEVEL_MAX ? 'max' : 'mid') : 'min';
const withOtherVersions = !IS_TAURI && (window.location.hostname === PRODUCTION_HOSTNAME || IS_TEST);
const archivedUnreadChatsCount = useFolderManagerForUnreadCounters()[ARCHIVED_FOLDER_ID]?.chatsCount || 0;
const bots = useMemo(() => Object.values(attachBots).filter((bot) => bot.isForSideMenu), [attachBots]);
const handleSelectMyProfile = useLastCallback(() => {
openChatWithInfo({ id: currentUserId, shouldReplaceHistory: true, profileTab: 'stories' });
});
const handleSelectSaved = useLastCallback(() => {
openChat({ id: currentUserId, shouldReplaceHistory: true });
});
const handleDarkModeToggle = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
const newTheme = theme === 'light' ? 'dark' : 'light';
setSharedSettingOption({ theme: newTheme });
setSharedSettingOption({ shouldUseSystemTheme: false });
});
const handleAnimationLevelChange = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
let newLevel = animationLevel + 1;
if (newLevel > ANIMATION_LEVEL_MAX) {
newLevel = ANIMATION_LEVEL_MIN;
}
const performanceSettings = newLevel === ANIMATION_LEVEL_MIN
? INITIAL_PERFORMANCE_STATE_MIN
: (newLevel === ANIMATION_LEVEL_MAX ? INITIAL_PERFORMANCE_STATE_MAX : INITIAL_PERFORMANCE_STATE_MED);
setSharedSettingOption({ animationLevel: newLevel as AnimationLevel, wasAnimationLevelSetManually: true });
updatePerformanceSettings(performanceSettings);
});
const handleChangelogClick = useLastCallback(() => {
window.open(BETA_CHANGELOG_URL, '_blank', 'noopener,noreferrer');
});
const handleSwitchToWebK = useLastCallback(() => {
switchPermanentWebVersion('K');
});
const handleOpenTipsChat = useLastCallback(() => {
openChatByUsername({ username: lang('TelegramFeaturesUsername') });
});
const handleBugReportClick = useLastCallback(() => {
openUrl({ url: FEEDBACK_URL });
});
return (
<>
{IS_MULTIACCOUNT_SUPPORTED && currentUser && (
<>
<AccountMenuItems
currentUser={currentUser}
totalLimit={accountsTotalLimit}
onSelectCurrent={onSelectSettings}
/>
<MenuSeparator />
</>
)}
<MenuItem
icon="user"
onClick={handleSelectMyProfile}
>
{lang('MenuMyProfile')}
</MenuItem>
<MenuItem
icon="saved-messages"
onClick={handleSelectSaved}
>
{lang('MenuSavedMessages')}
</MenuItem>
{archiveSettings.isHidden && (
<MenuItem
icon="archive"
onClick={onSelectArchived}
>
<span className="menu-item-name">{lang('MenuArchivedChats')}</span>
{archivedUnreadChatsCount > 0 && (
<div className="right-badge">{archivedUnreadChatsCount}</div>
)}
</MenuItem>
)}
<MenuItem
icon="group"
onClick={onSelectContacts}
>
{lang('MenuContacts')}
</MenuItem>
{bots.map((bot) => (
<AttachBotItem
bot={bot}
theme={theme}
isInSideMenu
canShowNew
onMenuOpened={onBotMenuOpened}
onMenuClosed={onBotMenuClosed}
/>
))}
<MenuItem
icon="settings"
onClick={onSelectSettings}
>
{lang('MenuSettings')}
</MenuItem>
<MenuItem
icon="darkmode"
onClick={handleDarkModeToggle}
>
<span className="menu-item-name">{lang('MenuNightMode')}</span>
<Switcher
id="darkmode"
label={lang(theme === 'dark' ? 'AriaMenuDisableNightMode' : 'AriaMenuEnableNightMode')}
checked={theme === 'dark'}
noAnimation
/>
</MenuItem>
<MenuItem
icon="animations"
onClick={handleAnimationLevelChange}
>
<span className="menu-item-name capitalize">{lang('MenuAnimationsSwitch')}</span>
<Toggle value={animationLevelValue} />
</MenuItem>
<MenuItem
icon="help"
onClick={handleOpenTipsChat}
>
{lang('MenuTelegramFeatures')}
</MenuItem>
<MenuItem
icon="bug"
onClick={handleBugReportClick}
>
{lang('MenuReportBug')}
</MenuItem>
{IS_BETA && (
<MenuItem
icon="permissions"
onClick={handleChangelogClick}
>
{lang('MenuBetaChangelog')}
</MenuItem>
)}
{withOtherVersions && (
<MenuItem
icon="K"
isCharIcon
href={`${WEB_VERSION_BASE}k`}
onClick={handleSwitchToWebK}
>
{lang('MenuSwitchToK')}
</MenuItem>
)}
{canInstall && (
<MenuItem
icon="install"
onClick={getPromptInstall()}
>
{lang('MenuInstallApp')}
</MenuItem>
)}
</>
);
};
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const tabState = selectTabState(global);
const {
currentUserId, archiveSettings,
} = global;
const { animationLevel } = selectSharedSettings(global);
const attachBots = global.attachMenu.bots;
return {
currentUserId,
currentUser: selectUser(global, currentUserId!),
theme: selectTheme(global),
animationLevel,
canInstall: Boolean(tabState.canInstall),
archiveSettings,
attachBots,
accountsTotalLimit: selectPremiumLimit(global, 'moreAccounts'),
};
},
)(LeftSideMenuItems));