mobile: add support for internal links

This commit is contained in:
Ammar Ahmed
2026-03-27 11:38:51 +05:00
parent 1172a8c67b
commit 5909025976
8 changed files with 78 additions and 33 deletions

View File

@@ -155,6 +155,15 @@
<data android:scheme="notesnook" />
</intent-filter>
<intent-filter android:label="Notesnook">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nn" />
</intent-filter>
</activity>
<activity
android:name="com.facebook.react.devsupport.DevSettingsActivity"

View File

@@ -33,7 +33,7 @@ public class NotePreviewWidget extends AppWidgetProvider {
intent.putExtra(OpenNoteId, note.getId());
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RCTNNativeModule.IntentType, "OpenNote");
intent.setData(Uri.parse("https://app.notesnook.com/open_note?id=" + note.getId()));
intent.setData(Uri.parse("nn://note/" + note.getId()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.open_note, pendingIntent);

View File

@@ -259,7 +259,7 @@ public class RCTNNativeModule extends ReactContextBaseJavaModule {
return;
}
String uri = "https://app.notesnook.com/open_" + type + "?id=" + id;
String uri = "nn://" + type + "/" + id;
Intent intent = new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(uri));
intent.setPackage(mContext.getPackageName());

View File

@@ -79,6 +79,7 @@ const COLUMN_BAR_ITEMS: ActionId[] = [
"rename-color",
"rename-tag",
"launcher-shortcut",
"copy-link",
"restore",
"trash",
"delete"

View File

@@ -1002,20 +1002,6 @@ export const useActions = ({
icon: "history",
onPress: openHistory
},
{
id: "copy-link",
title: strings.copyLink(),
icon: "link",
onPress: () => {
Clipboard.setString(createInternalLink("note", item.id));
ToastManager.show({
heading: strings.linkCopied(),
message: createInternalLink("note", item.id),
context: "local",
type: "success"
});
}
},
{
id: "reminders",
title: strings.dataTypesPluralCamelCase.reminder(),
@@ -1271,5 +1257,28 @@ export const useActions = ({
});
}
if (
item.type === "tag" ||
item.type === "note" ||
item.type === "notebook" ||
item.type === "color"
) {
actions.push({
id: "copy-link",
title: strings.copyLink(),
icon: "link",
onPress: () => {
const link = createInternalLink(item.type, item.id);
Clipboard.setString(link);
ToastManager.show({
heading: strings.linkCopied(),
message: link,
context: "local",
type: "success"
});
}
});
}
return actions;
};

View File

@@ -25,7 +25,9 @@ import {
SYNC_CHECK_IDS,
SubscriptionPlan,
SyncStatusEvent,
User
User,
isInternalLink,
parseInternalLink
} from "@notesnook/core";
import { strings } from "@notesnook/intl";
import notifee from "@notifee/react-native";
@@ -169,6 +171,8 @@ const onAppOpenedFromURL = async (event: {
}) => {
const url = event.url;
const parsedLink = isInternalLink(url) ? parseInternalLink(url) : undefined;
try {
if (url.startsWith("https://app.notesnook.com/account/verified")) {
await onUserEmailVerified();
@@ -178,8 +182,12 @@ const onAppOpenedFromURL = async (event: {
eSendEvent(eOnLoadNote, { newNote: true });
fluidTabsRef.current?.goToPage("editor", false);
return;
} else if (url.startsWith("https://app.notesnook.com/open_note?")) {
const id = new URL(url).searchParams.get("id");
} else if (
parsedLink?.type === "note" ||
url.startsWith("https://app.notesnook.com/open_note?")
) {
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
const note = await db.notes.note(id);
if (note) {
@@ -191,10 +199,11 @@ const onAppOpenedFromURL = async (event: {
}
}
} else if (
url.startsWith("https://app.notesnook.com/open_notebook?") &&
(parsedLink?.type === "notebook" ||
url.startsWith("https://app.notesnook.com/open_notebook?")) &&
!event.isInitialUrl
) {
const id = new URL(url).searchParams.get("id");
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
const notebook = await db.notebooks.notebook(id);
if (notebook) {
@@ -206,10 +215,11 @@ const onAppOpenedFromURL = async (event: {
}
}
} else if (
url.startsWith("https://app.notesnook.com/open_tag?") &&
(parsedLink?.type === "tag" ||
url.startsWith("https://app.notesnook.com/open_tag?")) &&
!event.isInitialUrl
) {
const id = new URL(url).searchParams.get("id");
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
const tag = await db.tags.tag(id);
if (tag) {
@@ -222,10 +232,11 @@ const onAppOpenedFromURL = async (event: {
}
}
} else if (
url.startsWith("https://app.notesnook.com/open_color?") &&
(parsedLink?.type === "color" ||
url.startsWith("https://app.notesnook.com/open_color?")) &&
!event.isInitialUrl
) {
const id = new URL(url).searchParams.get("id");
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
const color = await db.colors.color(id);
if (color) {

View File

@@ -31,6 +31,7 @@ import { useSettingStore } from "../stores/use-setting-store";
import { rootNavigatorRef } from "../utils/global-refs";
import Navigation from "../services/navigation";
import { isFeatureAvailable } from "@notesnook/common";
import { isInternalLink, parseInternalLink } from "@notesnook/core";
const RootStack = createNativeStackNavigator();
const AppStack = createNativeStackNavigator();
@@ -63,10 +64,17 @@ const AppNavigation = React.memo(
React.useEffect(() => {
if (!home) {
if (useSettingStore.getState().initialUrl) {
const url = useSettingStore.getState().initialUrl;
if (url?.startsWith("https://app.notesnook.com/open_notebook?")) {
const id = new URL(url).searchParams.get("id");
const url = useSettingStore.getState().initialUrl;
if (url) {
const parsedLink = isInternalLink(url)
? parseInternalLink(url)
: undefined;
if (
parsedLink?.type === "notebook" ||
url?.startsWith("https://app.notesnook.com/open_notebook?")
) {
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
setHome({
name: "Notebook",
@@ -76,8 +84,11 @@ const AppNavigation = React.memo(
});
return;
}
} else if (url?.startsWith("https://app.notesnook.com/open_tag?")) {
const id = new URL(url).searchParams.get("id");
} else if (
parsedLink?.type === "tag" ||
url?.startsWith("https://app.notesnook.com/open_tag?")
) {
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
setHome({
name: "TaggedNotes",
@@ -88,8 +99,11 @@ const AppNavigation = React.memo(
});
return;
}
} else if (url?.startsWith("https://app.notesnook.com/open_color?")) {
const id = new URL(url).searchParams.get("id");
} else if (
parsedLink?.type === "color" ||
url?.startsWith("https://app.notesnook.com/open_color?")
) {
const id = parsedLink?.id || new URL(url).searchParams.get("id");
if (id) {
setHome({
name: "ColoredNotes",

View File

@@ -52,6 +52,7 @@
<key>CFBundleURLSchemes</key>
<array>
<string>ShareMedia</string>
<string>nn</string>
</array>
</dict>
<dict>