Feature: Implement read write access checking on Project Directory and report any issues in home page (#5676)

* chore: skeleton to detect read write directories and if we have access to notify user

* chore: adding buttont to easily change project directory

* chore: cleaning up home page error bar layout and button

* fix: adding clearer comments

* fix: ugly console debugging but I need to save off progress

* fix: removing project dir check on empty string

* fix: debug progress to save off listProjects once. Still bugged...

* fix: more hard coded debugging to get project loading optimizted

* fix: yarp, we got another one bois

* fix: cleaning up code

* fix: massive bug comment to warn devs about chokidar bugs

* fix: returning error instead of throwing

* fix: cleaning up PR

* fix: fixed loading the projects when the project directory changes

* fix: remove testing code

* fix: only skip directories if you can access the project directory since we don't need to view them

* fix: unit tests, turning off noisey localhost vitest garbage

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* fix: deleted testing state

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
This commit is contained in:
Kevin Nadro
2025-03-24 14:57:01 -05:00
committed by GitHub
parent 65c455ae7c
commit fdeb2b3f49
17 changed files with 207 additions and 51 deletions

View File

@ -19,19 +19,23 @@ import { LowerRightControls } from 'components/LowerRightControls'
import { ProjectSearchBar, useProjectSearch } from 'components/ProjectSearchBar'
import { Project } from 'lib/project'
import { markOnce } from 'lib/performance'
import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher'
import { useProjectsLoader } from 'hooks/useProjectsLoader'
import { useProjectsContext } from 'hooks/useProjectsContext'
import { commandBarActor } from 'machines/commandBarMachine'
import { useCreateFileLinkQuery } from 'hooks/useCreateFileLinkQueryWatcher'
import { useSettings } from 'machines/appMachine'
import { reportRejection } from 'lib/trap'
// This route only opens in the desktop context for now,
// as defined in Router.tsx, so we can use the desktop APIs and types.
const Home = () => {
const { state, send } = useProjectsContext()
const [projectsLoaderTrigger, setProjectsLoaderTrigger] = useState(0)
const { projectsDir } = useProjectsLoader([projectsLoaderTrigger])
const [readWriteProjectDir, setReadWriteProjectDir] = useState<{
value: boolean
error: unknown
}>({
value: true,
error: undefined,
})
// Keep a lookout for a URL query string that invokes the 'import file from URL' command
useCreateFileLinkQuery((argDefaultValues) => {
@ -66,14 +70,6 @@ const Home = () => {
)
const ref = useRef<HTMLDivElement>(null)
// Re-read projects listing if the projectDir has any updates.
useFileSystemWatcher(
async () => {
setProjectsLoaderTrigger(projectsLoaderTrigger + 1)
},
projectsDir ? [projectsDir] : []
)
const projects = state?.context.projects ?? []
const [searchParams, setSearchParams] = useSearchParams()
const { searchResults, query, setQuery } = useProjectSearch(projects)
@ -91,6 +87,16 @@ const Home = () => {
defaultDirectory: settings.app.projectDirectory.current,
},
})
// Must be a truthy string, not '' or null or undefined
if (settings.app.projectDirectory.current) {
window.electron
.canReadWriteDirectory(settings.app.projectDirectory.current)
.then((res) => {
setReadWriteProjectDir(res)
})
.catch(reportRejection)
}
}, [
settings.app.projectDirectory.current,
settings.projects.defaultProjectName.current,
@ -124,6 +130,18 @@ const Home = () => {
data: { name: project.name || '' },
})
}
/** Type narrowing function of unknown error to a string */
function errorMessage(error: unknown): string {
if (error != undefined && error instanceof Error) {
return error.message
} else if (error && typeof error === 'object') {
return JSON.stringify(error)
} else if (typeof error === 'string') {
return error
} else {
return 'Unknown error'
}
}
return (
<div className="relative flex flex-col h-screen overflow-hidden" ref={ref}>
@ -219,6 +237,22 @@ const Home = () => {
</Link>
.
</p>
{!readWriteProjectDir.value && (
<section>
<div className="flex items-center select-none">
<div className="flex gap-8 items-center justify-between grow bg-destroy-80 text-white py-1 px-4 my-2 rounded-sm grow">
<p className="">{errorMessage(readWriteProjectDir.error)}</p>
<Link
data-testid="project-directory-settings-link"
to={`${PATHS.HOME + PATHS.SETTINGS_USER}#projectDirectory`}
className="py-1 text-white underline underline-offset-2 text-sm"
>
Change Project Directory
</Link>
</div>
</div>
</section>
)}
</section>
<section
data-testid="home-section"