import React, { createRef, useEffect, useState } from 'react'; import { Modal, Text, TouchableOpacity, View } from 'react-native'; import Animated, { Easing } from 'react-native-reanimated'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import WebView from 'react-native-webview'; import { normalize, SIZE, WEIGHT } from '../../common/common'; import { useTracked } from '../../provider'; import { eSubscribeEvent, eUnSubscribeEvent, eSendEvent, } from '../../services/eventManager'; import { eApplyChanges, eShowMergeDialog, refreshNotesPage, } from '../../services/events'; import { getElevation, h, db } from '../../utils/utils'; import { simpleDialogEvent, updateEvent } from '../DialogManager/recievers'; import { TEMPLATE_APPLY_CHANGES } from '../DialogManager/templates'; import { ACTIONS } from '../../provider/actions'; const { Value, timing } = Animated; const firstWebViewHeight = new Value(h * 0.5 - 50); const secondWebViewHeight = new Value(h * 0.5 - 50); const primaryWebView = createRef(); const secondaryWebView = createRef(); let note = null; function openEditorAnimation( heightToAnimate, extendedHeight = null, siblingStatus, ) { let openConfig = { duration: 300, toValue: !siblingStatus ? h - 100 : h * 0.5 - 50, easing: Easing.inOut(Easing.ease), }; let extendConfig = { duration: 300, toValue: h * 0.5 - 50, easing: Easing.inOut(Easing.ease), }; if (extendedHeight) { timing(extendedHeight, extendConfig).start(); } timing(heightToAnimate, openConfig).start(); } function closeEditorAnimation(heightToAnimate, heightToExtend = null) { let closeConfig = { duration: 300, toValue: 0, easing: Easing.inOut(Easing.ease), }; let extendConfig = { duration: 300, toValue: h - 100, easing: Easing.inOut(Easing.ease), }; if (heightToExtend) { timing(heightToExtend, extendConfig).start(); } timing(heightToAnimate, closeConfig).start(); } let primaryDelta = null; let primaryText = ''; let secondaryDelta = null; let secondaryText = ''; const MergeEditor = () => { const [state, dispatch] = useTracked(); const { colors } = state; const [visible, setVisible] = useState(false); const [primary, setPrimary] = useState(true); const [secondary, setSecondary] = useState(true); const [keepContentFrom, setKeepContentFrom] = useState(null); const [copyToSave, setCopyToSave] = useState(null); const [disardedContent, setDiscardedContent] = useState(null); const postMessageToPrimaryWebView = message => primaryWebView.current?.postMessage(JSON.stringify(message)); const postMessageToSecondaryWebView = message => secondaryWebView.current?.postMessage(JSON.stringify(message)); const onPrimaryWebViewLoad = () => { postMessageToPrimaryWebView({ type: 'delta', value: primaryDelta, }); let c = { ...colors }; c.factor = normalize(1); postMessageToPrimaryWebView({ type: 'theme', value: c, }); }; const onSecondaryWebViewLoad = () => { postMessageToSecondaryWebView({ type: 'delta', value: secondaryDelta, }); let c = { ...colors }; c.factor = normalize(1); postMessageToSecondaryWebView({ type: 'theme', value: c, }); }; const _onShouldStartLoadWithRequest = request => { if (request.url.includes('https')) { Linking.openURL(request.url); return false; } else { return true; } }; const onMessageFromPrimaryWebView = evt => { if (evt.nativeEvent.data !== '') { let data = JSON.parse(evt.nativeEvent.data); primaryDelta = data.delta; primaryText = data.text; } }; const onMessageFromSecondaryWebView = evt => { if (evt.nativeEvent.data !== '') { let data = JSON.parse(evt.nativeEvent.data); secondaryDelta = data.delta; secondaryText = data.text; } }; const applyChanges = async () => { if (keepContentFrom === 'primary') { await db.notes.add({ content: { text: primaryText, delta: { data: primaryDelta, resolved: true }, }, id: note.id, conflicted: false, }); } else if (keepContentFrom === 'secondary') { await db.notes.add({ content: { text: secondaryText, delta: { data: primaryDelta, resolved: true }, }, id: note.id, conflicted: false, }); } if (copyToSave === 'primary') { await db.notes.add({ content: { text: primaryText, delta: primaryDelta, }, id: null, }); } else if (copyToSave === 'secondary') { await db.notes.add({ content: { text: secondaryText, delta: secondaryDelta, }, id: null, }); } eSendEvent(refreshNotesPage); updateEvent({ type: ACTIONS.NOTES }); updateEvent({ type: ACTIONS.FAVORITES }); close(); }; const show = async item => { note = item; primaryDelta = await db.notes.note(note.id).delta(); secondaryDelta = await db.notes.note(note.id).delta().conflicted; setVisible(true); postMessageToPrimaryWebView({ type: 'delta', value: primaryDelta, }); postMessageToSecondaryWebView({ type: 'delta', value: secondaryDelta, }); openEditorAnimation(firstWebViewHeight, secondWebViewHeight, true); }; useEffect(() => { eSubscribeEvent(eApplyChanges, applyChanges); eSubscribeEvent(eShowMergeDialog, show); return () => { eUnSubscribeEvent(eApplyChanges, applyChanges); eUnSubscribeEvent(eShowMergeDialog, show); }; }); const onPressKeepFromPrimaryWebView = () => { if (keepContentFrom == 'primary') { setKeepContentFrom(null); openEditorAnimation(firstWebViewHeight, secondWebViewHeight); } else { setKeepContentFrom('primary'); closeEditorAnimation(firstWebViewHeight, secondWebViewHeight); } }; const onPressSaveCopyFromPrimaryWebView = () => { setCopyToSave('primary'); simpleDialogEvent(TEMPLATE_APPLY_CHANGES); }; const onPressKeepFromSecondaryWebView = () => { if (keepContentFrom == 'secondary') { setKeepContentFrom(null); openEditorAnimation(secondWebViewHeight, firstWebViewHeight); } else { setKeepContentFrom('secondary'); closeEditorAnimation(secondWebViewHeight, firstWebViewHeight); } }; const onPressSaveCopyFromSecondaryWebView = () => { setCopyToSave('secondary'); simpleDialogEvent(TEMPLATE_APPLY_CHANGES); }; const onPressDiscardFromPrimaryWebView = () => { setDiscardedContent('primary'); simpleDialogEvent(TEMPLATE_APPLY_CHANGES); }; const onPressDiscardFromSecondaryWebView = () => { setDiscardedContent('secondary'); simpleDialogEvent(TEMPLATE_APPLY_CHANGES); }; const close = () => { setVisible(false); setPrimary(true); setSecondary(true); setCopyToSave(null); setDiscardedContent(null); setKeepContentFrom(null); primaryDelta = null; secondaryDelta = null; primaryText = null; secondaryText = null; note = null; openEditorAnimation(firstWebViewHeight, secondWebViewHeight, true); }; const params = 'platform=' + Platform.OS; const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '') + 'Web.bundle/loader.html'; const injectedJS = `if (!window.location.search) { var link = document.getElementById('progress-bar'); link.href = './site2/plaineditor.html?${params}'; link.click(); }`; return ( { if (keepContentFrom === 'primary') return; if (!primary) { openEditorAnimation( firstWebViewHeight, secondary && keepContentFrom !== 'secondary' ? secondWebViewHeight : null, secondary && keepContentFrom !== 'secondary', ); setPrimary(true); } else { closeEditorAnimation( firstWebViewHeight, secondary && keepContentFrom !== 'secondary' ? secondWebViewHeight : null, ); setPrimary(false); } }} style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }}> Saved on 10/10/20 {'\n'} 12:30pm on Tablet {keepContentFrom === 'secondary' ? ( Save as a copy ) : null} {keepContentFrom === 'secondary' ? ( Discard ) : null} {keepContentFrom === 'secondary' ? null : ( {keepContentFrom === 'primary' ? 'Undo' : 'Keep'} )} { if (keepContentFrom === 'secondary') return; if (!secondary) { openEditorAnimation( secondWebViewHeight, primary && keepContentFrom !== 'primary' ? firstWebViewHeight : null, primary && keepContentFrom !== 'primary', ); setSecondary(true); } else { closeEditorAnimation( secondWebViewHeight, primary && keepContentFrom !== 'primary' ? firstWebViewHeight : null, ); setSecondary(false); } }} style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }}> Saved on 10/10/20 {'\n'} 12:30pm on Tablet {keepContentFrom === 'primary' ? ( Save as a copy ) : null} {keepContentFrom === 'primary' ? ( Discard ) : null} {keepContentFrom === 'primary' ? null : ( {keepContentFrom === 'secondary' ? 'Undo' : 'Keep'} )} ); }; export default MergeEditor;