file tree kinda working :D

This commit is contained in:
2026-02-07 21:04:37 +11:00
parent 16afb5e2d0
commit 92990e7d4b
4 changed files with 175 additions and 109 deletions

View File

@@ -1,6 +1,6 @@
from textual.screen import Screen
from textual.app import ComposeResult
from textual.widgets import Input, Select, TextArea, LoadingIndicator, Static, DataTable, ContentSwitcher, Tabs, Tab, Button, Markdown
from textual.widgets import Input, Tree, Select, TextArea, LoadingIndicator, Static, DataTable, ContentSwitcher, Tabs, Tab, Button, Markdown
from textual.containers import VerticalGroup, Vertical, HorizontalGroup, Right
from textual import work
@@ -9,6 +9,8 @@ from widgets import Navbar, RepoDirectoryTree
from datetime import datetime
from human_readable import time_delta
from util import get_icon_from_name_and_type
import requests, asyncio, base64
@@ -21,81 +23,9 @@ class RepoViewScreen(Screen):
self.repo_name = repo_name
self.current_dir = "."
self.readme_loaded = False
def get_icon_from_name_and_type(self, file_name: str, is_folder: bool):
# nerd font icons my beloved
if not is_folder:
match file_name:
case "Makefile":
return "\ue673"
case "Dockerfile" | "Containerfile":
return "\ue7b0"
case "requirements.txt":
return "\ue73c"
case "LICENSE":
return "\uf1f9"
case "Cargo.lock" | "Cargo.toml":
return "\ue7a8"
if "." in file_name:
extension = file_name[file_name.find(".")+1:]
match extension:
case 'c' | 'h':
return "\ue61e"
case 'cpp':
return "\ue61d"
case 'py':
return "\ue73c"
case 'js':
return "\ue781"
case 'json':
return "\ueb0f"
case 'gitignore' | 'gitmodules':
return "\ue702"
case 'html' | 'htm':
return "\ue736"
case 'css' | 'tcss':
return "\ue749"
case 'svg':
return "\ue698"
case 'ico':
return "\ue623"
case 'go':
return "\ue65e"
case 'rs':
return "\ue7a8"
case 'grnd' | 'sols':
return "\uf44f"
case 'md':
return "\ueb1d"
case 'fish':
return "\uee41"
case 'sh':
return "\ue760"
case 'bat':
return "\ue70f"
case 'png' | 'jpg' | 'jpeg' | 'avif':
return "\uf03e"
case 'lua':
return "\ue620"
case 'zip' | 'tar' | 'gz' | "7z":
return "\ue6aa"
case "rb":
return "\ue605"
case "kt":
return "\ue634"
case "java":
return "\ue738"
case _: # unrecognized file type
return "\uf15b"
else: # has no dot in the name
return "\uf15b"
else: # is a folder
return "\ue5ff"
self.most_recent_commit = None
@work(thread=False, exclusive=True)
#@work(thread=False, exclusive=True)
async def action_view_file(self, path: str, type: str):
if type == "dir":
self.current_dir = path
@@ -163,7 +93,8 @@ class RepoViewScreen(Screen):
loading.display = False
file_screen.display = True
@work(thread=True, exclusive=True)
def show_directory(self, path: str):
files: DataTable = self.query_one("#files")
self.query_one("#file-screen").display = False
@@ -178,18 +109,6 @@ class RepoViewScreen(Screen):
readme: Markdown = self.query_one("#readme")
readme.display = path == "."
# get files in dir
files_response = requests.get(
self.app.GITEA_HOST + f"api/v1/repos/{self.owner_name}/{self.repo_name}/contents-ext/{path}",
params={
"includes": "commit_metadata,commit_message"
}
)
if not files_response.ok:
self.notify(files_response.text, title="Failed to get files:", severity="error")
return
print("Getting most recent commit...")
# get most recent commit
@@ -205,12 +124,27 @@ class RepoViewScreen(Screen):
self.notify(commits_response.text, title="Failed to get most recent commit:", severity="error")
return
most_recent_commit = commits_response.json()[0]
self.most_recent_commit = commits_response.json()[0]
files.add_columns(
f"[b]{most_recent_commit["commit"]["author"]["name"]}[/]",
f"[r]{most_recent_commit["sha"][:10]}[/]",
f"[d]{most_recent_commit["commit"]["message"]}"
f"[b]{self.most_recent_commit["commit"]["author"]["name"]}[/]",
f"[r]{self.most_recent_commit["sha"][:10]}[/]",
f"[d]{self.most_recent_commit["commit"]["message"]}"
)
self.query_one(RepoDirectoryTree).load_repo_tree()
# get files in dir
files_response = requests.get(
self.app.GITEA_HOST + f"api/v1/repos/{self.owner_name}/{self.repo_name}/contents-ext/{path}",
params={
"includes": "commit_metadata,commit_message"
}
)
if not files_response.ok:
self.notify(files_response.text, title="Failed to get files:", severity="error")
return
print("Getting root commits...")
@@ -223,7 +157,7 @@ class RepoViewScreen(Screen):
if path != ".":
previous_dir = self.current_dir[:self.current_dir.rfind("/")]
rows.append((
f"[cyan]{self.get_icon_from_name_and_type("..", True)}[/] [@click=screen.view_file('{previous_dir}','dir')]..[/]",
f"[cyan]{get_icon_from_name_and_type("..", True)}[/] [@click=screen.view_file('{previous_dir}','dir')]..[/]",
"",
""
))
@@ -232,7 +166,7 @@ class RepoViewScreen(Screen):
commit_created_at = datetime.fromisoformat(file["last_committer_date"]).replace(tzinfo=None)
rows.append((
f"[cyan]{self.get_icon_from_name_and_type(file["name"], file["type"] != "file")}[/] [@click=screen.view_file('{self.current_dir}/{file["name"]}','{file["type"]}')]{file["name"]}[/]",
f"[cyan]{get_icon_from_name_and_type(file["name"], file["type"] != "file")}[/] [@click=screen.view_file('{self.current_dir}/{file["name"]}','{file["type"]}')]{file["name"]}[/]",
f"[d]{file["last_commit_message"]}[/]",
f"[d]Updated {time_delta(datetime.now() - commit_created_at)} ago[/]"
))
@@ -259,10 +193,15 @@ class RepoViewScreen(Screen):
files.display = True
loading.display = False
@work(thread=True, exclusive=True)
def on_mount(self):
print("Getting files...")
self.show_directory(self.current_dir)
async def on_tree_node_selected(self, event: Tree.NodeSelected):
path = event.node.data["path"]
if not path.endswith("/"): # ignore when we click on a directory
await self.action_view_file(path, "file")
def compose(self) -> ComposeResult: