mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(app): stop own profile preview trapping mobile web (#3463)
This commit is contained in:
1 parent
d7bbe933fa
commit
381699623e
4 files changed
+66
-38
No files matched your search
@@ -766,6 +766,7 @@ export const UserProfileModal: UserProfileModalComponent = observer(
|
|||||||
return (
|
return (
|
||||||
<Modal.Root
|
<Modal.Root
|
||||||
size="medium"
|
size="medium"
|
||||||
|
centered
|
||||||
initialFocusRef={autoFocusNote ? noteRef : undefined}
|
initialFocusRef={autoFocusNote ? noteRef : undefined}
|
||||||
className={userProfileModalStyles.modalRoot}
|
className={userProfileModalStyles.modalRoot}
|
||||||
data-flx="user.user-profile-modal.modal-root"
|
data-flx="user.user-profile-modal.modal-root"
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import * as UserCommands from '@app/features/user/commands/UserCommands';
|
|||||||
import * as UserProfileCommands from '@app/features/user/commands/UserProfileCommands';
|
import * as UserProfileCommands from '@app/features/user/commands/UserProfileCommands';
|
||||||
import styles from '@app/features/user/components/modals/tabs/MyProfileTab.module.css';
|
import styles from '@app/features/user/components/modals/tabs/MyProfileTab.module.css';
|
||||||
import {AccentColorPicker} from '@app/features/user/components/modals/tabs/my_profile_tab/AccentColorPicker';
|
import {AccentColorPicker} from '@app/features/user/components/modals/tabs/my_profile_tab/AccentColorPicker';
|
||||||
import {AvatarUploader} from '@app/features/user/components/modals/tabs/my_profile_tab/AvatarUploader';
|
import {
|
||||||
|
AvatarUploader,
|
||||||
|
useChangeAvatarAction,
|
||||||
|
} from '@app/features/user/components/modals/tabs/my_profile_tab/AvatarUploader';
|
||||||
import {BannerUploader} from '@app/features/user/components/modals/tabs/my_profile_tab/BannerUploader';
|
import {BannerUploader} from '@app/features/user/components/modals/tabs/my_profile_tab/BannerUploader';
|
||||||
import {BIO_MARKDOWN_PARSER_FLAGS, BioEditor} from '@app/features/user/components/modals/tabs/my_profile_tab/BioEditor';
|
import {BIO_MARKDOWN_PARSER_FLAGS, BioEditor} from '@app/features/user/components/modals/tabs/my_profile_tab/BioEditor';
|
||||||
import {UsernameSection} from '@app/features/user/components/modals/tabs/my_profile_tab/MyProfileTabUsernameSection';
|
import {UsernameSection} from '@app/features/user/components/modals/tabs/my_profile_tab/MyProfileTabUsernameSection';
|
||||||
@@ -615,6 +618,7 @@ const MyProfileTabComponent = observer(function MyProfileTabComponent({
|
|||||||
form.setValue('avatar', null);
|
form.setValue('avatar', null);
|
||||||
transitionAvatarAsset({type: 'asset.cleared'});
|
transitionAvatarAsset({type: 'asset.cleared'});
|
||||||
}, [form, transitionAvatarAsset]);
|
}, [form, transitionAvatarAsset]);
|
||||||
|
const {openChangeAvatar} = useChangeAvatarAction({onAvatarChange: handleAvatarChange});
|
||||||
const handleBannerChange = useCallback(
|
const handleBannerChange = useCallback(
|
||||||
(base64: string) => {
|
(base64: string) => {
|
||||||
form.setValue('banner', base64);
|
form.setValue('banner', base64);
|
||||||
@@ -674,6 +678,7 @@ const MyProfileTabComponent = observer(function MyProfileTabComponent({
|
|||||||
const guilds = Guilds.getGuilds();
|
const guilds = Guilds.getGuilds();
|
||||||
const selectedGuild = selectedGuildId ? guilds.find((g) => g.id === selectedGuildId) : null;
|
const selectedGuild = selectedGuildId ? guilds.find((g) => g.id === selectedGuildId) : null;
|
||||||
const isPerGuildProfileCustomizationDisabled = isPerGuildProfile && !hasPerGuildProfiles;
|
const isPerGuildProfileCustomizationDisabled = isPerGuildProfile && !hasPerGuildProfiles;
|
||||||
|
const isAvatarCustomizationDisabled = isProfileCustomizationLocked || isPerGuildProfileCustomizationDisabled;
|
||||||
const isPronounsDisabled = isProfileCustomizationLocked;
|
const isPronounsDisabled = isProfileCustomizationLocked;
|
||||||
const profileCustomizationDescription = isProfileEmailLocked
|
const profileCustomizationDescription = isProfileEmailLocked
|
||||||
? isPerGuildProfile
|
? isPerGuildProfile
|
||||||
@@ -840,7 +845,7 @@ const MyProfileTabComponent = observer(function MyProfileTabComponent({
|
|||||||
hasAvatar={hasAvatar}
|
hasAvatar={hasAvatar}
|
||||||
onAvatarChange={handleAvatarChange}
|
onAvatarChange={handleAvatarChange}
|
||||||
onAvatarClear={handleAvatarClear}
|
onAvatarClear={handleAvatarClear}
|
||||||
disabled={isProfileCustomizationLocked || isPerGuildProfileCustomizationDisabled}
|
disabled={isAvatarCustomizationDisabled}
|
||||||
disableModeSelection={isProfileCustomizationLocked}
|
disableModeSelection={isProfileCustomizationLocked}
|
||||||
isPerGuildProfile={isPerGuildProfile}
|
isPerGuildProfile={isPerGuildProfile}
|
||||||
errorMessage={form.formState.errors.avatar?.message}
|
errorMessage={form.formState.errors.avatar?.message}
|
||||||
@@ -934,6 +939,9 @@ const MyProfileTabComponent = observer(function MyProfileTabComponent({
|
|||||||
}}
|
}}
|
||||||
ignoreGuildAvatarInPreview={isPerGuildProfile && avatarAsset.mode === 'inherit'}
|
ignoreGuildAvatarInPreview={isPerGuildProfile && avatarAsset.mode === 'inherit'}
|
||||||
ignoreGuildBannerInPreview={isPerGuildProfile && bannerAsset.mode === 'inherit'}
|
ignoreGuildBannerInPreview={isPerGuildProfile && bannerAsset.mode === 'inherit'}
|
||||||
|
onAvatarClick={
|
||||||
|
mobileLayout.enabled && !isAvatarCustomizationDisabled ? openChangeAvatar : undefined
|
||||||
|
}
|
||||||
data-flx="user.my-profile-tab.my-profile-tab-component.profile-preview"
|
data-flx="user.my-profile-tab.my-profile-tab-component.profile-preview"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+52
-35
@@ -116,47 +116,22 @@ interface AvatarUploaderProps {
|
|||||||
onAvatarModeChange?: (mode: AvatarMode) => void;
|
onAvatarModeChange?: (mode: AvatarMode) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AvatarUploader = observer(
|
interface ChangeAvatarActionOptions {
|
||||||
({
|
onAvatarChange: (base64: string) => void;
|
||||||
hasAvatar,
|
requireAnimatedAvatarEntitlement?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useChangeAvatarAction({
|
||||||
onAvatarChange,
|
onAvatarChange,
|
||||||
onAvatarClear,
|
|
||||||
disabled,
|
|
||||||
disableModeSelection,
|
|
||||||
requireAnimatedAvatarEntitlement = true,
|
requireAnimatedAvatarEntitlement = true,
|
||||||
isPerGuildProfile,
|
}: ChangeAvatarActionOptions) {
|
||||||
errorMessage,
|
|
||||||
avatarMode = 'inherit',
|
|
||||||
onAvatarModeChange,
|
|
||||||
}: AvatarUploaderProps) => {
|
|
||||||
const PREMIUM_PRODUCT_NAME = getPremiumProductName();
|
|
||||||
const {i18n} = useLingui();
|
const {i18n} = useLingui();
|
||||||
|
const PREMIUM_PRODUCT_NAME = getPremiumProductName();
|
||||||
const hasAnimatedAvatarEntitlement = isLimitToggleEnabled(
|
const hasAnimatedAvatarEntitlement = isLimitToggleEnabled(
|
||||||
{feature_animated_avatar: LimitResolver.resolve({key: 'feature_animated_avatar', fallback: 0})},
|
{feature_animated_avatar: LimitResolver.resolve({key: 'feature_animated_avatar', fallback: 0})},
|
||||||
'feature_animated_avatar',
|
'feature_animated_avatar',
|
||||||
);
|
);
|
||||||
const canUploadAnimatedAvatar = !requireAnimatedAvatarEntitlement || hasAnimatedAvatarEntitlement;
|
const canUploadAnimatedAvatar = !requireAnimatedAvatarEntitlement || hasAnimatedAvatarEntitlement;
|
||||||
const getAvatarModeOptions = useCallback(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
value: 'inherit' as AvatarMode,
|
|
||||||
name: i18n._(USE_GLOBAL_PROFILE_DESCRIPTOR),
|
|
||||||
desc: i18n._(SHOW_YOUR_GLOBAL_PROFILE_AVATAR_IN_THIS_COMMUNITY_DESCRIPTOR),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'custom' as AvatarMode,
|
|
||||||
name: i18n._(USE_CUSTOM_IMAGE_DESCRIPTOR),
|
|
||||||
desc: i18n._(UPLOAD_A_CUSTOM_AVATAR_FOR_THIS_COMMUNITY_DESCRIPTOR),
|
|
||||||
disabled: !canUploadAnimatedAvatar,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'unset' as AvatarMode,
|
|
||||||
name: i18n._(DON_T_SHOW_DESCRIPTOR),
|
|
||||||
desc: i18n._(SHOW_DEFAULT_AVATAR_IGNORING_YOUR_GLOBAL_PROFILE_DESCRIPTOR),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[canUploadAnimatedAvatar, i18n],
|
|
||||||
);
|
|
||||||
const processAvatarFile = useCallback(
|
const processAvatarFile = useCallback(
|
||||||
async (file: File) => {
|
async (file: File) => {
|
||||||
if (file.size > GlobalLimits.getAvatarMaxSize()) {
|
if (file.size > GlobalLimits.getAvatarMaxSize()) {
|
||||||
@@ -189,8 +164,8 @@ export const AvatarUploader = observer(
|
|||||||
<>
|
<>
|
||||||
<p data-flx="user.my-profile-tab.avatar-uploader.handle-avatar-upload.p">
|
<p data-flx="user.my-profile-tab.avatar-uploader.handle-avatar-upload.p">
|
||||||
<Trans>
|
<Trans>
|
||||||
Animated avatars ({ANIMATED_AVATAR_FORMATS}) are exclusively available to{' '}
|
Animated avatars ({ANIMATED_AVATAR_FORMATS}) are exclusively available to {PREMIUM_PRODUCT_NAME}{' '}
|
||||||
{PREMIUM_PRODUCT_NAME} subscribers.
|
subscribers.
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
@@ -335,6 +310,48 @@ export const AvatarUploader = observer(
|
|||||||
onSelectGif: (gif) => void handleSelectAvatarGif(gif),
|
onSelectGif: (gif) => void handleSelectAvatarGif(gif),
|
||||||
});
|
});
|
||||||
}, [canUploadAnimatedAvatar, handlePickAvatarFile, handleSelectAvatarGif, i18n]);
|
}, [canUploadAnimatedAvatar, handlePickAvatarFile, handleSelectAvatarGif, i18n]);
|
||||||
|
return {canUploadAnimatedAvatar, openChangeAvatar: handleAvatarUpload};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AvatarUploader = observer(
|
||||||
|
({
|
||||||
|
hasAvatar,
|
||||||
|
onAvatarChange,
|
||||||
|
onAvatarClear,
|
||||||
|
disabled,
|
||||||
|
disableModeSelection,
|
||||||
|
requireAnimatedAvatarEntitlement = true,
|
||||||
|
isPerGuildProfile,
|
||||||
|
errorMessage,
|
||||||
|
avatarMode = 'inherit',
|
||||||
|
onAvatarModeChange,
|
||||||
|
}: AvatarUploaderProps) => {
|
||||||
|
const {i18n} = useLingui();
|
||||||
|
const {canUploadAnimatedAvatar, openChangeAvatar: handleAvatarUpload} = useChangeAvatarAction({
|
||||||
|
onAvatarChange,
|
||||||
|
requireAnimatedAvatarEntitlement,
|
||||||
|
});
|
||||||
|
const getAvatarModeOptions = useCallback(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
value: 'inherit' as AvatarMode,
|
||||||
|
name: i18n._(USE_GLOBAL_PROFILE_DESCRIPTOR),
|
||||||
|
desc: i18n._(SHOW_YOUR_GLOBAL_PROFILE_AVATAR_IN_THIS_COMMUNITY_DESCRIPTOR),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'custom' as AvatarMode,
|
||||||
|
name: i18n._(USE_CUSTOM_IMAGE_DESCRIPTOR),
|
||||||
|
desc: i18n._(UPLOAD_A_CUSTOM_AVATAR_FOR_THIS_COMMUNITY_DESCRIPTOR),
|
||||||
|
disabled: !canUploadAnimatedAvatar,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'unset' as AvatarMode,
|
||||||
|
name: i18n._(DON_T_SHOW_DESCRIPTOR),
|
||||||
|
desc: i18n._(SHOW_DEFAULT_AVATAR_IGNORING_YOUR_GLOBAL_PROFILE_DESCRIPTOR),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[canUploadAnimatedAvatar, i18n],
|
||||||
|
);
|
||||||
const handleModeChange = useCallback(
|
const handleModeChange = useCallback(
|
||||||
(mode: AvatarMode) => {
|
(mode: AvatarMode) => {
|
||||||
if (mode === 'custom') {
|
if (mode === 'custom') {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ interface ProfilePreviewProps {
|
|||||||
showMessageButton?: boolean;
|
showMessageButton?: boolean;
|
||||||
showPreviewLabel?: boolean;
|
showPreviewLabel?: boolean;
|
||||||
previewCustomStatus?: CustomStatus | null;
|
previewCustomStatus?: CustomStatus | null;
|
||||||
|
onAvatarClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProfilePreview: React.FC<ProfilePreviewProps> = observer(
|
export const ProfilePreview: React.FC<ProfilePreviewProps> = observer(
|
||||||
@@ -90,6 +91,7 @@ export const ProfilePreview: React.FC<ProfilePreviewProps> = observer(
|
|||||||
showMessageButton = true,
|
showMessageButton = true,
|
||||||
showPreviewLabel = true,
|
showPreviewLabel = true,
|
||||||
previewCustomStatus,
|
previewCustomStatus,
|
||||||
|
onAvatarClick,
|
||||||
}) => {
|
}) => {
|
||||||
const {i18n} = useLingui();
|
const {i18n} = useLingui();
|
||||||
const previewOverrides = useMemo<ProfilePreviewOverrides>(
|
const previewOverrides = useMemo<ProfilePreviewOverrides>(
|
||||||
@@ -245,7 +247,7 @@ export const ProfilePreview: React.FC<ProfilePreviewProps> = observer(
|
|||||||
avatarUrl={finalAvatarUrl}
|
avatarUrl={finalAvatarUrl}
|
||||||
hoverAvatarUrl={finalHoverAvatarUrl}
|
hoverAvatarUrl={finalHoverAvatarUrl}
|
||||||
isClickable={true}
|
isClickable={true}
|
||||||
onAvatarClick={openMockProfile}
|
onAvatarClick={onAvatarClick ?? openMockProfile}
|
||||||
data-flx="user.profile.profile-preview.profile-card-banner"
|
data-flx="user.profile.profile-preview.profile-card-banner"
|
||||||
/>
|
/>
|
||||||
<UserProfileBadges
|
<UserProfileBadges
|
||||||
|
|||||||
Reference in new issue
Block a user