mobile: handle app shortcuts correctly during cold and warm app launches

Signed-off-by: kashaf-ansari-dev <kashafansari3108@gmail.com>
This commit is contained in:
kashaf-ansari-dev
2026-07-07 14:28:23 +05:00
committed by Ammar Ahmed
parent 64943647f8
commit 180c202c4e
5 changed files with 71 additions and 40 deletions

View File

@@ -44,9 +44,15 @@ import { useUserStore } from "./stores/use-user-store";
import RNBootSplash from "react-native-bootsplash";
import AppLocked from "./components/app-lock";
import { useSettingStore } from "./stores/use-setting-store";
import { registerAppShortcuts } from "./hooks/use-shortcut-manager";
import Shortcuts, { ShortcutItem } from "react-native-actions-shortcuts";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
I18nManager.swapLeftAndRightInRTL(false);
declare global {
var __pendingShortcut: ShortcutItem | null | undefined;
}
const { appLockEnabled, appLockMode } = SettingsService.get();
if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
@@ -59,10 +65,23 @@ Linking.getInitialURL().then((url) => {
initialUrl: url
});
});
Shortcuts.getInitialShortcut().then((shortcut) => {
globalThis.__pendingShortcut = shortcut;
});
const App = (props: { configureMode: "note-preview" }) => {
useAppEvents();
//@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true;
const introCompleted = useSettingStore(
(state) => state.settings.introCompleted
);
useEffect(() => {
if (introCompleted) {
registerAppShortcuts();
}
}, [introCompleted]);
useEffect(() => {
SettingsService.onFirstLaunch();
changeSystemBarColors();

View File

@@ -45,26 +45,12 @@ const defaultShortcuts: ShortcutItem[] = [
}
];
export const useShortcutManager = ({
onShortcutPressed,
shortcuts = defaultShortcuts
onShortcutPressed
}: {
onShortcutPressed: (shortcut: ShortcutItem | null) => void;
shortcuts?: ShortcutItem[];
}) => {
const initialShortcutRecieved = useRef(false);
useEffect(() => {
if (!isSupported()) return;
Shortcuts.setShortcuts(shortcuts);
}, [shortcuts]);
useEffect(() => {
if (!isSupported()) return;
Shortcuts.getInitialShortcut().then((shortcut) => {
if (initialShortcutRecieved.current || !shortcut) return;
onShortcutPressed(shortcut);
initialShortcutRecieved.current = true;
});
const subscription = ShortcutsEmitter.addListener(
"onShortcutItemPressed",
onShortcutPressed
@@ -74,3 +60,8 @@ export const useShortcutManager = ({
};
}, [onShortcutPressed]);
};
export const registerAppShortcuts = () => {
if (!isSupported()) return;
Shortcuts.setShortcuts(defaultShortcuts);
};

View File

@@ -68,6 +68,8 @@ import { fluidTabsRef } from "../utils/global-refs";
import { AppNavigationStack } from "./navigation-stack";
import type { PaneWidths } from "../screens/editor/wrapper";
import AddReminder from "../screens/add-reminder";
import Navigation from "../services/navigation";
import { ShortcutItem } from "react-native-actions-shortcuts";
const MOBILE_SIDEBAR_SIZE = 0.85;
@@ -112,33 +114,37 @@ export const FluidPanelsView = React.memo(
}
}, [appLoading]);
useShortcutManager({
onShortcutPressed: async (item) => {
if (!item) return;
useEffect(() => {
const pending = globalThis.__pendingShortcut;
if (
pending?.type === "notesnook.action.newnote" &&
fluidTabsRef.current &&
!appLoading
) {
eSendEvent(eOnLoadNote, { newNote: true });
editorState().movedAway = false;
fluidTabsRef.current.goToPage("editor", false);
globalThis.__pendingShortcut = null;
}
}, [deviceMode, appLoading]);
if (item?.type === "notesnook.action.newnote") {
if (!fluidTabsRef.current) {
setTimeout(() => {
eSendEvent(eOnLoadNote, { newNote: true });
editorState().movedAway = false;
fluidTabsRef.current?.goToPage("editor", false);
}, 1000);
return;
}
const onShortcutPressed = useCallback(async (item: ShortcutItem | null) => {
if (!item) return;
if (item?.type === "notesnook.action.newnote") {
Navigation.navigate("FluidPanelsView");
requestAnimationFrame(() => {
eSendEvent(eOnLoadNote, { newNote: true });
editorState().movedAway = false;
setTimeout(
() => fluidTabsRef.current?.goToPage("editor", false),
300
);
}
if (item?.type === "notesnook.action.newreminder") {
setTimeout(() => {
AddReminder.present();
}, 1000);
}
fluidTabsRef.current?.goToPage("editor", false);
});
}
});
if (item?.type === "notesnook.action.newreminder") {
AddReminder.present();
}
}, []);
useShortcutManager({ onShortcutPressed });
const showFullScreenEditor = useCallback(() => {
setFullscreen(true);

View File

@@ -316,8 +316,23 @@ export const RootNavigation = () => {
[clearSelection]
);
const onNavigationReady = React.useCallback(() => {
const pending = globalThis.__pendingShortcut;
if (pending?.type === "notesnook.action.newreminder") {
rootNavigatorRef.current?.navigate("AddReminder", {
reminder: undefined,
reference: undefined
});
globalThis.__pendingShortcut = null;
}
}, []);
return (
<NavigationContainer onStateChange={onStateChange} ref={rootNavigatorRef}>
<NavigationContainer
onStateChange={onStateChange}
onReady={onNavigationReady}
ref={rootNavigatorRef}
>
<RootStack.Navigator
screenOptions={{
headerShown: false

View File

@@ -94,7 +94,7 @@ const ReminderNotificationModes = {
};
export default function AddReminder(props: NavigationProps<"AddReminder">) {
const { reminder, reference } = props.route.params;
const { reminder, reference } = props.route.params ?? {};
useNavigationFocus(props.navigation, {
focusOnInit: true,
onFocus: () => {