mirror of
https://git.0x0.st/mia/0x0.git
synced 2024-11-23 09:17:11 +01:00
ModUI: Update for Textual 0.54.0
This commit is contained in:
parent
8a912e8744
commit
3330a85c2c
3 changed files with 56 additions and 53 deletions
16
mod.css
16
mod.css
|
@ -1,5 +1,6 @@
|
||||||
#ftable {
|
#ftable {
|
||||||
width: 1fr;
|
width: 1fr;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#infopane {
|
#infopane {
|
||||||
|
@ -10,7 +11,7 @@
|
||||||
|
|
||||||
#finfo {
|
#finfo {
|
||||||
background: $boost;
|
background: $boost;
|
||||||
height: 12;
|
height: 14;
|
||||||
width: 1fr;
|
width: 1fr;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
|
@ -27,20 +28,9 @@
|
||||||
width: 1fr;
|
width: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filter_container {
|
|
||||||
height: auto;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#filter_label {
|
|
||||||
content-align: right middle;
|
|
||||||
height: 1fr;
|
|
||||||
width: 20%;
|
|
||||||
margin: 0 1 0 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#filter_input {
|
#filter_input {
|
||||||
width: 1fr;
|
width: 1fr;
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification {
|
Notification {
|
||||||
|
|
49
mod.py
49
mod.py
|
@ -5,7 +5,7 @@ from sys import stdout
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from textual.app import App, ComposeResult
|
from textual.app import App, ComposeResult
|
||||||
from textual.widgets import DataTable, Header, Footer, TextLog, Static, Input
|
from textual.widgets import DataTable, Header, Footer, RichLog, Static, Input
|
||||||
from textual.containers import Horizontal, Vertical
|
from textual.containers import Horizontal, Vertical
|
||||||
from textual.screen import Screen
|
from textual.screen import Screen
|
||||||
from textual import log
|
from textual import log
|
||||||
|
@ -20,13 +20,13 @@ fhost_app.app_context().push()
|
||||||
class NullptrMod(Screen):
|
class NullptrMod(Screen):
|
||||||
BINDINGS = [
|
BINDINGS = [
|
||||||
("q", "quit_app", "Quit"),
|
("q", "quit_app", "Quit"),
|
||||||
("f1", "filter(1, 'Lookup name:')", "Lookup name"),
|
("f1", "filter(1, 'Name')", "Lookup name"),
|
||||||
("f2", "filter(2, 'Filter IP address:')", "Filter IP"),
|
("f2", "filter(2, 'IP address')", "Filter IP"),
|
||||||
("f3", "filter(3, 'Filter MIME Type:')", "Filter MIME"),
|
("f3", "filter(3, 'MIME Type')", "Filter MIME"),
|
||||||
("f4", "filter(4, 'Filter extension:')", "Filter Ext."),
|
("f4", "filter(4, 'Extension')", "Filter Ext."),
|
||||||
("f5", "refresh", "Refresh"),
|
("f5", "refresh", "Refresh"),
|
||||||
("f6", "filter_clear", "Clear filter"),
|
("f6", "filter_clear", "Clear filter"),
|
||||||
("f7", "filter(5, 'Filter user agent:')", "Filter UA"),
|
("f7", "filter(5, 'User agent')", "Filter UA"),
|
||||||
("r", "remove_file(False)", "Remove file"),
|
("r", "remove_file(False)", "Remove file"),
|
||||||
("ctrl+r", "remove_file(True)", "Ban file"),
|
("ctrl+r", "remove_file(True)", "Ban file"),
|
||||||
("p", "ban_ip(False)", "Ban IP"),
|
("p", "ban_ip(False)", "Ban IP"),
|
||||||
|
@ -42,29 +42,28 @@ class NullptrMod(Screen):
|
||||||
ftable.watch_query(None, None)
|
ftable.watch_query(None, None)
|
||||||
|
|
||||||
def action_filter_clear(self):
|
def action_filter_clear(self):
|
||||||
self.query_one("#filter_container").display = False
|
self.finput.display = False
|
||||||
ftable = self.query_one("#ftable")
|
ftable = self.query_one("#ftable")
|
||||||
ftable.focus()
|
ftable.focus()
|
||||||
ftable.query = ftable.base_query
|
ftable.query = ftable.base_query
|
||||||
|
|
||||||
def action_filter(self, fcol: int, label: str):
|
def action_filter(self, fcol: int, label: str):
|
||||||
self.query_one("#filter_label").update(label)
|
self.finput.placeholder = label
|
||||||
finput = self.query_one("#filter_input")
|
self.finput.display = True
|
||||||
|
self.finput.focus()
|
||||||
self.filter_col = fcol
|
self.filter_col = fcol
|
||||||
self.query_one("#filter_container").display = True
|
|
||||||
finput.focus()
|
|
||||||
self._refresh_layout()
|
self._refresh_layout()
|
||||||
|
|
||||||
if self.current_file:
|
if self.current_file:
|
||||||
match fcol:
|
match fcol:
|
||||||
case 1: finput.value = ""
|
case 1: self.finput.value = ""
|
||||||
case 2: finput.value = self.current_file.addr
|
case 2: self.finput.value = self.current_file.addr
|
||||||
case 3: finput.value = self.current_file.mime
|
case 3: self.finput.value = self.current_file.mime
|
||||||
case 4: finput.value = self.current_file.ext
|
case 4: self.finput.value = self.current_file.ext
|
||||||
case 5: finput.value = self.current_file.ua or ""
|
case 5: self.finput.value = self.current_file.ua or ""
|
||||||
|
|
||||||
def on_input_submitted(self, message: Input.Submitted) -> None:
|
def on_input_submitted(self, message: Input.Submitted) -> None:
|
||||||
self.query_one("#filter_container").display = False
|
self.finput.display = False
|
||||||
ftable = self.query_one("#ftable")
|
ftable = self.query_one("#ftable")
|
||||||
ftable.focus()
|
ftable.focus()
|
||||||
|
|
||||||
|
@ -122,13 +121,13 @@ class NullptrMod(Screen):
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Header()
|
yield Header()
|
||||||
yield Horizontal(
|
yield Horizontal(
|
||||||
FileTable(id="ftable", zebra_stripes=True),
|
FileTable(id="ftable", zebra_stripes=True, cursor_type="row"),
|
||||||
Vertical(
|
Vertical(
|
||||||
DataTable(id="finfo", show_header=False),
|
DataTable(id="finfo", show_header=False, cursor_type="none"),
|
||||||
MpvWidget(id="mpv"),
|
MpvWidget(id="mpv"),
|
||||||
TextLog(id="ftextlog"),
|
RichLog(id="ftextlog", auto_scroll=False),
|
||||||
id="infopane"))
|
id="infopane"))
|
||||||
yield Horizontal(Static("Filter:", id="filter_label"), Input(id="filter_input"), id="filter_container")
|
yield Input(id="filter_input")
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
|
@ -143,6 +142,8 @@ class NullptrMod(Screen):
|
||||||
self.mpvw = self.query_one("#mpv")
|
self.mpvw = self.query_one("#mpv")
|
||||||
self.ftlog = self.query_one("#ftextlog")
|
self.ftlog = self.query_one("#ftextlog")
|
||||||
|
|
||||||
|
self.finput = self.query_one("#filter_input")
|
||||||
|
|
||||||
self.mimehandler = mime.MIMEHandler()
|
self.mimehandler = mime.MIMEHandler()
|
||||||
self.mimehandler.register(mime.MIMECategory.Archive, self.handle_libarchive)
|
self.mimehandler.register(mime.MIMECategory.Archive, self.handle_libarchive)
|
||||||
self.mimehandler.register(mime.MIMECategory.Text, self.handle_text)
|
self.mimehandler.register(mime.MIMECategory.Text, self.handle_text)
|
||||||
|
@ -261,13 +262,11 @@ class NullptrMod(Screen):
|
||||||
])
|
])
|
||||||
|
|
||||||
self.mpvw.stop_mpv(True)
|
self.mpvw.stop_mpv(True)
|
||||||
self.ftlog.remove()
|
self.ftlog.clear()
|
||||||
self.query_one("#infopane").mount(TextLog(id="ftextlog"))
|
|
||||||
self.ftlog = self.query_one("#ftextlog")
|
|
||||||
|
|
||||||
if f.getpath().is_file():
|
if f.getpath().is_file():
|
||||||
self.mimehandler.handle(f.mime, f.ext)
|
self.mimehandler.handle(f.mime, f.ext)
|
||||||
self.ftlog.scroll_home(animate=False)
|
self.ftlog.scroll_to(x=0, y=0, animate=False)
|
||||||
|
|
||||||
class NullptrModApp(App):
|
class NullptrModApp(App):
|
||||||
CSS_PATH = "mod.css"
|
CSS_PATH = "mod.css"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from textual.widgets import DataTable, Static
|
from textual.widgets import DataTable, Static
|
||||||
from textual.reactive import Reactive
|
from textual.reactive import Reactive
|
||||||
from textual.message import Message, MessageTarget
|
from textual.message import Message
|
||||||
from textual import events, log
|
from textual import events, log
|
||||||
from jinja2.filters import do_filesizeformat
|
from jinja2.filters import do_filesizeformat
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ class FileTable(DataTable):
|
||||||
self.query = self.base_query
|
self.query = self.base_query
|
||||||
|
|
||||||
class Selected(Message):
|
class Selected(Message):
|
||||||
def __init__(self, sender: MessageTarget, f: File) -> None:
|
def __init__(self, f: File) -> None:
|
||||||
self.file = f
|
self.file = f
|
||||||
super().__init__(sender)
|
super().__init__()
|
||||||
|
|
||||||
def watch_order_col(self, old, value) -> None:
|
def watch_order_col(self, old, value) -> None:
|
||||||
self.watch_query(None, None)
|
self.watch_query(None, None)
|
||||||
|
@ -44,25 +44,39 @@ class FileTable(DataTable):
|
||||||
)
|
)
|
||||||
|
|
||||||
if (self.query):
|
if (self.query):
|
||||||
self.clear()
|
|
||||||
order = FileTable.colmap[self.order_col]
|
order = FileTable.colmap[self.order_col]
|
||||||
q = self.query
|
q = self.query
|
||||||
if order: q = q.order_by(order.desc() if self.order_desc else order, File.id)
|
if order: q = q.order_by(order.desc() if self.order_desc else order, File.id)
|
||||||
self.add_rows(map(fmt_file, q.limit(self.limit)))
|
qres = list(map(fmt_file, q.limit(self.limit)))
|
||||||
|
|
||||||
def _scroll_cursor_in_to_view(self, animate: bool = False) -> None:
|
ri = 0
|
||||||
region = self._get_cell_region(self.cursor_row, 0)
|
row = self.cursor_coordinate.row
|
||||||
spacing = self._get_cell_border()
|
if row < self.row_count and row >= 0:
|
||||||
self.scroll_to_region(region, animate=animate, spacing=spacing)
|
ri = int(self.get_row_at(row)[0])
|
||||||
|
|
||||||
async def watch_cursor_cell(self, old, value) -> None:
|
self.clear()
|
||||||
super().watch_cursor_cell(old, value)
|
self.add_rows(qres)
|
||||||
if value[0] < len(self.data) and value[0] >= 0:
|
|
||||||
f = File.query.get(int(self.data[value[0]][0]))
|
for i, v in enumerate(qres):
|
||||||
await self.emit(self.Selected(self, f))
|
if int(v[0]) == ri:
|
||||||
|
self.move_cursor(row=i)
|
||||||
|
break
|
||||||
|
|
||||||
|
self.on_selected()
|
||||||
|
|
||||||
|
def on_selected(self) -> Selected:
|
||||||
|
row = self.cursor_coordinate.row
|
||||||
|
if row < self.row_count and row >= 0:
|
||||||
|
f = File.query.get(int(self.get_row_at(row)[0]))
|
||||||
|
self.post_message(self.Selected(f))
|
||||||
|
|
||||||
|
def watch_cursor_coordinate(self, old, value) -> None:
|
||||||
|
super().watch_cursor_coordinate(old, value)
|
||||||
|
if old != value:
|
||||||
|
self.on_selected()
|
||||||
|
|
||||||
def on_click(self, event: events.Click) -> None:
|
def on_click(self, event: events.Click) -> None:
|
||||||
super().on_click(event)
|
|
||||||
meta = self.get_style_at(event.x, event.y).meta
|
meta = self.get_style_at(event.x, event.y).meta
|
||||||
if meta:
|
if meta:
|
||||||
if meta["row"] == -1:
|
if meta["row"] == -1:
|
||||||
|
|
Loading…
Reference in a new issue