feat: list file contents

This commit is contained in:
2025-10-17 21:21:19 +03:00
parent a256c3e16f
commit 9b0d48214b
7 changed files with 73 additions and 49 deletions

View File

@@ -1,11 +1,12 @@
package main package main
import ( import (
"fmt" // "fmt"
"io/fs" "io/fs"
"log" "log"
"os" "os"
"path" "path"
"encoding/base64"
"net/http" "net/http"
@@ -17,7 +18,7 @@ func main() {
router := gin.Default() router := gin.Default()
router.SetTrustedProxies([]string{"127.0.0.1"}) // TODO: fix All origins allowed by default router.SetTrustedProxies([]string{"127.0.0.1"}) // TODO: fix All origins allowed by default
router.Use(cors.Default()) router.Use(cors.Default())
list := listFiles("/Users/madundead/Syncthing/Obsidian/Personal") list := listFiles("/home/madundead/Syncthing/Obsidian/Personal")
router.GET("/api/v1/files", func(c *gin.Context) { router.GET("/api/v1/files", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
@@ -26,6 +27,21 @@ func main() {
}) })
}) })
router.GET("/api/v1/files/:id", func(c *gin.Context) {
id := c.Params.ByName("id")
// value, ok := db[user]
// if ok {
path, _ := base64.StdEncoding.DecodeString(id)
data, _ := os.ReadFile(string(path))
// fmt.Print(string(dat))
c.JSON(http.StatusOK, gin.H{"data": string(data)})
// } else {
// c.JSON(http.StatusOK, gin.H{"user": user, "status": "no value"})
// }
})
if err := router.Run(); err != nil { if err := router.Run(); err != nil {
panic(err) panic(err)
} }
@@ -46,12 +62,12 @@ func listFiles(dir string) []string {
} }
return files return files
} }
//
func readFile(string filePath) []string { // func readFile(string filePath) []string {
content, err := os.ReadFile(filePath) // content, err := os.ReadFile(filePath)
if err != nil { // if err != nil {
fmt.Println("Error reading file:", err) // fmt.Println("Error reading file:", err)
return // return
} // }
return content // return content
} // }

View File

@@ -1,10 +1,10 @@
// import { FilesList } from "./components/FilesList"; // import { FilesList } from "./components/FilesList";
// import { FileContent } from "./components/FileContent"; // import { FileContent } from "./components/FileContent";
import { Root } from "./components/Root"; import { Obi } from "./components/Obi";
import "./index.css"; import "./index.css";
export function App() { export function App() {
return (<Root/ >); return (<Obi />);
} }
export default App; export default App;

View File

@@ -8,7 +8,7 @@ export function FileContent({ filePath }) {
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
try { try {
const response = await fetch("http://localhost:8912/api/v1/files"); // Replace with your API endpoint const response = await fetch("http://localhost:8912/api/v1/files/" + filePath); // Replace with your API endpoint
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
@@ -22,14 +22,14 @@ export function FileContent({ filePath }) {
}; };
fetchData(); fetchData();
}, []); // Empty dependency array ensures this effect runs only once on mount }, [filePath]); // Empty dependency array ensures this effect runs only once on mount
if (loading) return <p>Loading data...</p>; if (loading) return <p>Loading data...</p>;
if (error) return <p>Error: {error.message}</p>; // if (error) return <p>Error: {error.message}</p>;
return ( return (
<div> <div>
<pre>{filePath}</pre> <pre>{data?.data}</pre>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
export function FilesList({ handleFileClick }) { export function FilesList({ handleFileClick }) {
const [data, setData] = useState(null); const [data, setData] = useState(null);
@@ -27,15 +27,11 @@ export function FilesList({ handleFileClick }) {
if (loading) return <p>Loading data...</p>; if (loading) return <p>Loading data...</p>;
if (error) return <p>Error: {error.message}</p>; if (error) return <p>Error: {error.message}</p>;
const onClick = (event) => {
handleFileClick(event.target.value); // Call the parent's callback with the new value
};
const listFiles = data.map(filePath => <li onClick={onClick} className="cursor-pointer">{filePath}</li>);
return ( return (
<div> <div>
{listFiles} {data.map(filePath => (
<li key={filePath} onClick={() => handleFileClick(filePath)} className="cursor-pointer">{filePath}</li>)
)}
</div> </div>
); );
} }

View File

@@ -0,0 +1,24 @@
import { useState } from 'react';
import { FilesList } from "./FilesList";
import { FileContent } from "./FileContent";
import { bytesToBase64 } from "../util/codecs.ts";
export function Obi() {
const [filePath, setFilePath] = useState('');
const handleFileClick = (value) => {
console.log(`Encoded string: [${bytesToBase64(value)}]`);
setFilePath(bytesToBase64(value));
};
return (
<div className="grid text-black grid-cols-1 md:grid-cols-2 h-screen">
<div className="bg-gray-100 p-4 overflow-y-auto">
<FilesList handleFileClick={handleFileClick} />
</div>
<div className="bg-white p-4 overflow-y-auto">
<FileContent filePath={filePath} />
</div>
</div>
);
}

View File

@@ -1,24 +0,0 @@
import React, { useState, useEffect } from 'react';
import { FilesList } from "./FilesList";
import { FileContent } from "./FileContent";
export function Root() {
const [filePath, setFilePath] = useState(''); // State to be shared
const handleFileClick = () => {
setFilePath('1000')
alert("Button clicked!");
};
return (
<div className="flex">
<div className="flex-1">
<FilesList onClick={handleFileClick} />
</div>
<div className="flex-2">
<FileContent filePath={filePath} />
</div>
</div>
);
}

View File

@@ -0,0 +1,12 @@
// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem.
export function base64ToBytes(base64) {
const binString = atob(base64);
return Uint8Array.from(binString, (m) => m.codePointAt(0));
}
// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem.
export function bytesToBase64(string: String) {
const bytes = new TextEncoder().encode(string)
const binString = String.fromCodePoint(...bytes);
return btoa(binString);
}