Add shortcuts, syntax fixes and enhancements.
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import RNS
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, List
|
||||
|
||||
import RNS
|
||||
|
||||
|
||||
@dataclass
|
||||
class Announce:
|
||||
destination_hash: str
|
||||
display_name: Optional[str]
|
||||
display_name: str | None
|
||||
timestamp: int
|
||||
|
||||
class AnnounceService:
|
||||
@@ -14,11 +15,12 @@ class AnnounceService:
|
||||
Service to listen for Reticulum announces and collect them.
|
||||
Calls update_callback whenever a new announce is received.
|
||||
"""
|
||||
|
||||
def __init__(self, update_callback):
|
||||
# Accept all announce aspects
|
||||
self.aspect_filter = "nomadnetwork.node"
|
||||
self.receive_path_responses = True
|
||||
self.announces: List[Announce] = []
|
||||
self.announces: list[Announce] = []
|
||||
self.update_callback = update_callback
|
||||
# Initialize Reticulum transport once
|
||||
try:
|
||||
@@ -48,6 +50,6 @@ class AnnounceService:
|
||||
if self.update_callback:
|
||||
self.update_callback(self.announces)
|
||||
|
||||
def get_announces(self) -> List[Announce]:
|
||||
def get_announces(self) -> list[Announce]:
|
||||
"""Return collected announces."""
|
||||
return self.announces
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import flet as ft
|
||||
from flet import Page, AppView
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import flet as ft
|
||||
from flet import AppView, Page
|
||||
|
||||
from ren_browser.ui.ui import build_ui
|
||||
|
||||
# Current renderer name
|
||||
@@ -68,4 +70,4 @@ def android_dev():
|
||||
def ios_dev():
|
||||
"""Launch Ren Browser in iOS mode via Flet CLI with hot reload."""
|
||||
rc = subprocess.call(["flet", "run", "--ios", "-d", "-r", "ren_browser/app.py"])
|
||||
sys.exit(rc)
|
||||
sys.exit(rc)
|
||||
|
||||
40
ren_browser/controls/shortcuts.py
Normal file
40
ren_browser/controls/shortcuts.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import flet as ft
|
||||
|
||||
|
||||
class Shortcuts:
|
||||
def __init__(self, page: ft.Page, tab_manager):
|
||||
"""Attach keyboard event handler to page and delegate actions to tab_manager and UI."""
|
||||
self.page = page
|
||||
self.tab_manager = tab_manager
|
||||
page.on_keyboard_event = self.on_keyboard
|
||||
|
||||
def on_keyboard(self, e: ft.KeyboardEvent):
|
||||
# Support Ctrl (and Meta on macOS)
|
||||
ctrl = e.ctrl or e.meta
|
||||
if not ctrl:
|
||||
return
|
||||
key = e.key
|
||||
# New tab: Ctrl+T
|
||||
if key.lower() == "t":
|
||||
self.tab_manager._on_add_click(None)
|
||||
# Close tab: Ctrl+W
|
||||
elif key.lower() == "w":
|
||||
self.tab_manager._on_close_click(None)
|
||||
# Focus URL bar: Ctrl+L
|
||||
elif key.lower() == "l":
|
||||
idx = self.tab_manager.manager.index
|
||||
field = self.tab_manager.manager.tabs[idx]["url_field"]
|
||||
field.focus()
|
||||
# Show announces drawer: Ctrl+A
|
||||
elif key.lower() == "a":
|
||||
self.page.drawer.open = True
|
||||
# Cycle through tabs: Ctrl+Tab / Ctrl+Shift+Tab
|
||||
elif key == "Tab":
|
||||
idx = self.tab_manager.manager.index
|
||||
count = len(self.tab_manager.manager.tabs)
|
||||
new_idx = (idx - 1) % count if e.shift else (idx + 1) % count
|
||||
self.tab_manager.select_tab(new_idx)
|
||||
else:
|
||||
return
|
||||
# Apply UI updates
|
||||
self.page.update()
|
||||
@@ -1,17 +1,20 @@
|
||||
from typing import Optional, Dict
|
||||
from pydantic import BaseModel
|
||||
import os, time, threading
|
||||
import threading
|
||||
import time
|
||||
|
||||
import RNS
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class PageRequest(BaseModel):
|
||||
destination_hash: str
|
||||
page_path: str
|
||||
field_data: Optional[Dict] = None
|
||||
field_data: dict | None = None
|
||||
|
||||
class PageFetcher:
|
||||
"""
|
||||
Fetcher to download pages from the Reticulum network.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Initialize Reticulum with default config (singleton)
|
||||
try:
|
||||
|
||||
@@ -1 +1 @@
|
||||
# Add a profiler to the browser.
|
||||
# Add a profiler to the browser.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import flet as ft
|
||||
|
||||
|
||||
def render_micron(content: str) -> ft.Control:
|
||||
"""
|
||||
Render micron markup content to a Flet control placeholder.
|
||||
"""Render micron markup content to a Flet control placeholder.
|
||||
Currently displays raw content.
|
||||
"""
|
||||
return ft.Text(
|
||||
@@ -10,4 +10,4 @@ def render_micron(content: str) -> ft.Control:
|
||||
selectable=True,
|
||||
font_family="monospace",
|
||||
expand=True,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1 +1 @@
|
||||
# Add storage system/management, eg handling downloading files, saving bookmarks, caching, tabs and history.
|
||||
# Add storage system/management, eg handling downloading files, saving bookmarks, caching, tabs and history.
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import flet as ft
|
||||
from types import SimpleNamespace
|
||||
from ren_browser.renderer.plaintext.plaintext import render_plaintext
|
||||
|
||||
import flet as ft
|
||||
|
||||
from ren_browser.renderer.micron.micron import render_micron
|
||||
from ren_browser.renderer.plaintext.plaintext import render_plaintext
|
||||
|
||||
|
||||
class TabsManager:
|
||||
def __init__(self, page: ft.Page):
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import flet as ft
|
||||
from flet import Page
|
||||
from ren_browser.tabs.tabs import TabsManager
|
||||
from ren_browser.renderer.plaintext.plaintext import render_plaintext
|
||||
from ren_browser.renderer.micron.micron import render_micron
|
||||
|
||||
from ren_browser.announces.announces import AnnounceService
|
||||
from ren_browser.controls.shortcuts import Shortcuts
|
||||
from ren_browser.pages.page_request import PageFetcher, PageRequest
|
||||
from ren_browser.renderer.micron.micron import render_micron
|
||||
from ren_browser.renderer.plaintext.plaintext import render_plaintext
|
||||
from ren_browser.tabs.tabs import TabsManager
|
||||
|
||||
|
||||
def build_ui(page: Page):
|
||||
@@ -45,7 +47,11 @@ def build_ui(page: Page):
|
||||
result = page_fetcher.fetch_page(req)
|
||||
except Exception as ex:
|
||||
result = f"Error: {ex}"
|
||||
tab = tab_manager.manager.tabs[idx]
|
||||
# Skip update if tab has been closed or index out of range
|
||||
try:
|
||||
tab = tab_manager.manager.tabs[idx]
|
||||
except IndexError:
|
||||
return
|
||||
# Use micron renderer for .mu pages, fallback to plaintext
|
||||
if req.page_path.endswith(".mu"):
|
||||
new_control = render_micron(result)
|
||||
@@ -78,6 +84,7 @@ def build_ui(page: Page):
|
||||
|
||||
# Dynamic tabs manager for pages
|
||||
tab_manager = TabsManager(page)
|
||||
Shortcuts(page, tab_manager)
|
||||
# Main area: tab bar and content
|
||||
main_area = ft.Column(
|
||||
expand=True,
|
||||
|
||||
Reference in New Issue
Block a user