we have a very basic search system working

This commit is contained in:
2026-02-04 19:30:41 +11:00
parent 33ce1aac67
commit de101e8dfb
6 changed files with 213 additions and 0 deletions

123
screens/search_screen.py Normal file
View File

@@ -0,0 +1,123 @@
from widgets import Navbar
from textual.screen import Screen
from textual.widgets import Input, Select, LoadingIndicator, Static
from textual.containers import HorizontalGroup, ScrollableContainer
from textual.app import ComposeResult
from human_readable import time_delta
from datetime import datetime, timedelta
import requests
class SearchResult(HorizontalGroup):
DEFAULT_CSS = """
SearchResult {
padding: 0 1;
margin: 0 1;
margin-top: 1;
border: tall $surface;
Static {
width: auto;
}
}
"""
def __init__(
self,
author: str,
name: str,
description: str,
is_fork: bool,
updated_at: datetime
):
super().__init__()
self.author = author
self.repo_name = name
self.description = description
self.is_fork = is_fork
self.updated_at = updated_at.replace(tzinfo=None)
def compose(self) -> ComposeResult:
updated_string = time_delta(datetime.now() - self.updated_at)
yield Static(f"[b]{self.author}[/] / [b]{self.repo_name}[/]{' [d]\[[blue]fork[/]]' if self.is_fork else ''}\n{self.description}\n[d]Updated {updated_string} ago")
class SearchScreen(Screen):
DEFAULT_CSS = """
#search-box {
padding: 1;
padding-bottom: 0;
border-bottom: hkey $surface;
#query {
width: 1fr;
}
#search-select {
width: 25;
}
}
"""
def action_search_query(self):
query_input = self.query_one("#query")
loading = self.query_one(LoadingIndicator)
results = self.query_one(ScrollableContainer)
loading.display = True
# send off a request
response = requests.get(
url=self.app.GITEA_HOST + "api/v1/repos/search",
params={
"q": query_input.value,
"limit": 20
}
)
loading.display = False
# error handling
if not response.ok:
self.notify(response.text, title="Error while getting search results:", severity="error")
return
# display results
results.remove_children(SearchResult)
to_mount = []
print(response.json())
for result in response.json()["data"]:
to_mount.append(SearchResult(
result["owner"]["login"],
result["name"],
result["description"],
result["fork"],
datetime.fromisoformat(result["updated_at"])
))
results.mount_all(to_mount)
# self explanitory
query_input.clear()
def on_input_submitted(self, event: Input.Submitted):
if event.input.id == "query":
self.action_search_query()
def on_mount(self):
self.action_search_query()
#self.query_one(LoadingIndicator).display = False
def compose(self) -> ComposeResult:
yield Navbar()
with HorizontalGroup(id="search-box"):
yield Input(placeholder="Search repos...", id="query")
yield Select.from_values([
"Repositories",
], id="search-select", allow_blank=False)
with ScrollableContainer(id="results"):
yield LoadingIndicator()