-
Notifications
You must be signed in to change notification settings - Fork 2
enhancement: added interactive walkthrough to guide new users #25
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| .raycast-overlay { | ||
| position: fixed; | ||
| top: 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,29 @@ import HomeOptions from "./components/HomeOptions"; | |
| import ClipboardPage from "./components/ClipboardPage"; | ||
| import OnlineSearchPage from "./components/OnlineSearchPage"; | ||
| import OpenFilePage from "./components/OpenFilePage"; | ||
| import GuidePage from "./components/guidePages/GuidePage"; | ||
|
|
||
|
|
||
| function App() { | ||
| const [query, setQuery] = useState(""); | ||
| const inputRef = useRef(null); | ||
| const [currentPage, setCurrentPage] = useState("home"); | ||
| const [firstLaunchChecked, setFirstLaunchChecked] = useState(false); | ||
|
|
||
|
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker: First‑launch logic always opens the guide; flag saved too early. You’re setting hasLaunched=true on first mount and never reading it, so the guide shows every time. Read the flag and only show the guide when missing. Save the flag after completion (GuidePage sets it at page 6 per its fix). - const [firstLaunchChecked, setFirstLaunchChecked] = useState(false);
+ const [firstLaunchChecked, setFirstLaunchChecked] = useState(false);
...
- useEffect(() => {
-
- if(firstLaunchChecked === false){
- localStorage.setItem("hasLaunched", "true");
- setCurrentPage("open-guide")
- console.log()
- }
- else{
- setCurrentPage("home")
- }
- setFirstLaunchChecked(true)
-
- },[])
+ useEffect(() => {
+ const hasLaunched = localStorage.getItem("hasLaunched") === "true";
+ setCurrentPage(hasLaunched ? "home" : "open-guide");
+ setFirstLaunchChecked(true);
+ }, []);Also applies to: 18-30 🤖 Prompt for AI Agents |
||
|
|
||
| useEffect(() => { | ||
|
|
||
| if(firstLaunchChecked === false){ | ||
| localStorage.setItem("hasLaunched", "true"); | ||
| setCurrentPage("open-guide") | ||
| console.log() | ||
| } | ||
| else{ | ||
| setCurrentPage("home") | ||
| } | ||
| setFirstLaunchChecked(true) | ||
|
|
||
| },[]) | ||
|
|
||
| useEffect(() => { | ||
| function handleKeyDown(e) { | ||
|
|
@@ -40,7 +58,7 @@ function App() { | |
| placeholder="Search..." | ||
| value={query} | ||
| onChange={(e) => setQuery(e.target.value)} | ||
| className="search-input" | ||
| className={`search-input ${currentPage === "open-guide" ? "hidden" : "block"}`} | ||
| /> | ||
|
Comment on lines
+61
to
62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: Passing unused prop to GuidePage. GuidePage doesn’t consume query; you can drop it to reduce prop churn. - {currentPage === "open-guide" && <GuidePage query={query} />}
+ {currentPage === "open-guide" && <GuidePage />}Also applies to: 82-83 🤖 Prompt for AI Agents |
||
| </div> | ||
| <div className="main-container"> | ||
|
|
@@ -60,6 +78,7 @@ function App() { | |
| <OnlineSearchPage query={query} /> | ||
| )} | ||
| {currentPage === "open-app" && <OpenFilePage query={query} />} | ||
| {currentPage === "open-guide" && <GuidePage query={query} />} | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,163 @@ | ||||||||||||||||||
| import { useEffect, useState } from "react" | ||||||||||||||||||
| import { useForm } from "react-hook-form" | ||||||||||||||||||
| import snapshort1 from "../../assets/snapshot1.png" | ||||||||||||||||||
| import snapshot2 from "../../assets/snapshort2.png" | ||||||||||||||||||
| import snapshot3 from "../../assets/snapshort3.png" | ||||||||||||||||||
| import snapshort4 from "../../assets/snapshort4.png" | ||||||||||||||||||
|
Comment on lines
+3
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix inconsistent asset import naming. The imports mix -import snapshort1 from "../../assets/snapshot1.png"
-import snapshot2 from "../../assets/snapshort2.png"
-import snapshot3 from "../../assets/snapshort3.png"
-import snapshort4 from "../../assets/snapshort4.png"
+import snapshot1 from "../../assets/snapshot1.png"
+import snapshot2 from "../../assets/snapshot2.png"
+import snapshot3 from "../../assets/snapshot3.png"
+import snapshot4 from "../../assets/snapshot4.png"Then update references on lines 91, 98, 117, and 136 accordingly.
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| function GuidePage(){ | ||||||||||||||||||
| const [page, setPage] = useState(0) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| const handleClick = () => { | ||||||||||||||||||
| setPage(p => p + 1) | ||||||||||||||||||
| console.log(page) | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+14
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use functional state update to avoid stale closures. -const handleClick = () => {
- setPage(page + 1)
- console.log(page)
-}
+const handleClick = () => setPage(p => p + 1)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| const { | ||||||||||||||||||
| register, | ||||||||||||||||||
| handleSubmit, | ||||||||||||||||||
| formState: { errors }, | ||||||||||||||||||
| } = useForm() | ||||||||||||||||||
|
|
||||||||||||||||||
| const onSubmit = (data) => { | ||||||||||||||||||
| console.log(data) | ||||||||||||||||||
| localStorage.setItem("name", data.name) | ||||||||||||||||||
| console.log(localStorage.getItem("name")) | ||||||||||||||||||
| handleClick() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 0){ | ||||||||||||||||||
| return( | ||||||||||||||||||
| <div style={{ | ||||||||||||||||||
| backgroundImage: "radial-gradient(circle, rgba(39, 39, 42, 1) 1.5px, transparent 1px)", | ||||||||||||||||||
| backgroundSize: "20px 20px", | ||||||||||||||||||
| backgroundRepeat: "repeat", | ||||||||||||||||||
| }} | ||||||||||||||||||
| className="flex flex-col justify-center items-center gap-1 h-screen bg-[#3D3C3C] font-sans"> | ||||||||||||||||||
| <div className="flex flex-row justify-center text-6xl pb-5 font-bold">Pathfinder</div> | ||||||||||||||||||
| <div className="felx flex-row justify-center text-center text-3xl">A tool to make your life easy</div> | ||||||||||||||||||
| <button onClick={handleClick} type="button" className="absolute bottom-3 right-5 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
|
Comment on lines
+42
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix Tailwind class typos and invalid utilities.
- <div className="felx flex-row justify-center text-center text-3xl">A tool to make your life easy</div>
+ <div className="flex flex-row justify-center text-center text-3xl">A tool to make your life easy</div>
...
- <div className="felx flex-row justify-left text-left text-4xl ">Hi ,{localStorage.getItem("name")} Welcome to Pathfinder</div>
+ <div className="flex flex-row justify-start text-left text-4xl ">Hi, {localStorage.getItem("name")} Welcome to Pathfinder</div>
...
- A powerful Raycast-inspired launcher application built with Tauri and React. PathFinder provides instant access to your most-used tools and information through a beautiful, keyboard-driven interface. And you can access it just my pressing
+ A powerful Raycast-inspired launcher application built with Tauri and React. PathFinder provides instant access to your most-used tools and information through a beautiful, keyboard-driven interface. And you can access it just by pressing
...
- <button onClick={handleClick} className="absolute bottom-3 left-180 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button>
+ <button type="button" onClick={handleClick} className="absolute bottom-3 left-[180px] flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button>Also applies to: 88-93, 102-103 🤖 Prompt for AI Agents |
||||||||||||||||||
| </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 1){ | ||||||||||||||||||
| return( | ||||||||||||||||||
| <div className="flex flex-col justify-center items-center gap-5 h-screen bg-[#3D3C3C] font-sans"> | ||||||||||||||||||
| <div className="text-4xl">Enter Your Name</div> | ||||||||||||||||||
| <div> | ||||||||||||||||||
| <form onSubmit={handleSubmit(onSubmit)}> | ||||||||||||||||||
| <input | ||||||||||||||||||
| className="bg-white rounded-md text-2xl text-center" | ||||||||||||||||||
| defaultValue="" {...register("name")} type='text' placeholder="Type"/> | ||||||||||||||||||
| </form> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <button type='button' onClick={handleClick} className="absolute bottom-3 right-5 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
| </div> | ||||||||||||||||||
|
Comment on lines
+49
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker: Name isn’t saved; Next doesn’t submit the form. The “Next” button advances pages without submitting; onSubmit never runs unless the user presses Enter. Make Next submit the form and persist the name: - <div>
- <form onSubmit={handleSubmit(onSubmit)}>
- <input
- className="bg-white rounded-md text-2xl text-center"
- defaultValue="" {...register("name")} type='text' placeholder="Type"/>
- </form>
- </div>
- <button type='button' onClick={handleClick} className="absolute bottom-3 right-5 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button>
+ <div>
+ <form onSubmit={handleSubmit(onSubmit)}>
+ <input
+ className="bg-white rounded-md text-2xl text-center"
+ {...register("name", { required: true })}
+ type="text"
+ placeholder="Your name"
+ />
+ <button type="submit" className="absolute bottom-3 right-5 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white">
+ next
+ </button>
+ </form>
+ </div>🤖 Prompt for AI Agents |
||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 2){ | ||||||||||||||||||
| return( | ||||||||||||||||||
| <div style={{ | ||||||||||||||||||
| backgroundImage: "radial-gradient(circle, rgba(39, 39, 42, 1) 1.5px, transparent 1px)", | ||||||||||||||||||
| backgroundSize: "20px 20px", | ||||||||||||||||||
| backgroundRepeat: "repeat", | ||||||||||||||||||
| }} | ||||||||||||||||||
| className="flex flex-col justify-center gap-5 p-5 h-screen bg-[#3D3C3C] font-sans text-white"> | ||||||||||||||||||
| <div className="felx flex-row justify-left text-left text-4xl ">Hi ,{localStorage.getItem("name")} Welcome to Pathfinder</div> | ||||||||||||||||||
| <div className="text-left backdrop-blur-sm"> | ||||||||||||||||||
| A powerful Raycast-inspired launcher application built with Tauri and React. PathFinder provides instant access to your most-used tools and information through a beautiful, keyboard-driven interface. And you can access it just my pressing | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <div className="text-5xl text-center text-[#737373]">Ctrl+Shift+Space</div> | ||||||||||||||||||
| <button type="button" onClick={handleClick} className="absolute bottom-3 left-180 flex flex-row justify-center py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
|
Comment on lines
+72
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Avoid reading localStorage during render (optional). Store the name in component state when it’s submitted; it avoids null flashes and makes SSR/testing easier. Example: -const { register, handleSubmit, formState: { errors } } = useForm()
+const { register, handleSubmit } = useForm()
+const [name, setName] = useState("")
...
- const onSubmit = (data) => {
- localStorage.setItem("name", data.name)
- handleClick()
-}
+ const onSubmit = (data) => {
+ setName(data.name)
+ localStorage.setItem("name", data.name)
+ handleClick()
+}
...
-Hi, {localStorage.getItem("name")} Welcome to Pathfinder
+Hi, {name || localStorage.getItem("name") || "there"} Welcome to Pathfinder
🧰 Tools🪛 Biome (2.1.2)[error] 93-93: Provide an explicit type prop for the button element. The default type of a button is submit, which causes the submission of a form when placed inside a (lint/a11y/useButtonType) 🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 3){ | ||||||||||||||||||
|
|
||||||||||||||||||
| return( | ||||||||||||||||||
| <div className="flex flex-col justify-center gap-5 p-5 h-full bg-[#3D3C3C] font-sans text-white"> | ||||||||||||||||||
| <div className="flex flex-row justify-left text-left text-4xl ">Clipboard:</div> | ||||||||||||||||||
| <div className="text-left backdrop-blur-sm"> | ||||||||||||||||||
| A clipboard manager feature that displays all copied items with details like timestamp, size, and usage count. Users can easily view, search, and re-copy any saved entry, making it simple to manage frequently used texts or data efficiently. | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <div className="m-5 px-10 pt-10 rounded-t-xl bg-[#929292]"> | ||||||||||||||||||
| <img src={snapshort1} alt='snapshot1' | ||||||||||||||||||
| className="rounded-t-xl "/> | ||||||||||||||||||
| </div> | ||||||||||||||||||
|
|
||||||||||||||||||
| <div className="text-left mt-5 backdrop-blur-sm"> | ||||||||||||||||||
| A clipboard search feature that lets users quickly find any saved clipboard entry by typing keywords. It filters items in real-time, showing relevant results with details like timestamp, size, and usage, enabling fast retrieval and efficient clipboard management. </div> | ||||||||||||||||||
| <div className="m-5 px-10 pt-10 rounded-t-xl bg-[#929292]"> | ||||||||||||||||||
| <img src={snapshot2} alt='snapshot2' | ||||||||||||||||||
| className="rounded-t-xl "/> | ||||||||||||||||||
| </div> | ||||||||||||||||||
|
|
||||||||||||||||||
| <div className="flex flex-row justify-end"> | ||||||||||||||||||
| <button onClick={handleClick} className=" py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 4){ | ||||||||||||||||||
|
|
||||||||||||||||||
| return( | ||||||||||||||||||
| <div className="flex flex-col justify-center gap-5 p-5 h-full bg-[#3D3C3C] font-sans text-white"> | ||||||||||||||||||
| <div className="flex flex-row justify-left text-left text-4xl ">Online Search:</div> | ||||||||||||||||||
| <div className="text-left backdrop-blur-sm"> | ||||||||||||||||||
| Quick-access web search allows users to instantly search the internet directly from the app. With a streamlined interface, it supports rapid queries, displays results efficiently, and saves frequently used searches, enabling fast, convenient, and productive online information retrieval. </div> | ||||||||||||||||||
| <div className="m-5 px-10 pt-10 rounded-t-xl bg-[#929292]"> | ||||||||||||||||||
| <img src={snapshot3} alt='snapshot1' | ||||||||||||||||||
| className="flex justify-center items-center rounded-t-xl "/> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <div className="flex flex-row justify-end"> | ||||||||||||||||||
| <button onClick={handleClick} className=" py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 5){ | ||||||||||||||||||
|
|
||||||||||||||||||
| return( | ||||||||||||||||||
|
|
||||||||||||||||||
| <div className="flex flex-col justify-center gap-5 p-5 h-full bg-[#3D3C3C] font-sans text-white"> | ||||||||||||||||||
| <div className="flex flex-row justify-left text-left text-4xl ">Open File:</div> | ||||||||||||||||||
| <div className="text-left backdrop-blur-sm"> | ||||||||||||||||||
| A fast file access feature that lets users locate and open files instantly. By typing filenames or keywords, it quickly filters results, showing file paths and details, streamlining workflow and saving time when managing documents, media, or system files. </div> | ||||||||||||||||||
| <div className="m-5 px-10 pt-10 rounded-t-xl bg-[#929292]"> | ||||||||||||||||||
| <img src={snapshort4} alt='snapshot1' className="rounded-t-xl "/> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <div className="flex flex-row justify-end"> | ||||||||||||||||||
| <button onClick={handleClick} className=" py-1 px-3 bg-black rounded-md text-center text-white ">next</button> | ||||||||||||||||||
| </div> </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if(page === 6){ | ||||||||||||||||||
|
|
||||||||||||||||||
| return( | ||||||||||||||||||
| <div className="flex flex-row gap-3 justify-center items-center h-screen w-screen bg-[#3D3C3C]"> | ||||||||||||||||||
| <div className="flex flex-row text-center text-3xl"> | ||||||||||||||||||
| All done, press <div className="flex justify-center items-center px-2 mx-2 border border-b-2 border-r-2 rounded-md bg-zinc-800">esc</div>to continue to | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <div className="py-2 px-3 bg-black rounded-md text-center text-white text-3xl">Pathfinder</div> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| } | ||||||||||||||||||
| export default GuidePage | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Move build‑time tools to devDependencies (optional).
@tailwindcss/vite and tailwindcss are build‑time; consider moving them to devDependencies to reduce install footprint at runtime.
🤖 Prompt for AI Agents
🧩 Analysis chain
Blocker: GuidePage imports @tauri-apps/plugin-store but it’s not declared.
GuidePage.jsx imports Store from @tauri-apps/plugin-store, but package.json lacks that dependency. Builds will fail (or the app will crash at runtime). Decide one path:
If you keep Store, add to dependencies:
"dependencies": { + "@tauri-apps/plugin-store": "^2.4.0", "@tailwindcss/vite": "^4.1.16", "@tauri-apps/api": "^2.9.0", "@tauri-apps/plugin-fs": "^2.4.3",Run to check for mismatches:
🏁 Script executed:
Length of output: 774
Add missing @tauri-apps/plugin-store dependency to package.json.
GuidePage.jsx imports and uses Store from
@tauri-apps/plugin-store(lines 7, 16), but the dependency is missing from package.json. While package-lock.json contains the entry (^2.4.1), package.json must explicitly declare all direct dependencies. Add it to dependencies:"dependencies": { + "@tauri-apps/plugin-store": "^2.4.1", "@tailwindcss/vite": "^4.1.16", "@tauri-apps/api": "^2.9.0", "@tauri-apps/plugin-fs": "^2.4.3",📝 Committable suggestion
🤖 Prompt for AI Agents