fix(app): correct shortcuts, nagbar, stream menu, share audio (#2599)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-08 19:09:59 +02:00
1 parent 55846b24ea
commit fc2b6b5299
37 files changed
+1074 -268

No files matched your search

@@ -25,7 +25,6 @@ import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
import {modal} from '@app/features/ui/commands/ModalCommands';
import * as PopoutCommands from '@app/features/ui/commands/PopoutCommands';
import * as TextCopyCommands from '@app/features/ui/commands/TextCopyCommands';
import * as ToastCommands from '@app/features/ui/commands/ToastCommands';
import {MockAvatar} from '@app/features/ui/components/MockAvatar';
import {StatusIndicator} from '@app/features/ui/components/StatusIndicator';
import FocusRing from '@app/features/ui/focus_ring/FocusRing';
@@ -52,9 +51,8 @@ import Users from '@app/features/user/state/Users';
import * as NicknameUtils from '@app/features/user/utils/NicknameUtils';
import * as ProfileDisplayUtils from '@app/features/user/utils/ProfileDisplayUtils';
import {createMockProfile} from '@app/features/user/utils/ProfileUtils';
import {COPIED_STATS_JSON_DESCRIPTOR} from '@app/features/voice/components/StatsForNerdsCopyDescriptors';
import {copyVoiceDiagnostics} from '@app/features/voice/commands/VoiceDiagnosticsCommands';
import MediaEngine from '@app/features/voice/engine/MediaEngineFacade';
import {buildStatsForNerdsCopyPayload, collectStatsForNerdsSnapshot} from '@app/features/voice/utils/StatsForNerdsCopy';
import {MEDIA_PROXY_PROFILE_BANNER_SIZE_POPOUT} from '@fluxer/constants/src/MediaProxyAssetSizes';
import {StatusTypes} from '@fluxer/constants/src/StatusConstants';
import type {MessageDescriptor} from '@lingui/core';
@@ -462,12 +460,7 @@ export const UserAreaPopout = observer(() => {
});
}, [i18n]);
const handleCopyStats = useCallback(() => {
const data = collectStatsForNerdsSnapshot();
void buildStatsForNerdsCopyPayload(data).then((payload) => {
void navigator.clipboard.writeText(JSON.stringify(payload, null, 2)).then(() => {
ToastCommands.createToast({type: 'success', children: i18n._(COPIED_STATS_JSON_DESCRIPTOR)});
});
});
void copyVoiceDiagnostics(i18n);
}, [i18n]);
const handleCopyUserTag = useCallback(() => {
if (!currentUser) {
@@ -1277,6 +1277,7 @@ const SKELETON_NAGBAR_ROW_SHAPES: Record<NagbarType, SkeletonNagbarRowShape> = {
[NagbarType.PREMIUM_ONBOARDING]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.GIFT_INVENTORY]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.DESKTOP_DOWNLOAD]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.DESKTOP_UPDATE_READY]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.GUILD_MEMBERSHIP_CTA]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.VISIONARY_MFA]: {tone: SkeletonNagbarTone.BRAND, hasActions: true},
[NagbarType.VOICE_SESSION_RESTORE]: {tone: SkeletonNagbarTone.VOICE, hasActions: true},
@@ -11,6 +11,7 @@ import Config from '@app/features/app/config/Config';
import {isClientReconnecting} from '@app/features/app/state/ClientReadiness';
import Initialization from '@app/features/app/state/Initialization';
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
import Updater from '@app/features/app/state/Updater';
import Authentication from '@app/features/auth/state/Authentication';
import Channels from '@app/features/channel/state/Channels';
import DeveloperOptions from '@app/features/devtools/state/DeveloperOptions';
@@ -230,6 +231,7 @@ export const useNagbarConditions = (): NagbarConditions => {
const canShowLinuxInputAccess = NativePermission.shouldShowLinuxInputAccessNagbar;
const canShowSoftwareEncoder = SoftwareEncoderWarning.showWarning;
const canShowStreamerMode = StreamerMode.shouldShowNagbar;
const canShowDesktopUpdateReady = Updater.shouldShowUpdateReadyNagbar;
const canShowBuildEnvironment =
!BUILD_ENVIRONMENT_HIDDEN_RELEASE_CHANNELS.has(Config.PUBLIC_RELEASE_CHANNEL) &&
!nagbarState.buildEnvironmentDismissedThisSession;
@@ -288,6 +290,7 @@ export const useNagbarConditions = (): NagbarConditions => {
canShowLinuxInputAccess,
canShowSoftwareEncoder,
canShowStreamerMode,
canShowDesktopUpdateReady,
};
};
export const useActiveNagbars = (conditions: NagbarConditions): Array<NagbarState> => {
@@ -407,6 +410,12 @@ export const useActiveNagbars = (conditions: NagbarConditions): Array<NagbarStat
visible: conditions.canShowStreamerMode,
dismissible: true,
},
{
type: NagbarType.DESKTOP_UPDATE_READY,
priority: -1.5,
visible: conditions.canShowDesktopUpdateReady,
dismissible: true,
},
];
return selectVisibleNagbars(nagbars);
}, [conditions]);
@@ -15,6 +15,7 @@ export const NagbarType = {
PREMIUM_ONBOARDING: 'premium-onboarding',
GIFT_INVENTORY: 'gift-inventory',
DESKTOP_DOWNLOAD: 'desktop-download',
DESKTOP_UPDATE_READY: 'desktop-update-ready',
GUILD_MEMBERSHIP_CTA: 'guild-membership-cta',
VISIONARY_MFA: 'visionary-mfa',
VOICE_SESSION_RESTORE: 'voice-session-restore',
@@ -50,6 +51,7 @@ export interface NagbarConditions {
canShowPremiumOnboarding: boolean;
canShowGiftInventory: boolean;
canShowDesktopDownload: boolean;
canShowDesktopUpdateReady: boolean;
canShowGuildMembershipCta: boolean;
canShowVisionaryMfa: boolean;
canShowVoiceSessionRestore: boolean;
@@ -7,6 +7,7 @@ import {ConnectionNagbar} from '@app/features/app/components/layout/app_layout/n
import {CorruptedInstallationNagbar} from '@app/features/app/components/layout/app_layout/nagbars/CorruptedInstallationNagbar';
import {DesktopDownloadNagbar} from '@app/features/app/components/layout/app_layout/nagbars/DesktopDownloadNagbar';
import {DesktopNotificationNagbar} from '@app/features/app/components/layout/app_layout/nagbars/DesktopNotificationNagbar';
import {DesktopUpdateReadyNagbar} from '@app/features/app/components/layout/app_layout/nagbars/DesktopUpdateReadyNagbar';
import {EmailVerificationNagbar} from '@app/features/app/components/layout/app_layout/nagbars/EmailVerificationNagbar';
import {GiftInventoryNagbar} from '@app/features/app/components/layout/app_layout/nagbars/GiftInventoryNagbar';
import {GuildMembershipCtaNagbar} from '@app/features/app/components/layout/app_layout/nagbars/GuildMembershipCtaNagbar';
@@ -153,6 +154,14 @@ export const NagbarContainer: React.FC<NagbarContainerProps> = observer(({nagbar
data-flx="app.app-layout.nagbar-container.desktop-download-nagbar"
/>
);
case NagbarType.DESKTOP_UPDATE_READY:
return (
<DesktopUpdateReadyNagbar
key={nagbar.type}
isMobile={mobileLayout.enabled}
data-flx="app.app-layout.nagbar-container.desktop-update-ready-nagbar"
/>
);
case NagbarType.GUILD_MEMBERSHIP_CTA:
return (
<GuildMembershipCtaNagbar
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {Nagbar} from '@app/features/app/components/layout/Nagbar';
import {NagbarButton} from '@app/features/app/components/layout/NagbarButton';
import {NagbarContent} from '@app/features/app/components/layout/NagbarContent';
import {NAGBAR_TONES, NagbarToneKind} from '@app/features/app/components/layout/NagbarTones';
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
import Updater from '@app/features/app/state/Updater';
import {
DESKTOP_VERSION_HAS_BEEN_DOWNLOADED_DESCRIPTOR,
RESTART_FLUXER_DESCRIPTOR,
THE_DESKTOP_UPDATE_HAS_BEEN_DOWNLOADED_DESCRIPTOR,
} from '@app/features/updater/commands/UpdaterModalCommands';
import {useLingui} from '@lingui/react/macro';
import {observer} from 'mobx-react-lite';
export const DesktopUpdateReadyNagbar = observer(({isMobile}: {isMobile: boolean}) => {
const {i18n} = useLingui();
const version = Updater.updateInfo.native.version;
return (
<Nagbar
isMobile={isMobile}
backgroundColor={NAGBAR_TONES[NagbarToneKind.BRAND].backgroundColor}
textColor={NAGBAR_TONES[NagbarToneKind.BRAND].textColor}
dismissible
onDismiss={Updater.dismissUpdateReadyNagbar}
data-flx="app.app-layout.nagbars.desktop-update-ready-nagbar.nagbar"
>
<NagbarContent
isMobile={isMobile}
onDismiss={Updater.dismissUpdateReadyNagbar}
message={
version
? i18n._(DESKTOP_VERSION_HAS_BEEN_DOWNLOADED_DESCRIPTOR, {version, productName: PRODUCT_NAME})
: i18n._(THE_DESKTOP_UPDATE_HAS_BEEN_DOWNLOADED_DESCRIPTOR, {productName: PRODUCT_NAME})
}
actions={
<NagbarButton
isMobile={isMobile}
onClick={() => void Updater.applyUpdate()}
data-flx="app.app-layout.nagbars.desktop-update-ready-nagbar.restart-button"
>
{i18n._(RESTART_FLUXER_DESCRIPTOR, {productName: PRODUCT_NAME})}
</NagbarButton>
}
data-flx="app.app-layout.nagbars.desktop-update-ready-nagbar.nagbar-content"
/>
</Nagbar>
);
});