-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
239 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{ | ||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"] | ||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", | ||
"vcs": { | ||
"enabled": false, | ||
"clientKind": "git", | ||
"useIgnoreFile": false | ||
}, | ||
"files": { | ||
"ignoreUnknown": false, | ||
"ignore": [] | ||
}, | ||
"formatter": { | ||
"enabled": true, | ||
"indentStyle": "space", | ||
"indentWidth": 2 | ||
}, | ||
"organizeImports": { | ||
"enabled": true | ||
}, | ||
"linter": { | ||
"enabled": true, | ||
"rules": { | ||
"recommended": true, | ||
"a11y": { | ||
"useAltText": "off", | ||
"noSvgWithoutTitle": "off", | ||
"useKeyWithClickEvents": "off" | ||
} | ||
} | ||
}, | ||
"javascript": { | ||
"formatter": { | ||
"quoteStyle": "double" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export default { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { SVGProps } from "react"; | ||
|
||
function createIcon(svgPath: string) { | ||
return function Icon(props: SVGProps<SVGSVGElement>) { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="currentColor" | ||
aria-hidden="true" | ||
focusable="false" | ||
viewBox="0 0 16 16" | ||
width="16" | ||
height="16" | ||
{...props} | ||
> | ||
<path d={svgPath} /> | ||
</svg> | ||
); | ||
}; | ||
} | ||
export const DirectoryIcon = createIcon( | ||
"M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z", | ||
); | ||
export const DirectoryOpenIcon = createIcon( | ||
"M.513 1.513A1.75 1.75 0 0 1 1.75 1h3.5c.55 0 1.07.26 1.4.7l.9 1.2a.25.25 0 0 0 .2.1H13a1 1 0 0 1 1 1v.5H2.75a.75.75 0 0 0 0 1.5h11.978a1 1 0 0 1 .994 1.117L15 13.25A1.75 1.75 0 0 1 13.25 15H1.75A1.75 1.75 0 0 1 0 13.25V2.75c0-.464.184-.91.513-1.237Z", | ||
); | ||
export const FileIcon = createIcon( | ||
"M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z", | ||
); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import type { DirEntry } from "@tauri-apps/plugin-fs"; | ||
import clsx from "clsx"; | ||
import { DirectoryIcon, FileIcon } from "../assets/icons"; | ||
|
||
export function FilePicker({ | ||
entries, | ||
onSelectFile, | ||
className, | ||
}: { | ||
entries: DirEntry[]; | ||
onSelectFile: (entry: DirEntry) => void; | ||
className?: string; | ||
}) { | ||
return ( | ||
<ul className={clsx("w-full", className)}> | ||
{entries.map((entry) => ( | ||
<FileRow key={entry.name} entry={entry} onClick={onSelectFile} /> | ||
))} | ||
</ul> | ||
); | ||
} | ||
|
||
function FileRow({ | ||
entry, | ||
onClick, | ||
}: { entry: DirEntry; onClick?: (entry: DirEntry) => void }) { | ||
return ( | ||
<li | ||
className="flex items-center p-1 px-2 rounded-md text-xs hover:bg-neutral-200 cursor-pointer" | ||
onClick={() => onClick?.(entry)} | ||
> | ||
{!entry.isDirectory ? ( | ||
<FileIcon className="mr-2 fill-[#59636E]" /> | ||
) : ( | ||
<DirectoryIcon className="mr-2 fill-[#54AEFF]" /> | ||
)} | ||
<span className="truncate cursor-pointer">{entry.name}</span> | ||
</li> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
html, | ||
body { | ||
overscroll-behavior-y: none; /* Stop rubber banding */ | ||
overscroll-behavior-x: none; /* Stop rubber banding */ | ||
user-select: none; /* Disable text selection */ | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,98 @@ | ||
import { open } from '@tauri-apps/plugin-dialog'; | ||
import { readTextFile } from '@tauri-apps/plugin-fs'; | ||
import { useState } from 'react'; | ||
import { open } from "@tauri-apps/plugin-dialog"; | ||
import { type DirEntry, readDir, readTextFile } from "@tauri-apps/plugin-fs"; | ||
import { Button } from "antd"; | ||
import { useEffect, useState } from "react"; | ||
import { FilePicker } from "../components/FilePicker"; | ||
|
||
export default function FileSystemView() { | ||
|
||
const [currentPath, setCurrentPath] = useState<string>( | ||
"/Users/tomhill/Developer/projects/DNAvigate/examples", | ||
); | ||
const [fileContents, setFileContents] = useState<string | null>(null); | ||
const [entries, setEntries] = useState<DirEntry[]>([]); | ||
|
||
const handlePick = (entry: DirEntry) => { | ||
if (entry.name === "..") { | ||
setCurrentPath(currentPath.replace(/\/[^/]+$/, "")); | ||
return; | ||
} | ||
|
||
if (entry.isDirectory) { | ||
setCurrentPath(`${currentPath}/${entry.name}`); | ||
} else { | ||
handleSelectFile(`${currentPath}/${entry.name}`); | ||
} | ||
}; | ||
|
||
const handleFileOpen = async () => { | ||
const path = await open({ | ||
multiple: false, | ||
directory: false, | ||
title: 'Open File', | ||
filters: [{ | ||
name: 'Text Files', | ||
extensions: ['txt'] | ||
}, { | ||
name: "FASTA Files", | ||
extensions: ["fasta", "fa", "fasta.gz", "fa.gz"] | ||
}, { | ||
name: "FASTQ Files", | ||
extensions: ["fastq", "fq", "fastq.gz", "fq.gz"] | ||
}] | ||
title: "Open File", | ||
filters: [ | ||
{ | ||
name: "Text Files", | ||
extensions: ["txt"], | ||
}, | ||
{ | ||
name: "FASTA Files", | ||
extensions: ["fasta", "fa", "fasta.gz", "fa.gz"], | ||
}, | ||
{ | ||
name: "FASTQ Files", | ||
extensions: ["fastq", "fq", "fastq.gz", "fq.gz"], | ||
}, | ||
], | ||
}); | ||
|
||
handleSelectFile(path); | ||
}; | ||
|
||
const handleSelectFile = async (path: string | null) => { | ||
if (!path) { | ||
console.log('No file selected'); | ||
return; | ||
} | ||
|
||
console.log('Selected file:', path); | ||
// TODO: consider how to handle very large files | ||
const contents = await readTextFile(path); | ||
setFileContents(contents); | ||
}; | ||
|
||
async function getFiles(path: string) { | ||
const contents = await readDir(path); | ||
setEntries(contents); | ||
} | ||
|
||
// biome-ignore lint/correctness/useExhaustiveDependencies: not getFiles | ||
useEffect(() => { | ||
getFiles(currentPath); | ||
}, [currentPath]); | ||
|
||
const sortedEntries = [ | ||
{ name: "..", isDirectory: true, isSymlink: false, isFile: false }, | ||
...entries | ||
.sort((a, b) => { | ||
// Sort directories before files | ||
if (a.isDirectory !== b.isDirectory) { | ||
return a.isDirectory ? -1 : 1; | ||
} | ||
// If both are directories or both are files, sort by name | ||
return a.name.localeCompare(b.name); | ||
}) | ||
.filter((entry) => !entry.name.startsWith(".")), // Hide hidden files | ||
]; | ||
|
||
return ( | ||
<div> | ||
<h1>File System</h1> | ||
<p>File System view</p> | ||
<button onClick={handleFileOpen}>Open File</button> | ||
{fileContents && <pre>{fileContents}</pre>} | ||
<div className="flex justify-between border-t border-neutral-200"> | ||
<div className="w-60 border-r border-neutral-200 h-screen p-2"> | ||
<p className="text-sm">Files</p> | ||
<FilePicker entries={sortedEntries} onSelectFile={handlePick} /> | ||
<Button size="small" onClick={handleFileOpen}> | ||
Open File | ||
</Button> | ||
</div> | ||
<div className="overflow-y-scroll h-screen w-full text-select"> | ||
{fileContents && <pre className="text-xs">{fileContents}</pre>} | ||
</div> | ||
</div> | ||
) | ||
} | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('tailwindcss').Config} */ | ||
export default { | ||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], | ||
theme: { | ||
extend: {}, | ||
}, | ||
plugins: [], | ||
}; |