Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add desktop shortcut support #4194

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 45 additions & 0 deletions app/components/sidebar.tsx
Expand Up @@ -31,6 +31,8 @@ import { isIOS, useMobileScreen } from "../utils";
import dynamic from "next/dynamic";
import { showConfirm, showToast } from "./ui-lib";

import { register } from "@tauri-apps/api/globalShortcut";

const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, {
loading: () => null,
});
Expand Down Expand Up @@ -128,6 +130,47 @@ function useDragSideBar() {
};
}

function useGlobalShortcut() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this the correct

function useGlobalShortcut() {
  // Early return if not in a Tauri environment
  if (!window.__TAURI__) {
    return;
  }

  const chatStore = useChatStore();
  const navigate = useNavigate();
  const config = useAppConfig();

  const handleMasks = async () => {
    await register("CommandOrControl+Shift+M", () => {
      if (config.dontShowMaskSplashScreen !== true) {
        navigate(Path.NewChat, { state: { fromHome: true } });
      } else {
        navigate(Path.Masks, { state: { fromHome: true } });
      }
    });
  };

  const handleSettings = async () => {
    await register("CommandOrControl+,", () => {
      navigate(Path.Settings);
    });
  };

  const handleNewChat = async () => {
    await register("CommandOrControl+N", () => {
      if (config.dontShowMaskSplashScreen) {
        chatStore.newSession();
        navigate(Path.Chat);
      } else {
        navigate(Path.NewChat);
      }
    });
  };

  useEffect(() => {
    handleMasks();
    handleSettings();
    handleNewChat();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JasonEWNL there is another one

function useGlobalShortcut() {
  // Call hooks at the top level to comply with the rules of hooks.
  const chatStore = useChatStore();
  const navigate = useNavigate();
  const config = useAppConfig();

  useEffect(() => {
    // Early return if not in a Tauri environment. This way, the hooks are called unconditionally,
    // but the code inside useEffect only runs conditionally.
    if (!window.__TAURI__) {
      return;
    }

    const handleMasks = async () => {
      await register("CommandOrControl+Shift+M", () => {
        if (config.dontShowMaskSplashScreen !== true) {
          navigate(Path.NewChat, { state: { fromHome: true } });
        } else {
          navigate(Path.Masks, { state: { fromHome: true } });
        }
      });
    };

    const handleSettings = async () => {
      await register("CommandOrControl+,", () => {
        navigate(Path.Settings);
      });
    };

    const handleNewChat = async () => {
      await register("CommandOrControl+N", () => {
        if (config.dontShowMaskSplashScreen) {
          chatStore.newSession();
          navigate(Path.Chat);
        } else {
          navigate(Path.NewChat);
        }
      });
    };

    // Execute the registration functions.
    handleMasks();
    handleSettings();
    handleNewChat();

    // Remember to return a cleanup function if necessary, for example, to unregister the shortcuts.
  }, [chatStore, navigate, config]); // Include all dependencies here.
}

const chatStore = useChatStore();
const navigate = useNavigate();
const config = useAppConfig();

const handleMasks = async () => {
await register("CommandOrControl+Shift+M", () => {
if (config.dontShowMaskSplashScreen !== true) {
navigate(Path.NewChat, { state: { fromHome: true } });
} else {
navigate(Path.Masks, { state: { fromHome: true } });
}
});
};

const handleSettings = async () => {
await register("CommandOrControl+,", () => {
navigate(Path.Settings);
});
};

const handleNewChat = async () => {
await register("CommandOrControl+N", () => {
if (config.dontShowMaskSplashScreen) {
chatStore.newSession();
navigate(Path.Chat);
} else {
navigate(Path.NewChat);
}
});
};

useEffect(() => {
if (window.__TAURI__) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you still need to put // eslint-disable-next-line react-hooks/exhaustive-deps for bypass/ignore stupid react/nextjs warning

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience! All changes are cleaned and submitted.

handleMasks();
handleSettings();
handleNewChat();
}
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this comment
// eslint-disable-next-line react-hooks/exhaustive-deps

for example:

  useEffect(() => {
    handleMasks();
    handleSettings();
    handleNewChat();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

for ignore/bypass that stupid react/nextjs warning

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review! It might be refactored into a modular structure if desktop shortcut feature is accepted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JasonEWNL cek new one

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review! It might be refactored into a modular structure if desktop shortcut feature is accepted.

@JasonEWNL The desktop version is actually quite useful compared to the web version, which has limitations. For instance, you can't leverage certain features on the web version, but you can definitely leverage them on the desktop version. since it's safe through memory leaks and other

}

export function SideBar(props: { className?: string }) {
const chatStore = useChatStore();

Expand All @@ -143,6 +186,8 @@ export function SideBar(props: { className?: string }) {

useHotKey();

useGlobalShortcut();

return (
<div
className={`${styles.sidebar} ${props.className} ${
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -20,6 +20,7 @@
"@hello-pangea/dnd": "^16.5.0",
"@next/third-parties": "^14.1.0",
"@svgr/webpack": "^6.5.1",
"@tauri-apps/api": "^1.5.3",
"@vercel/analytics": "^0.1.11",
"@vercel/speed-insights": "^1.0.2",
"emoji-picker-react": "^4.5.15",
Expand Down Expand Up @@ -64,4 +65,4 @@
"resolutions": {
"lint-staged/yaml": "^2.2.2"
}
}
}
1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Expand Up @@ -35,6 +35,7 @@ tauri = { version = "1.5.4", features = [
"window-start-dragging",
"window-unmaximize",
"window-unminimize",
"global-shortcut-all",
] }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }

Expand Down
3 changes: 3 additions & 0 deletions src-tauri/tauri.conf.json
Expand Up @@ -50,6 +50,9 @@
},
"notification": {
"all": true
},
"globalShortcut": {
"all": true
}
},
"bundle": {
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Expand Up @@ -1438,6 +1438,11 @@
dependencies:
tslib "^2.4.0"

"@tauri-apps/api@^1.5.3":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.5.3.tgz#f7b362b1f30aadb0a8bbeb7ae111755c0ed33d73"
integrity sha512-zxnDjHHKjOsrIzZm6nO5Xapb/BxqUq1tc7cGkFXsFkGTsSWgCPH1D8mm0XS9weJY2OaR73I3k3S+b7eSzJDfqA==

"@tauri-apps/cli-darwin-arm64@1.5.7":
version "1.5.7"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.7.tgz#3435f1b6c4b431e0283f94c3a0bd486be66b24ee"
Expand Down