import { useState } from 'react';
import { isCancelledError } from '#/lib/errors';
import {
type ComposerImage,
compressProfileImage,
createComposerImage,
type ImageMeta,
} from '#/lib/media/composer-image';
import { openImagePicker } from '#/lib/media/picker';
import * as Dialog from '#/components/Dialog';
import * as styles from '#/components/EditableBanner.css';
import { EditImageDialog } from '#/components/EditImageDialog/EditImageDialog';
import * as Menu from '#/components/Menu';
import CameraFilledIcon from '#/icons/central/Camera1_round_filled_radius1_stroke2.svg';
import LibraryIcon from '#/icons/central/Streaming_round_outlined_radius1_stroke2.svg';
import TrashIcon from '#/icons/central/TrashCan_round_outlined_radius1_stroke2.svg';
import { m } from '#/paraglide/messages';
/** Web-native banner editor: a menu-triggering banner that crops uploads via {@link EditImageDialog}. */
export function EditableBanner({
banner,
onSelectNewBanner,
}: {
banner?: string | null;
onSelectNewBanner: (img: ImageMeta | null) => void;
}) {
const [rawImage, setRawImage] = useState<ComposerImage | undefined>();
const editImageDialogHandle = Dialog.useDialogHandle();
const onOpenLibrary = async () => {
const file = await openImagePicker();
if (!file) {
return;
}
try {
setRawImage(await createComposerImage(file));
editImageDialogHandle.open(null);
} catch (e) {
// a user-cancelled selection is not a failure worth reporting
if (!isCancelledError(e)) {
console.error('Failed to crop banner', e);
}
}
};
const onChangeEditImage = async (image: ComposerImage) => {
onSelectNewBanner(await compressProfileImage(image, 3000, 1000));
};
return (
<>
<Menu.Root>
<Menu.Trigger aria-label={m['components.editableBanner.edit']()} className={styles.trigger}>
{banner && <img className={styles.image} src={banner} alt="" />}
<span className={styles.editBadge}>
<CameraFilledIcon className={styles.cameraFilledIcon} />
</span>
</Menu.Trigger>
<Menu.Popup label={m['components.editableBanner.edit']()} align="center">
<Menu.Item onClick={() => void onOpenLibrary()}>
<Menu.ItemText>{m['common.action.uploadFromFiles']()}</Menu.ItemText>
<Menu.ItemIcon icon={LibraryIcon} />
</Menu.Item>
{!!banner && (
<>
<Menu.Separator />
<Menu.Item destructive onClick={() => onSelectNewBanner(null)}>
<Menu.ItemText>{m['components.editableBanner.remove']()}</Menu.ItemText>
<Menu.ItemIcon icon={TrashIcon} />
</Menu.Item>
</>
)}
</Menu.Popup>
</Menu.Root>
<EditImageDialog
handle={editImageDialogHandle}
image={rawImage}
onChange={(image) => void onChangeEditImage(image)}
aspectRatio={3}
/>
</>
);
}