import React, { useState } from "react"; import { useTextInput, useBlocksContext, useTextBlocksContext, useBlock, updateBlockData, createBlock, DragProvider } from "@react-native-blocks/core"; import { View, TextInput, Text, StyleSheet, TouchableOpacity, Modal, Button, Image, Dimensions, Pressable } from "react-native"; import Ionicons from '@expo/vector-icons/Ionicons'; import EmojiSelector from "react-native-emoji-selector"; import * as ImagePicker from 'expo-image-picker'; const { width } = Dimensions.get("window"); function containsEmoji(str: string) { const emojiRegex = /\p{Emoji_Presentation}|\p{Extended_Pictographic}/u; return emojiRegex.test(str); } interface Props { blockId: string } export function PageBlock({ blockId } : Props) { const { getTextInputProps, getValue, getSelection } = useTextInput(blockId); const { blocks, insertBlock, updateBlock, updateBlockV2, blocksOrder, } = useBlocksContext(); const { inputRefs } = useTextBlocksContext(); const { properties } = useBlock(blockId); // This condition should be renamed to "isFirstBlock" or sth like that. const isRootBlock = blocks["root"].content[0] === blockId; const [showEmojiSelector, setShowEmojiSelector] = useState(false); const [pageIcon, setPageIcon] = useState(blocks[blockId]?.format?.page_icon || null); const [pageCover, setPageCover] = useState(blocks[blockId]?.format?.page_cover || null); const placeholder = "New page"; const pickCover = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: false, quality: 1, }); if (!result.canceled) { setPageCover(result.assets[0].uri); const updatedBlock = updateBlockData(blocks[blockId], { format: { page_cover: result.assets[0].uri /* page_cover_position */ } }); updateBlock(updatedBlock); } } const pickIcon = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, aspect: [4, 3] }); if (!result.canceled) { setPageIcon(result.assets[0].uri); /* setAspectRatio(result.assets[0].width / result.assets[0].height); */ setShowEmojiSelector(false); const updatedBlock = updateBlockData(blocks[blockId], { format: { page_icon: result.assets[0].uri, ...blocks[blockId]?.format } }); updateBlock(updatedBlock); } }; const handleEmojiSelect = (emoji: string) => { setPageIcon(emoji); setShowEmojiSelector(false); const updatedBlock = updateBlockData(blocks[blockId], { format: { page_icon: emoji, ...blocks[blockId]?.format } }); updateBlock(updatedBlock); }; const handleRemoveIcon = () => { setPageIcon(null); setShowEmojiSelector(false); const block = blocks[blockId]; delete block.format.page_icon; updateBlock(block); }; const handleRemoveCover = () => { setPageCover(null); const block = blocks[blockId]; delete block.format.page_cover; updateBlock(block); }; const handleSubmitEditing = () => { const value = getValue(); const selection = getSelection(); if (selection.start === value.length && selection.end === value.length) { const newBlock = createBlock({ type: "text", properties: { title: "" }, parent: blockId, content: [] }); insertBlock(newBlock, { nextBlockId: blocks[blockId].content[0] }); requestAnimationFrame(() => { inputRefs.current[newBlock.id]?.current.focus(); }) return; } if (selection.start === 0 && selection.end === 0) { const newBlock = createBlock({ type: "text", properties: { title: value }, parent: blockId, content: [] }); updateBlockV2(blockId, { properties: { title: "" } }); insertBlock(newBlock, { nextBlockId: blocks[blockId].content[0] }); requestAnimationFrame(() => { inputRefs.current[blockId].current.setText(""); inputRefs.current[newBlock.id]?.current.setSelection({ start: 0, end: 0 }); inputRefs.current[newBlock.id]?.current.focus(); }) return; } const textBeforeSelection = value.substring(0, selection.start); const textAfterSelection = value.substring(selection.end); const newBlock = createBlock({ type: "text", properties: { title: textAfterSelection }, parent: blockId, content: [] }); updateBlockV2(blockId, { properties: { title: textBeforeSelection } }); insertBlock(newBlock, { nextBlockId: blocks[blockId].content[0] }); requestAnimationFrame(() => { inputRefs.current[blockId]?.current.setText(textBeforeSelection); inputRefs.current[newBlock.id]?.current.setSelection({ start: 0, end: 0 }); inputRefs.current[newBlock.id]?.current.focus(); }); } const handleOnKeyPress = (event: { nativeEvent: { key: string; }; }) => { const value = getValue(); const selection = getSelection(); if (event.nativeEvent.key === "Backspace" && selection.start === 0 && selection.end === 0) { return; } } return ( <> { isRootBlock && pageCover ? ( setShowEmojiSelector(true)}> Add icon Remove cover ) : null} {isRootBlock ? ( <> {pageCover === null ? ( {pageIcon === null && ( setShowEmojiSelector(true)}> Add icon )} {pageCover === null && ( Add cover )} ) : null} {pageIcon !== null ? ( setShowEmojiSelector(true)} style={{ borderRadius: 8, overflow: "hidden", width: 64, height: 64, justifyContent: "center", alignItems: "center" }} > {containsEmoji(pageIcon) === false ? ( ) : ( {pageIcon} )} ) : null} ) : ( setShowEmojiSelector(true)} style={styles.iconContainer} > {pageIcon === null ? ( ) : ( <> {containsEmoji(pageIcon) === false ? ( ) : ( {pageIcon} )} )} {properties.title.length === 0 ? placeholder : properties.title} )} setShowEmojiSelector(false)} presentationStyle="pageSheet" animationType="slide" >