|
|
@ -1,21 +1,79 @@
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
|
|
from textual.app import App, ComposeResult
|
|
|
|
from textual.app import App, ComposeResult
|
|
|
|
from textual.widgets import Header, Input, Static, Button
|
|
|
|
from textual.widgets import Header, Input, Static, Button
|
|
|
|
from textual.containers import Horizontal
|
|
|
|
from textual.containers import Horizontal, Container
|
|
|
|
from textual.validation import Number
|
|
|
|
from textual.validation import Number
|
|
|
|
|
|
|
|
from textual.command import DiscoveryHit, Provider, Hits, Hit
|
|
|
|
|
|
|
|
from textual.reactive import reactive
|
|
|
|
|
|
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
from BingoBoard import BingoBoard
|
|
|
|
from BingoBoard import BingoBoard
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MESSAGE = '''
|
|
|
|
|
|
|
|
Be excellent to each other!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Made with :red_heart: by Panki
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[@click="app.open_link('https://tty0.social/@panki')"]Mastodon:[/] tty0.social/@panki
|
|
|
|
|
|
|
|
[@click="app.open_link('https://git.theresno.cloud/panki/bingo-cli')"]Source:[/] git.theresno.cloud/panki/bingo-cli
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Built using [@click="app.open_link('https://textual.textualize.io/')"]Textual[/]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AboutCommand(Provider):
|
|
|
|
|
|
|
|
async def discover(self) -> Hits:
|
|
|
|
|
|
|
|
yield DiscoveryHit(display='About', command=self.app.action_toggle_sidebar, help='Link to repo etc.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def show_about(self):
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def search(self, query: str) -> Hits:
|
|
|
|
|
|
|
|
matcher = self.matcher(query)
|
|
|
|
|
|
|
|
command = "About"
|
|
|
|
|
|
|
|
score = matcher.match(command)
|
|
|
|
|
|
|
|
if score > 0:
|
|
|
|
|
|
|
|
yield Hit(score, matcher.highlight(command), self.app.action_toggle_sidebar, 'Link to repo etc.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Sidebar(Container):
|
|
|
|
|
|
|
|
def compose(self) -> ComposeResult:
|
|
|
|
|
|
|
|
yield Static('CCC Bingo', classes='title')
|
|
|
|
|
|
|
|
yield Static(MESSAGE, classes='message')
|
|
|
|
|
|
|
|
self.button = Button('< Back', variant='primary', classes='btn_sidebar')
|
|
|
|
|
|
|
|
self.button.disabled = True
|
|
|
|
|
|
|
|
yield self.button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
|
|
|
|
|
|
print('sidebar button press')
|
|
|
|
|
|
|
|
self.app.action_toggle_sidebar()
|
|
|
|
|
|
|
|
|
|
|
|
class BingoApp(App):
|
|
|
|
class BingoApp(App):
|
|
|
|
'''A Textual app to run a Bingo board.'''
|
|
|
|
'''A Textual app to run a Bingo board.'''
|
|
|
|
CSS_PATH = "bingo.tcss"
|
|
|
|
CSS_PATH = "bingo.tcss"
|
|
|
|
|
|
|
|
COMMANDS = App.COMMANDS | {AboutCommand}
|
|
|
|
|
|
|
|
AUTO_FOCUS = 'Input'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
show_sidebar = reactive(False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def action_toggle_sidebar(self) -> None:
|
|
|
|
|
|
|
|
print('sidebar toggle')
|
|
|
|
|
|
|
|
sidebar = self.query_one(Sidebar)
|
|
|
|
|
|
|
|
self.set_focus(None)
|
|
|
|
|
|
|
|
if sidebar.has_class("-hidden"):
|
|
|
|
|
|
|
|
sidebar.remove_class("-hidden")
|
|
|
|
|
|
|
|
sidebar.button.disabled = False
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if sidebar.query("*:focus"):
|
|
|
|
|
|
|
|
self.screen.set_focus(None)
|
|
|
|
|
|
|
|
sidebar.add_class("-hidden")
|
|
|
|
|
|
|
|
sidebar.button.disabled = True
|
|
|
|
|
|
|
|
|
|
|
|
def compose(self) -> ComposeResult:
|
|
|
|
def compose(self) -> ComposeResult:
|
|
|
|
'''Create child widgets for the app.'''
|
|
|
|
'''Create child widgets for the app.'''
|
|
|
|
yield Header()
|
|
|
|
yield Sidebar(classes="-hidden")
|
|
|
|
|
|
|
|
yield Header(show_clock=True)
|
|
|
|
yield BingoDisplay()
|
|
|
|
yield BingoDisplay()
|
|
|
|
|
|
|
|
|
|
|
|
def on_mount(self) -> None:
|
|
|
|
def on_mount(self) -> None:
|
|
|
|