();
@@ -380,7 +373,7 @@ export const Search = ({
const onSearch = async () => {
if (timer.current) {
clearTimeout(timer.current);
- timer.current = undefined;
+ timer.current = null;
}
timer.current = setTimeout(async () => {
if (!searchKeyword) {
@@ -420,7 +413,7 @@ export const Search = ({
}
diff --git a/apps/mobile/share/share.js b/apps/mobile/app/share/share.tsx
similarity index 88%
rename from apps/mobile/share/share.js
rename to apps/mobile/app/share/share.tsx
index 9cf75277d..9440e9541 100644
--- a/apps/mobile/share/share.js
+++ b/apps/mobile/app/share/share.tsx
@@ -17,7 +17,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-import ShareExtension from "@ammarahmed/react-native-share-extension";
+import ShareExtension, {
+ ShareItem
+} from "@ammarahmed/react-native-share-extension";
import { getPreviewData } from "@flyerhq/react-native-link-preview";
import {
formatBytes,
@@ -33,8 +35,8 @@ import {
Dimensions,
Image,
Keyboard,
+ KeyboardEvent,
Platform,
- SafeAreaView,
ScrollView,
Text,
TextInput,
@@ -43,31 +45,36 @@ import {
useWindowDimensions
} from "react-native";
import RNFetchBlob from "react-native-blob-util";
-import { SafeAreaProvider } from "react-native-safe-area-context";
+import {
+ SafeAreaProvider,
+ SafeAreaView,
+ useSafeAreaInsets
+} from "react-native-safe-area-context";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import isURL from "validator/lib/isURL";
-import { DatabaseLogger, db } from "../app/common/database";
-import { Storage } from "../app/common/database/storage";
-import { Button } from "../app/components/ui/button";
-import Heading from "../app/components/ui/typography/heading";
-import Paragraph from "../app/components/ui/typography/paragraph";
-import { useDBItem } from "../app/hooks/use-db-item";
-import { eSendEvent } from "../app/services/event-manager";
-import { FILE_SIZE_LIMIT, IMAGE_SIZE_LIMIT } from "../app/utils/constants";
-import { eOnLoadNote } from "../app/utils/events";
-import { NoteBundle } from "../app/utils/note-bundle";
-import { defaultBorderRadius, AppFontSize } from "../app/utils/size";
+import { DatabaseLogger, db } from "../common/database";
+import { Storage } from "../common/database/storage";
+import { Button } from "../components/ui/button";
+import Heading from "../components/ui/typography/heading";
+import Paragraph from "../components/ui/typography/paragraph";
+import { useDBItem } from "../hooks/use-db-item";
+import { eSendEvent } from "../services/event-manager";
+import { eOnLoadNote } from "../utils/events";
+import { NoteBundle } from "../utils/note-bundle";
+import { defaultBorderRadius, AppFontSize } from "../utils/size";
import { AddNotebooks } from "./add-notebooks";
import { AddTags } from "./add-tags";
-import { Editor } from "./editor";
+import { Editor, EditorRef } from "./editor";
import { HtmlLoadingWebViewAgent, fetchHandle } from "./fetch-webview";
import { Search } from "./search";
import { initDatabase, useShareStore } from "./store";
+import { isTablet } from "react-native-device-info";
+import { NotesnookModule } from "../utils/notesnook-module";
-const getLinkPreview = (url) => {
+const getLinkPreview = (url: string) => {
return getPreviewData(url, 5000);
};
-async function sanitizeHtml(site) {
+async function sanitizeHtml(site: string) {
try {
let html = await fetchHandle.current?.processUrl(site);
return html;
@@ -76,11 +83,11 @@ async function sanitizeHtml(site) {
}
}
-function makeHtmlFromUrl(url) {
+function makeHtmlFromUrl(url: string) {
return `${url}`;
}
-function makeHtmlFromPlainText(text) {
+function makeHtmlFromPlainText(text: string) {
if (!text) return "";
return `${text
@@ -88,12 +95,22 @@ function makeHtmlFromPlainText(text) {
.replace(/(?:\r\n|\r|\n)/g, "
")}
`;
}
-let defaultNote = {
- title: null,
- id: null,
+type DefaultNote = {
+ title?: string;
+ id?: string;
+ sessionId?: number;
+ content: {
+ type: "tiptap";
+ data?: string;
+ };
+};
+
+let defaultNote: DefaultNote = {
+ title: "",
+ id: undefined,
content: {
type: "tiptap",
- data: null
+ data: ""
}
};
@@ -115,32 +132,40 @@ const modes = {
}
};
+declare global {
+ var IS_SHARE_EXTENSION: boolean;
+ var IS_MAIN_APP_RUNNING: boolean;
+}
+
const ShareView = () => {
const { colors } = useThemeColors();
+ const gesturesEnabled = NotesnookModule.isGestureNavigationEnabled();
const appendNoteId = useShareStore((state) => state.appendNote);
const [note, setNote] = useState({ ...defaultNote });
- const noteContent = useRef("");
- const noteTitle = useRef("");
+ const noteContent = useRef(undefined);
+ const noteTitle = useRef(undefined);
const [loading, setLoading] = useState(false);
const [loadingExtension, setLoadingExtension] = useState(true);
const fullQualityImages = useIsFeatureAvailable("fullQualityImages");
- const [rawData, setRawData] = useState({
- type: null,
- value: null
- });
- const inputRef = useRef(null);
+ const [rawData, setRawData] = useState<{
+ type?: string;
+ value?: string;
+ }>({});
+ const inputRef = useRef(null);
const [mode, setMode] = useState(1);
const keyboardHeight = useRef(0);
const { width, height } = useWindowDimensions();
const [loadingPage, setLoadingPage] = useState(false);
- const editorRef = useRef();
- const [searchMode, setSearchMode] = useState(null);
- const [rawFiles, setRawFiles] = useState([]);
-
+ const editorRef = useRef(null);
+ const [searchMode, setSearchMode] = useState<
+ "appendNote" | "selectTags" | "selectNotebooks" | null
+ >(null);
+ const [rawFiles, setRawFiles] = useState([]);
+ const insets = useSafeAreaInsets();
const [kh, setKh] = useState(0);
const [compress, setCompress] = useState(true);
globalThis["IS_SHARE_EXTENSION"] = true;
- const onKeyboardDidShow = (event) => {
+ const onKeyboardDidShow = (event: KeyboardEvent) => {
let height = Dimensions.get("screen").height - event.endCoordinates.screenY;
keyboardHeight.current = height;
setKh(height);
@@ -172,7 +197,7 @@ const ShareView = () => {
}
}, [fullQualityImages]);
- const showLinkPreview = async (note, link) => {
+ const showLinkPreview = async (note: DefaultNote, link: string) => {
let _note = note;
_note.content.data = makeHtmlFromUrl(link);
try {
@@ -184,20 +209,33 @@ const ShareView = () => {
return note;
};
+ const onLoad = useCallback(() => {
+ console.log(noteContent.current, "current...");
+ eSendEvent(eOnLoadNote + "shareEditor", {
+ id: null,
+ content: {
+ type: "tiptap",
+ data: noteContent.current
+ },
+ forced: true
+ });
+ }, []);
+
const loadData = useCallback(
- async (isEditor) => {
+ async (isEditor: boolean) => {
try {
if (noteContent.current) {
onLoad();
return;
}
- defaultNote.content.data = null;
+ defaultNote.content.data = undefined;
setNote({ ...defaultNote });
const data = await ShareExtension.data();
if (!data || data.length === 0) {
setRawData({
- value: ""
+ value: "",
+ type: "text"
});
if (isEditor) {
setTimeout(() => {
@@ -257,7 +295,6 @@ const ShareView = () => {
}
}
onLoad();
-
setNote({ ...note });
} catch (e) {
console.error(e);
@@ -266,23 +303,12 @@ const ShareView = () => {
[onLoad]
);
- const onLoad = useCallback(() => {
- eSendEvent(eOnLoadNote + "shareEditor", {
- id: null,
- content: {
- type: "tiptap",
- data: noteContent.current
- },
- forced: true
- });
- }, []);
-
useEffect(() => {
(async () => {
try {
await initDatabase();
setLoadingExtension(false);
- loadData();
+ loadData(false);
useShareStore.getState().restore();
} catch (e) {
DatabaseLogger.error(e);
@@ -305,22 +331,23 @@ const ShareView = () => {
let noteData;
if (appendNoteId) {
- if (!(await db.notes.exists(appendNoteId))) {
+ const note = await db.notes.note(appendNoteId);
+ if (!note) {
useShareStore.getState().setAppendNote(null);
Alert.alert("The note you are trying to append to has been deleted.");
setLoading(false);
return;
}
- const note = await db.notes.note(appendNoteId);
- let rawContent = await db.content.get(note.contentId);
-
+ let rawContent = note.contentId
+ ? await db.content.get(note.contentId)
+ : null;
noteData = {
content: {
data: (rawContent?.data || "") + "
" + noteContent.current,
type: "tiptap"
},
- id: note.id,
+ id: note?.id,
sessionId: Date.now()
};
} else {
@@ -353,28 +380,30 @@ const ShareView = () => {
setLoading(false);
};
- const changeMode = async (m) => {
- setMode(m);
+ const changeMode = async (value: number) => {
+ setMode(value);
setLoading(true);
try {
- if (m === 2) {
+ if (value === 2) {
setLoadingPage(true);
setTimeout(async () => {
- let html = await sanitizeHtml(rawData.value);
- noteContent.current = html;
+ let html = await sanitizeHtml(rawData?.value || "");
+ noteContent.current = html || "";
setLoadingPage(false);
onLoad();
setNote((note) => {
- note.content.data = html;
+ note.content.data = html || "";
return { ...note };
});
}, 300);
} else {
setLoadingPage(false);
- let html = isURL(rawData.value)
- ? makeHtmlFromUrl(rawData.value)
- : makeHtmlFromPlainText(rawData.value);
+ let html = !rawData.value
+ ? ""
+ : isURL(rawData?.value)
+ ? makeHtmlFromUrl(rawData?.value)
+ : makeHtmlFromPlainText(rawData?.value);
setNote((note) => {
note.content.data = html;
noteContent.current = html;
@@ -394,7 +423,7 @@ const ShareView = () => {
loadData(true);
}, [loadData]);
- const onRemoveFile = (item) => {
+ const onRemoveFile = (item: ShareItem) => {
const index = rawFiles.findIndex((file) => file.name === item.name);
if (index > -1) {
setRawFiles((state) => {
@@ -412,10 +441,13 @@ const ShareView = () => {
500 ? 500 : width,
- height: height - kh,
+ height: "100%",
alignSelf: "center",
justifyContent: "flex-end",
- overflow: "hidden"
+ overflow: "hidden",
+ paddingBottom: kh
+ ? kh - (insets.bottom || (gesturesEnabled ? 25 : 50))
+ : 0
}}
>
{loadingPage ? : null}
@@ -528,7 +560,7 @@ const ShareView = () => {
defaultValue={noteTitle.current}
blurOnSubmit={false}
onSubmitEditing={() => {
- editorRef.current.focus();
+ editorRef.current?.focus();
}}
/>
)}
@@ -583,9 +615,6 @@ const ShareView = () => {
onRemoveFile(item)}
style={{
borderRadius: defaultBorderRadius,
@@ -598,7 +627,6 @@ const ShareView = () => {
paddingHorizontal: 8,
marginRight: 6
}}
- resizeMode="cover"
>
{