// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import Clipboard from '@react-native-clipboard/clipboard'; import React, {useCallback, useMemo} from 'react'; import {useIntl} from 'react-intl'; import {Alert, Text, View} from 'react-native'; import Share from 'react-native-share'; import {deleteChannelBookmark} from '@actions/remote/channel_bookmark'; import {fetchPublicLink} from '@actions/remote/file'; import CompassIcon from '@components/compass_icon'; import OptionItem from '@components/option_item'; import {Screens} from '@constants'; import {useServerUrl} from '@context/server'; import {useTheme} from '@context/theme'; import {useIsTablet} from '@hooks/device'; import DownloadWithAction from '@screens/gallery/footer/download_with_action'; import {dismissBottomSheet, showModal, showOverlay} from '@screens/navigation'; import {getFullErrorMessage} from '@utils/errors'; import {isImage, isVideo} from '@utils/file'; import {showSnackBar} from '@utils/snack_bar'; import {makeStyleSheetFromTheme} from '@utils/theme'; import {typography} from '@utils/typography'; import type ChannelBookmarkModel from '@typings/database/models/servers/channel_bookmark'; import type FileModel from '@typings/database/models/servers/file'; import type {GalleryAction, GalleryFileType, GalleryItemType} from '@typings/screens/gallery'; type Props = { bookmark: ChannelBookmarkModel; canCopyPublicLink: boolean; canDeleteBookmarks: boolean; canDownloadFiles: boolean; canEditBookmarks: boolean; enableSecureFilePreview: boolean; file?: FileModel; setAction: React.Dispatch>; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ flex: {flex: 1}, header: { marginBottom: 12, }, headerText: { color: theme.centerChannelColor, ...typography('Heading', 600, 'SemiBold'), }, })); const ChannelBookmarkOptions = ({ bookmark, canCopyPublicLink, canDeleteBookmarks, canDownloadFiles, canEditBookmarks, enableSecureFilePreview, file, setAction, }: Props) => { const serverUrl = useServerUrl(); const theme = useTheme(); const isTablet = useIsTablet(); const intl = useIntl(); const styles = getStyleSheet(theme); const canShare = canDownloadFiles || bookmark.type === 'link'; const isVideoFile = useMemo(() => isVideo(file), [file]); const isImageFile = useMemo(() => isImage(file), [file]); const galleryItem = useMemo(() => { if (file) { const fileInfo = file.toFileInfo(bookmark.ownerId); let type: GalleryFileType = 'file'; if (isImageFile) { type = 'image'; } else if (isVideoFile) { type = 'video'; } const item: GalleryItemType = { ...fileInfo, id: fileInfo.id!, type, lastPictureUpdate: 0, uri: '', cacheKey: fileInfo.id!, }; return item; } return null; }, [bookmark.ownerId, file, isImageFile, isVideoFile]); const handleDelete = useCallback(async () => { const {error} = await deleteChannelBookmark(serverUrl, bookmark.channelId, bookmark.id); if (error) { Alert.alert( intl.formatMessage({id: 'channel_bookmark.delete.failed_title', defaultMessage: 'Error deleting bookmark'}), intl.formatMessage({id: 'channel_bookmark.delete.failed_detail', defaultMessage: 'Details: {error}'}, { error: getFullErrorMessage(error), }), ); return; } await dismissBottomSheet(); }, [bookmark, intl, serverUrl]); const onCopy = useCallback(async () => { await dismissBottomSheet(); if (bookmark.type === 'link' && bookmark.linkUrl) { Clipboard.setString(bookmark.linkUrl); showSnackBar({barType: 'LINK_COPIED'}); return; } try { const publicLink = await fetchPublicLink(serverUrl, bookmark.fileId!); if ('link' in publicLink) { Clipboard.setString(publicLink.link); showSnackBar({barType: 'LINK_COPIED'}); } else { showSnackBar({barType: 'LINK_COPY_FAILED'}); } } catch { showSnackBar({barType: 'LINK_COPY_FAILED'}); } }, [bookmark, serverUrl]); const onDelete = useCallback(async () => { Alert.alert( intl.formatMessage({id: 'channel_bookmark.delete.confirm_title', defaultMessage: 'Delete bookmark'}), intl.formatMessage({id: 'channel_bookmark.delete.confirm', defaultMessage: 'You sure want to delete the bookmark {displayName}?'}, { displayName: bookmark.displayName, }), [{ text: intl.formatMessage({id: 'channel_bookmark.delete.yes', defaultMessage: 'Yes'}), style: 'destructive', isPreferred: true, onPress: handleDelete, }, { text: intl.formatMessage({id: 'channel_bookmark.add.file_cancel', defaultMessage: 'Cancel'}), style: 'cancel', }], ); }, [bookmark.displayName, handleDelete, intl]); const onEdit = useCallback(async () => { await dismissBottomSheet(); const title = intl.formatMessage({id: 'screens.channel_bookmark_edit', defaultMessage: 'Edit bookmark'}); const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor); const closeButtonId = 'close-channel_bookmark_edit'; const options = { topBar: { leftButtons: [{ id: closeButtonId, icon: closeButton, testID: 'close.channel_bookmark_edit.button', }], }, }; showModal(Screens.CHANNEL_BOOKMARK, title, { bookmark: bookmark.toApi(), canDeleteBookmarks, channelId: bookmark.channelId, closeButtonId, file: file?.toFileInfo(bookmark.ownerId), ownerId: bookmark.ownerId, type: bookmark.type, }, options); }, [bookmark, canDeleteBookmarks, file, intl, theme]); const onShare = useCallback(async () => { await dismissBottomSheet(); if (bookmark.type === 'file') { if (file) { setAction('sharing'); showOverlay(Screens.GENERIC_OVERLAY, { children: ( ), }, {}, bookmark.id); } return; } if (bookmark.type === 'link') { const title = bookmark.displayName; const url = bookmark.linkUrl!; Share.open({ title, message: title, url, showAppsToView: true, }).catch(() => { // do nothing }); } }, [bookmark.displayName, bookmark.id, bookmark.linkUrl, bookmark.type, enableSecureFilePreview, file, galleryItem, setAction]); return ( <> {!isTablet && ( {bookmark.displayName} )} {canEditBookmarks && } {!enableSecureFilePreview && canCopyPublicLink && } {!enableSecureFilePreview && canShare && } {canDeleteBookmarks && } ); }; export default ChannelBookmarkOptions;