feat(app,api): let group DM owners allow mature content (#3350)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-09 14:12:13 +02:00
1 parent 4749eb7f86
commit 9a20821332
126 files changed
+2127 -1277

No files matched your search

@@ -6,9 +6,11 @@ import {
STATIC_IMAGE_FORMATS,
} from '@app/features/app/config/I18nDisplayConstants';
import {useFormSubmit} from '@app/features/app/hooks/useFormSubmit';
import Authentication from '@app/features/auth/state/Authentication';
import * as ChannelCommands from '@app/features/channel/commands/ChannelCommands';
import {showChannelErrorModal} from '@app/features/channel/components/alerts/ChannelErrorModalUtils';
import styles from '@app/features/channel/components/modals/EditGroupBottomSheet.module.css';
import {GroupMatureContentSwitch} from '@app/features/channel/components/modals/GroupMatureContentSwitch';
import Channels from '@app/features/channel/state/Channels';
import {AssetCropModal, AssetType} from '@app/features/expressions/components/modals/AssetCropModal';
import {openAssetSourceModal} from '@app/features/expressions/components/modals/AssetSourceModal';
@@ -42,7 +44,7 @@ import {ArrowLeftIcon, PlusIcon} from '@phosphor-icons/react';
import {observer} from 'mobx-react-lite';
import type React from 'react';
import {useCallback, useMemo, useState} from 'react';
import {useForm} from 'react-hook-form';
import {Controller, useForm} from 'react-hook-form';
const ICON_FILE_IS_TOO_LARGE_PLEASE_CHOOSE_A_DESCRIPTOR = msg({
message: 'Icon file is too large. Choose a file smaller than {imageMaxSizeLabel}.',
@@ -94,6 +96,7 @@ const CHANGE_ICON_DESCRIPTOR = msg({
interface FormInputs {
icon?: string | null;
name: string;
nsfw: boolean;
}
interface EditGroupBottomSheetProps {
@@ -105,12 +108,13 @@ interface EditGroupBottomSheetProps {
export const EditGroupBottomSheet: React.FC<EditGroupBottomSheetProps> = observer(({isOpen, onClose, channelId}) => {
const {i18n} = useLingui();
const channel = Channels.getChannel(channelId);
const isOwner = channel?.ownerId === Authentication.currentUserId;
const [hasClearedIcon, setHasClearedIcon] = useState(false);
const [previewIconUrl, setPreviewIconUrl] = useState<string | null>(null);
const form = useForm<FormInputs>({
defaultValues: useMemo(() => ({name: channel?.name || ''}), [channel]),
defaultValues: useMemo(() => ({name: channel?.name || '', nsfw: channel?.nsfw ?? false}), [channel]),
});
const remoteValues: FormInputs | null = channel ? {name: channel.name || ''} : null;
const remoteValues: FormInputs | null = channel ? {name: channel.name || '', nsfw: channel.nsfw} : null;
const {commitRemoteValues} = useRemoteFormReset<FormInputs>({
form,
identityKey: channelId,
@@ -220,18 +224,21 @@ export const EditGroupBottomSheet: React.FC<EditGroupBottomSheetProps> = observe
}, [form]);
const onSubmit = useCallback(
async (data: FormInputs) => {
const updateData: {icon?: string | null; name: string} = {name: data.name};
const updateData: {icon?: string | null; name: string; nsfw?: boolean} = {name: data.name};
if (isOwner && data.nsfw !== channel?.nsfw) {
updateData.nsfw = data.nsfw;
}
assignTransientUploadFieldMutation(updateData, 'icon', {
value: data.icon,
previewUrl: previewIconUrl,
hasCleared: hasClearedIcon,
});
const newChannel = await ChannelCommands.update(channelId, updateData);
commitRemoteValues({name: newChannel.name || data.name});
commitRemoteValues({name: newChannel.name || data.name, nsfw: newChannel.nsfw ?? data.nsfw});
ToastCommands.createToast({type: 'success', children: <Trans>Group updated</Trans>});
onClose();
},
[channelId, commitRemoteValues, onClose, previewIconUrl, hasClearedIcon],
[channel, channelId, commitRemoteValues, isOwner, onClose, previewIconUrl, hasClearedIcon],
);
const {handleSubmit, isSubmitting} = useFormSubmit({
form,
@@ -356,6 +363,19 @@ export const EditGroupBottomSheet: React.FC<EditGroupBottomSheetProps> = observe
maxLength={100}
error={form.formState.errors.name?.message}
/>
{isOwner && (
<Controller
name="nsfw"
control={form.control}
render={({field}) => (
<GroupMatureContentSwitch
value={field.value}
onChange={field.onChange}
data-flx="channel.edit-group-bottom-sheet.group-mature-content-switch.change"
/>
)}
/>
)}
<div className={styles.footer} data-flx="channel.edit-group-bottom-sheet.footer">
<Button
type="submit"