feat: fully implement new note widget on android

This commit is contained in:
ammarahm-ed
2021-10-09 14:29:40 +05:00
parent 8a11961a6d
commit ac48c35710
6 changed files with 320 additions and 376 deletions

View File

@@ -6,6 +6,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Note Diff Preview</title> <title>Note Diff Preview</title>
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css">
<link rel="stylesheet" href="./fonts.css">
<link id="dark_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook-dark/content.min.css"> <link id="dark_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook-dark/content.min.css">
<link id="light_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook/content.min.css"> <link id="light_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook/content.min.css">
<style> <style>
@@ -80,17 +81,41 @@
padding: 12px !important; padding: 12px !important;
overflow-x: hidden; overflow-x: hidden;
overflow-y: scroll; overflow-y: scroll;
min-height: 150px;
font-family: "Open Sans";
}
[contenteditable] {
outline: 0px solid transparent;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
pointer-events: none;
display: block;
color: gray;
/* For Firefox */
} }
</style> </style>
</head> </head>
<body> <body>
<div class="htmldiff_div"> <div placeholder="Write something..." contenteditable="true" class="htmldiff_div">
</div> </div>
<script src="./listeners.js"></script> <script src="./listeners.js"></script>
<script src="./constants.js"></script> <script src="./constants.js"></script>
<script> <script>
function reactNativeEventHandler(type, value) {
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage(
JSON.stringify({
type: type,
value: value
})
);
}
}
attachMessageListener() attachMessageListener()
</script> </script>
</body> </body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -6,6 +6,7 @@
android:padding="@dimen/widget_margin" android:padding="@dimen/widget_margin"
android:theme="@style/ThemeOverlay.Notesnook.AppWidgetContainer"> android:theme="@style/ThemeOverlay.Notesnook.AppWidgetContainer">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/widget_button" android:id="@+id/widget_button"
@@ -14,7 +15,7 @@
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:background="@drawable/layout_bg" android:background="@drawable/layout_bg"
android:paddingHorizontal="10dp" android:paddingHorizontal="10dp"
android:elevation="5dp"
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout

View File

@@ -2,9 +2,9 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/note_widget" android:initialKeyguardLayout="@layout/note_widget"
android:initialLayout="@layout/note_widget" android:initialLayout="@layout/note_widget"
android:minWidth="110dp" android:minWidth="300dp"
android:minHeight="40dp" android:minHeight="50dp"
android:previewImage="@drawable/example_appwidget_preview" android:previewImage="@drawable/widget_preview"
android:resizeMode="horizontal" android:resizeMode="horizontal"
android:updatePeriodMillis="86400000" android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"></appwidget-provider> android:widgetCategory="home_screen"></appwidget-provider>

View File

@@ -6,6 +6,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Note Diff Preview</title> <title>Note Diff Preview</title>
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css">
<link rel="stylesheet" href="./fonts.css">
<link id="dark_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook-dark/content.min.css"> <link id="dark_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook-dark/content.min.css">
<link id="light_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook/content.min.css"> <link id="light_sheet" disabled rel="stylesheet" href="./dist/skins/notesnook/content.min.css">
<style> <style>
@@ -80,17 +81,41 @@
padding: 12px !important; padding: 12px !important;
overflow-x: hidden; overflow-x: hidden;
overflow-y: scroll; overflow-y: scroll;
min-height: 150px;
font-family: "Open Sans";
}
[contenteditable] {
outline: 0px solid transparent;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
pointer-events: none;
display: block;
color: gray;
/* For Firefox */
} }
</style> </style>
</head> </head>
<body> <body>
<div class="htmldiff_div"> <div placeholder="Write something..." contenteditable="true" class="htmldiff_div">
</div> </div>
<script src="./listeners.js"></script> <script src="./listeners.js"></script>
<script src="./constants.js"></script> <script src="./constants.js"></script>
<script> <script>
function reactNativeEventHandler(type, value) {
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage(
JSON.stringify({
type: type,
value: value
})
);
}
}
attachMessageListener() attachMessageListener()
</script> </script>
</body> </body>

View File

@@ -1,6 +1,7 @@
import Clipboard from '@react-native-clipboard/clipboard';
import absolutify from 'absolutify'; import absolutify from 'absolutify';
import {getLinkPreview} from 'link-preview-js'; import { getLinkPreview } from 'link-preview-js';
import React, {useEffect, useRef, useState} from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { import {
ActivityIndicator, ActivityIndicator,
Appearance, Appearance,
@@ -9,24 +10,25 @@ import {
Platform, Platform,
SafeAreaView, SafeAreaView,
Text, Text,
TextInput,
TouchableOpacity, TouchableOpacity,
useWindowDimensions, useWindowDimensions,
View View
} from 'react-native'; } from 'react-native';
import Animated, {Easing, timing, useValue} from 'react-native-reanimated'; import Animated, { Easing, timing, useValue } from 'react-native-reanimated';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import WebView from 'react-native-webview'; import WebView from 'react-native-webview';
import ShareExtension from 'rn-extensions-share'; import ShareExtension from 'rn-extensions-share';
import sanitize from 'sanitize-html';
import validator from 'validator'; import validator from 'validator';
import {getElevation, showTooltip, TOOLTIP_POSITIONS} from '../src/utils'; import {
import {COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT} from '../src/utils/Colors'; eSendEvent,
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; eSubscribeEvent,
import Clipboard from '@react-native-clipboard/clipboard'; eUnSubscribeEvent
import {db} from '../src/utils/database'; } from '../src/services/EventManager';
import {SIZE} from '../src/utils/SizeUtils'; import { getElevation } from '../src/utils';
import { COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT } from '../src/utils/Colors';
import { db } from '../src/utils/database';
import Storage from '../src/utils/storage'; import Storage from '../src/utils/storage';
import {sleep} from '../src/utils/TimeUtils'; import { sleep } from '../src/utils/TimeUtils';
const AnimatedKAV = Animated.createAnimatedComponent(KeyboardAvoidingView); const AnimatedKAV = Animated.createAnimatedComponent(KeyboardAvoidingView);
const AnimatedSAV = Animated.createAnimatedComponent(SafeAreaView); const AnimatedSAV = Animated.createAnimatedComponent(SafeAreaView);
@@ -34,19 +36,10 @@ async function sanitizeHtml(site) {
try { try {
let html = await fetch(site); let html = await fetch(site);
html = await html.text(); html = await html.text();
let siteHtml = sanitize(html, { let siteHtml = html.replace(
allowedTags: sanitize.defaults.allowedTags.concat([ /(?:<(script|button|input|textarea|style|link)(?:\s[^>]*)?>)\s*((?:(?!<\1)[\s\S])*)\s*(?:<\/\1>)/g,
'img', ''
'style', );
'head',
'link'
]),
allowedClasses: true,
allowVulnerableTags: true,
allowedAttributes: false,
allowProtocolRelative: true,
allowedSchemes: false
});
return absolutify(siteHtml, site); return absolutify(siteHtml, site);
} catch (e) { } catch (e) {
return ''; return '';
@@ -62,6 +55,30 @@ function makeHtmlFromPlainText(text) {
return `<p style="overflow-wrap:anywhere;white-space:pre-wrap" >${text}</p>`; return `<p style="overflow-wrap:anywhere;white-space:pre-wrap" >${text}</p>`;
} }
function getBaseUrl(site) {
var url = site.split('/').slice(0, 3).join('/');
return url;
}
async function absolutifyImgs(html, site) {
let parser = global.HTMLParser;
global.HTMLParser.body.innerHTML = html;
let images = parser.querySelectorAll('img');
for (var i = 0; i < images.length; i++) {
let img = images[i];
let url = getBaseUrl(site);
if (!img.src.startsWith('http')) {
if (img.src.startsWith('//')) {
img.src = img.src.replace('//', 'https://');
} else {
img.src = url + img.src;
}
}
}
return parser.body.innerHTML;
}
let defaultNote = { let defaultNote = {
title: null, title: null,
id: null, id: null,
@@ -71,7 +88,6 @@ let defaultNote = {
} }
}; };
let editorContentValue = null;
const modes = { const modes = {
1: { 1: {
@@ -101,13 +117,10 @@ const NotesnookShare = () => {
const [loadingIntent, setLoadingIntent] = useState(true); const [loadingIntent, setLoadingIntent] = useState(true);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [floating, setFloating] = useState(false); const [floating, setFloating] = useState(false);
const [quickNote, setQuickNote] = useState(false);
const [rawData, setRawData] = useState({ const [rawData, setRawData] = useState({
type: null, type: null,
value: null value: null
}); });
const textInputRef = useRef();
const titleInputRef = useRef();
const {width, height} = useWindowDimensions(); const {width, height} = useWindowDimensions();
const webviewRef = useRef(); const webviewRef = useRef();
const opacity = useValue(0); const opacity = useValue(0);
@@ -117,7 +130,6 @@ const NotesnookShare = () => {
}; };
const prevAnimation = useRef(null); const prevAnimation = useRef(null);
const [mode, setMode] = useState(1); const [mode, setMode] = useState(1);
const [keyboard,setKeyboard] = useState(false);
const animate = (opacityV, translateV) => { const animate = (opacityV, translateV) => {
prevAnimation.current = translateV; prevAnimation.current = translateV;
@@ -134,86 +146,79 @@ const NotesnookShare = () => {
}).start(); }).start();
}; };
const onKeyboardDidShow = (event) => { const onKeyboardDidShow = event => {
let kHeight = event.endCoordinates.height; let kHeight = event.endCoordinates.height;
console.log('called') //translate.setValue(-150);
translate.setValue(-kHeight/1.8); };
}
const onKeyboardDidHide = () => { const onKeyboardDidHide = () => {
translate.setValue(0); translate.setValue(0);
} };
useEffect(() => { useEffect(() => {
let keyboardWillChangeFrame = Keyboard.addListener('keyboardWillChangeFrame', onKeyboardWillChangeFrame); let keyboardWillChangeFrame = Keyboard.addListener(
let keyboardDidShow = Keyboard.addListener("keyboardDidShow", onKeyboardDidShow); 'keyboardWillChangeFrame',
let keyboardDidHide = Keyboard.addListener("keyboardDidHide", onKeyboardDidHide); onKeyboardWillChangeFrame
);
let keyboardDidShow = Keyboard.addListener(
'keyboardDidShow',
onKeyboardDidShow
);
let keyboardDidHide = Keyboard.addListener(
'keyboardDidHide',
onKeyboardDidHide
);
return () => { return () => {
keyboardWillChangeFrame?.remove(); keyboardWillChangeFrame?.remove();
keyboardDidShow?.remove(); keyboardDidShow?.remove();
keyboardDidHide?.remove(); keyboardDidHide?.remove();
}; };
},[]); }, []);
const onKeyboardWillChangeFrame = event => { const onKeyboardWillChangeFrame = event => {
console.log('keyboad change frame',event)
setFloating(event.endCoordinates.width !== width); setFloating(event.endCoordinates.width !== width);
}; };
const showLinkPreview = async link => { const showLinkPreview = async (note, link) => {
let _note = {...defaultNote}; let _note = note;
_note.title = 'Web link share'; _note.content.data = makeHtmlFromUrl(link);
_note.content.data = !note.content.data
? makeHtmlFromUrl(link)
: note.content.data + '\n' + makeHtmlFromUrl(link);
try { try {
let preview = await getLinkPreview(link); let preview = await getLinkPreview(link);
_note.title = preview.siteName || preview.title; _note.title = preview.siteName || preview.title;
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
setNote(_note); return note;
}; };
const loadData = async () => { const loadData = async () => {
try { try {
setNote(() => {
defaultNote.content.data = null;
return defaultNote;
});
const data = await ShareExtension.data(); const data = await ShareExtension.data();
console.log(data);
if (!data || data.length === 0) { if (!data || data.length === 0) {
setRawData({ setRawData({
value: '' value: ''
}); });
setNote({...defaultNote});
setLoadingIntent(false); setLoadingIntent(false);
setQuickNote(true);
return; return;
} }
let note = defaultNote;
for (item of data) { for (item of data) {
if (item.type === 'text') { if (item.type === 'text') {
setRawData(item); setRawData(item);
if (validator.isURL(item.value)) { if (validator.isURL(item.value)) {
await showLinkPreview(item.value); note = await showLinkPreview(note, item.value);
} else { } else {
setNote(note => { note.content.data = makeHtmlFromPlainText(item.value);
note.title = 'Note Share';
note.content.data = note.content.data
? note.content.data + '\n' + makeHtmlFromPlainText(item.value)
: makeHtmlFromPlainText(item.value);
return note;
});
} }
} }
} }
setNote({...note});
} catch (e) {} } catch (e) {}
setLoadingIntent(false); setLoadingIntent(false);
}; };
useEffect(() => { useEffect(() => {
setNote(defaultNote);
loadData(); loadData();
sleep(50).then(() => { sleep(50).then(() => {
animate(1, 0); animate(1, 0);
@@ -244,15 +249,20 @@ const NotesnookShare = () => {
} }
const onPress = async () => { const onPress = async () => {
titleInputRef.current?.blur(); content = await getContent();
textInputRef.current?.blur(); if (!content || content === '') {
return;
}
setLoading(true); setLoading(true);
let add = async () => { let add = async () => {
let _note = {...note}; let _note = {
_note.content.data = ...note,
_note.content.data + makeHtmlFromPlainText(editorContentValue); content: {
await db.notes.add(note); data: content,
type: 'tiny'
}
};
await db.notes.add(_note);
}; };
if (db && db.notes) { if (db && db.notes) {
await add(); await add();
@@ -276,6 +286,35 @@ const NotesnookShare = () => {
} }
}; };
const getContent = () => {
return new Promise(resolve => {
let oncontent = value => {
eUnSubscribeEvent('share_content_event', oncontent);
resolve(value);
};
eSubscribeEvent('share_content_event', oncontent);
webviewRef.current?.injectJavaScript(`(function() {
let html = document.querySelector(".htmldiff_div").innerHTML;
if (!html) {
html = '';
}
reactNativeEventHandler('tiny', html);
})();`);
});
};
const onMessage = event => {
if (!event) return;
let data = JSON.parse(event.nativeEvent.data);
if (data.type === 'tiny') {
eSendEvent('share_content_event', data.value);
}
};
useEffect(() => {
onLoad();
}, [note]);
return ( return (
<AnimatedSAV <AnimatedSAV
style={{ style={{
@@ -307,7 +346,6 @@ const NotesnookShare = () => {
enabled={!floating && Platform.OS === 'ios'} enabled={!floating && Platform.OS === 'ios'}
onLayout={event => { onLayout={event => {
if (prevAnimation.current === 0) return; if (prevAnimation.current === 0) return;
console.log('setting value here');
translate.setValue(event.nativeEvent.layout.height + 30); translate.setValue(event.nativeEvent.layout.height + 30);
}} }}
style={{ style={{
@@ -321,325 +359,180 @@ const NotesnookShare = () => {
] ]
}} }}
behavior="padding"> behavior="padding">
{quickNote ? null : ( <View
style={{
maxHeight: '100%',
paddingHorizontal: 12
}}>
<View <View
style={{ style={{
width: 50, width: '100%'
height: 6,
borderRadius: 100,
backgroundColor: colors.nav,
alignSelf: 'center',
position: 'absolute',
marginTop: 15
}}
/>
)}
{loadingIntent ? (
<View
style={{
height: 150,
width: '100%',
justifyContent: 'center',
alignItems: 'center'
}}> }}>
<ActivityIndicator color={colors.accent} /> <Button
color={colors.accent}
<Text onPress={onPress}
loading={loading || loadingIntent}
icon="check"
iconSize={25}
type="action"
loading={loading}
style={{ style={{
color: colors.pri, position: 'absolute',
fontSize: SIZE.md, zIndex: 999,
marginTop: 5 ...getElevation(10),
}}> right: 24,
Parsing Data... bottom: -35
</Text> }}
</View> />
) : (
<>
<View <View
style={{ style={{
maxHeight: '100%' marginTop: 10,
minHeight: 100,
borderRadius: 10,
...getElevation(5),
backgroundColor: colors.bg
}}> }}>
{quickNote ? null : (
<View
style={{
borderBottomWidth: 1,
borderBottomColor: colors.nav,
paddingHorizontal: 12
}}>
<TextInput
ref={titleInputRef}
style={{
fontSize: 25,
fontFamily:
Platform.OS === 'android' ? 'Roboto-Medium' : null,
fontWeight: Platform.OS === 'ios' ? '600' : null,
color: colors.pri,
flexGrow: 1,
maxWidth: '100%'
}}
placeholderTextColor={colors.icon}
defaultValue={note?.title}
onChangeText={v =>
setNote(_note => {
_note.title = v;
return _note;
})
}
onSubmitEditing={() => {
textInputRef.current?.focus();
}}
blurOnSubmit={false}
placeholder="Note title"
/>
</View>
)}
{quickNote ? null : (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
marginVertical: 10,
borderBottomWidth: 1,
borderBottomColor: colors.nav
}}>
{[
{
title: 'Plain text',
onPress: () => {
let html = validator.isURL(rawData.value)
? makeHtmlFromUrl(rawData.value)
: makeHtmlFromPlainText(rawData.value);
setNote(note => {
note.content.data = html;
return note;
});
onLoad();
}
},
...[
rawData?.value && validator.isURL(rawData.value)
? {
title: 'Clip webpage',
onPress: async () => {
let html = await sanitizeHtml(rawData.value);
setNote(note => {
note.content.data = html;
return note;
});
onLoad();
}
}
: null
]
].map(
(item, index) =>
item && (
<Button
title={item.title}
color={colors.nav}
textStyle={{
color: colors.icon,
fontWeight: 'normal',
fontSize: 14,
fontFamily: null
}}
onPress={item.onPress}
style={{
borderWidth: 0.5,
borderRadius: 100,
borderColor: colors.icon,
height: 30,
marginRight: 10,
marginLeft: index === 0 ? 12 : 0,
paddingHorizontal: 12
}}
/>
)
)}
</View>
)}
{quickNote ? null : (
<View
style={{
height: height * 0.25,
width: '100%'
}}>
<WebView
onLoad={onLoad}
ref={webviewRef}
style={{
width: '100%',
height: '100%',
backgroundColor: 'transparent'
}}
cacheMode="LOAD_DEFAULT"
domStorageEnabled={true}
scrollEnabled={true}
bounces={false}
allowFileAccess={true}
scalesPageToFit={true}
allowingReadAccessToURL={
Platform.OS === 'android' ? true : null
}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
allowFileAccessFromFileURLs={true}
allowUniversalAccessFromFileURLs={true}
originWhitelist={['*']}
javaScriptEnabled={true}
cacheEnabled={true}
source={
Platform.OS === 'ios'
? {uri: sourceUri}
: {
uri: 'file:///android_asset/plaineditor.html',
baseUrl: 'file:///android_asset/'
}
}
/>
</View>
)}
<View <View
style={{ style={{
width: '100%', width: '100%',
paddingHorizontal: 12 height: height * 0.25,
paddingBottom: 15
}}>
<WebView
onLoad={onLoad}
ref={webviewRef}
style={{
width: '100%',
height: '100%',
backgroundColor: 'transparent'
}}
cacheMode="LOAD_DEFAULT"
domStorageEnabled={true}
scrollEnabled={true}
bounces={false}
allowFileAccess={true}
scalesPageToFit={true}
allowingReadAccessToURL={
Platform.OS === 'android' ? true : null
}
onMessage={onMessage}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
allowFileAccessFromFileURLs={true}
allowUniversalAccessFromFileURLs={true}
originWhitelist={['*']}
javaScriptEnabled={true}
cacheEnabled={true}
source={
Platform.OS === 'ios'
? {uri: sourceUri}
: {
uri: 'file:///android_asset/plaineditor.html',
baseUrl: 'file:///android_asset/'
}
}
/>
</View>
<View
style={{
flexDirection: 'row',
paddingHorizontal: 12,
paddingRight: 80,
alignItems: 'center'
}}> }}>
<Button <Button
color={colors.accent} color={colors.shade}
onPress={onPress} onPress={onPress}
loading={loading} icon={modes[mode].icon}
icon="check" onPress={async () => {
iconSize={25} let _mode = modes[mode];
type="action" if (
_mode.type === 'text' &&
validator.isURL(rawData.value)
) {
let html = await sanitizeHtml(rawData.value);
html = await absolutifyImgs(html, rawData.value);
setNote(note => {
note.content.data = html;
return {...note};
});
setMode(2);
return;
}
if (_mode.type === 'clip') {
let html = validator.isURL(rawData.value)
? makeHtmlFromUrl(rawData.value)
: makeHtmlFromPlainText(rawData.value);
setNote(note => {
note.content.data = html;
return {...note};
});
setMode(1);
return;
}
}}
title={modes[mode].title}
iconSize={18}
iconColor={colors.accent}
textStyle={{
fontSize: 12,
color: colors.accent,
marginLeft: 5
}}
style={{ style={{
position: 'absolute', marginRight: 10,
zIndex: 999, height: 30,
...getElevation(10), borderRadius: 100,
right: 24, paddingHorizontal: 12,
bottom: -35 marginTop: -2.5
}} }}
/> />
<View {Clipboard.hasString() ? (
style={{ <Button
marginTop: 10, color={colors.nav}
minHeight: 100, onPress={onPress}
borderRadius: 10, icon="clipboard"
...getElevation(5), onPress={async () => {
backgroundColor: colors.bg let text = await Clipboard.getString();
}}> if (text) {
<TextInput let content = await getContent();
ref={textInputRef} setNote(note => {
style={{ note.content.data =
fontSize: 16, content + '\n' + makeHtmlFromPlainText(text);
color: colors.pri, return {...note};
fontFamily: 'OpenSans-Regular', });
padding: 12, }
width: '100%' }}
iconSize={18}
iconColor={colors.icon}
title="Paste"
textStyle={{
fontSize: 12,
color: colors.icon,
marginLeft: 5
}} }}
placeholderTextColor={colors.icon}
onChangeText={v => (editorContentValue = v)}
multiline={true}
numberOfLines={quickNote ? 5 : 3}
textAlignVertical="top"
value={editorContentValue}
blurOnSubmit={false}
placeholder={
quickNote
? 'Write something...'
: 'Add some additional notes here'
}
/>
<View
style={{ style={{
flexDirection: 'row', marginRight: 15,
paddingHorizontal: 12, height: 30,
paddingRight: 80 borderRadius: 100,
}}> paddingHorizontal: 6,
<Button marginTop: -2.5
color={colors.shade} }}
onPress={onPress} />
loading={loading} ) : null}
icon={modes[mode].icon}
onPress={async () => {
let _mode = modes[mode];
if (_mode.type === "text") {
setMode(2);
return;
}
if (_mode.type === "clip") {
setMode(1);
return
}
if (_mode.type == "link") {
setMode(3)
}
}}
title={modes[mode].title}
iconSize={18}
iconColor={colors.accent}
textStyle={{
fontSize: 12,
color: colors.accent,
marginLeft: 5
}}
style={{
marginRight: 10,
height: 30,
borderRadius: 100,
paddingHorizontal: 12,
marginTop: -2.5
}}
/>
{Clipboard.hasString() ? (
<Button
color={colors.nav}
onPress={onPress}
loading={loading}
icon="clipboard"
onPress={async () => {
let text = await Clipboard.getString();
if (text) {
textInputRef.current?.setNativeProps({
text: text
});
editorContentValue = text;
}
}}
iconSize={18}
iconColor={colors.icon}
title="Paste"
textStyle={{
fontSize: 12,
color: colors.icon,
marginLeft: 5
}}
style={{
marginRight: 15,
height: 30,
borderRadius: 100,
paddingHorizontal: 6,
marginTop: -2.5
}}
/>
) : null}
</View>
</View>
</View> </View>
<View
style={{
height: 40
}}
/>
</View> </View>
</> </View>
)} <View
style={{
height: 40
}}
/>
</View>
</AnimatedKAV> </AnimatedKAV>
</AnimatedSAV> </AnimatedSAV>
); );
@@ -699,7 +592,7 @@ const Button = ({
]}> ]}>
{loading && <ActivityIndicator color="white" />} {loading && <ActivityIndicator color="white" />}
{icon && ( {icon && !loading && (
<Icon name={icon} size={iconSize} color={iconColor || 'white'} /> <Icon name={icon} size={iconSize} color={iconColor || 'white'} />
)} )}