Added partial-updating links

This commit is contained in:
Mark Qvist
2025-12-29 22:21:51 +01:00
parent f2d0ea9910
commit 11ccc76d93
4 changed files with 79 additions and 49 deletions

View File

@@ -185,6 +185,7 @@ class Browser:
return destination_type
def handle_link(self, link_target, link_data = None):
partial_ids = None
request_data = None
if link_data != None:
link_fields = []
@@ -244,6 +245,10 @@ class Browser:
if len(components) == 2:
destination_type = self.expand_shorthands(components[0])
link_target = components[1]
elif link_target.startswith("p:"):
comps = link_target.split(":")
if len(comps) > 1: partial_ids = comps[1:]
destination_type = "partial"
else:
destination_type = "nomadnetwork.node"
link_target = components[0]
@@ -264,6 +269,9 @@ class Browser:
RNS.log("Passing LXMF link to handler", RNS.LOG_DEBUG)
self.handle_lxmf_link(link_target)
elif destination_type == "partial":
if partial_ids != None and len(partial_ids) > 0: self.handle_partial_updates(partial_ids)
else:
RNS.log("No known handler for destination type "+str(destination_type), RNS.LOG_DEBUG)
self.browser_footer = urwid.Text("Could not open link: "+"No known handler for destination type "+str(destination_type))
@@ -483,13 +491,13 @@ class Browser:
def detect_partials(self):
for w in self.attr_maps:
o = w._original_widget
if hasattr(o, "partial_id"):
RNS.log(f"Found partial: {o.partial_id} / {o.partial_url} / {o.partial_refresh}")
partial = {"id": o.partial_id, "url": o.partial_url, "fields": o.partial_fields, "refresh": o.partial_refresh,
"content": None, "updated": None, "update_requested": None, "request_id": None, "destination": None,
"link": None, "pile": o, "attr_maps": None, "failed": False, "pr_throttle": 0}
if hasattr(o, "partial_hash"):
RNS.log(f"Found partial: {o.partial_hash} / {o.partial_url} / {o.partial_refresh}")
partial = {"hash": o.partial_hash, "id": o.partial_id, "url": o.partial_url, "fields": o.partial_fields,
"refresh": o.partial_refresh, "content": None, "updated": None, "update_requested": None, "request_id": None,
"destination": None, "link": None, "pile": o, "attr_maps": None, "failed": False, "pr_throttle": 0}
self.page_partials[o.partial_id] = partial
self.page_partials[o.partial_hash] = partial
if len(self.page_partials) > 0: self.start_partial_updater()
@@ -560,7 +568,7 @@ class Browser:
partial["link"] = existing_link
break
if not partial["link"]:
if not partial["link"] or partial["link"].status == RNS.Link.CLOSED:
RNS.log(f"Establishing link for partial: {partial_destination_hash} / {path}", RNS.LOG_EXTREME)
identity = RNS.Identity.recall(partial_destination_hash)
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, self.app_name, self.aspects)
@@ -644,6 +652,19 @@ class Browser:
def start_partial_updater(self):
if not self.updater_running: self.update_partials()
def handle_partial_updates(self, partial_ids):
RNS.log(f"Update partials: {partial_ids}")
def job():
for pid in self.page_partials:
try:
partial = self.page_partials[pid]
if partial["id"] in partial_ids:
partial["update_requested"] = time.time()
self.__load_partial(partial)
except Exception as e: RNS.log(f"Error updating page partial: {e}", RNS.LOG_ERROR)
threading.Thread(target=job, daemon=True).start()
def update_partials(self, loop=None, user_data=None):
with self.partial_updater_lock:
def job():
@@ -702,35 +723,25 @@ class Browser:
components = url.split(":")
if len(components) == 1:
if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2:
try:
destination_hash = bytes.fromhex(components[0])
except Exception as e:
raise ValueError("Malformed URL")
try: destination_hash = bytes.fromhex(components[0])
except Exception as e: raise ValueError("Malformed URL")
path = Browser.DEFAULT_PATH
else:
raise ValueError("Malformed URL")
else: raise ValueError("Malformed URL")
elif len(components) == 2:
if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2:
try:
destination_hash = bytes.fromhex(components[0])
except Exception as e:
raise ValueError("Malformed URL")
try: destination_hash = bytes.fromhex(components[0])
except Exception as e: raise ValueError("Malformed URL")
path = components[1]
if len(path) == 0:
path = Browser.DEFAULT_PATH
if len(path) == 0: path = Browser.DEFAULT_PATH
else:
if len(components[0]) == 0:
if self.destination_hash != None:
destination_hash = self.destination_hash
path = components[1]
if len(path) == 0:
path = Browser.DEFAULT_PATH
else:
raise ValueError("Malformed URL")
else:
raise ValueError("Malformed URL")
else:
raise ValueError("Malformed URL")
if len(path) == 0: path = Browser.DEFAULT_PATH
else: raise ValueError("Malformed URL")
else: raise ValueError("Malformed URL")
else: raise ValueError("Malformed URL")
if destination_hash != None and path != None:
if path.startswith("/file/"):

View File

@@ -1302,24 +1302,6 @@ Here is `F00f`_`[a more visible link`72914442a3689add83a09a767963f57c:/page/inde
When links like these are displayed in the built-in browser, clicking on them or activating them using the keyboard will cause the browser to load the specified URL.
>Partials
You can include partials in pages, which will load asynchronously once the page itself has loaded.
`Faaa
`=
`{f64a846313b874ee4a357040807f8c77:/page/partial_1.mu}
`=
``
It's also possible to set an auto-refresh interval for partials. The following partial will update every 10 seconds.
`Faaa
`=
`{f64a846313b874ee4a357040807f8c77:/page/refreshing_partial.mu`10}
`=
``
>Fields & Requests
Nomad Network let's you use simple input fields for submitting data to node-side applications. Submitted data, along with other session variables will be available to the node-side script / program as environment variables.
@@ -1473,6 +1455,36 @@ This line will
``
>Partials
You can include partials in pages, which will load asynchronously once the page itself has loaded.
`Faaa
`=
`{f64a846313b874ee4a357040807f8c77:/page/partial_1.mu}
`=
``
It's also possible to set an auto-refresh interval for partials. Omit or set to 0 to disable. The following partial will update every 10 seconds.
`Faaa
`=
`{f64a846313b874ee4a357040807f8c77:/page/refreshing_partial.mu`10}
`=
``
You can include field values and variables in partial updates, and by setting the `!pid`! variable, you can create links that update one or more specific partials.
`Faaa
`=
Name: `B444`<user_name`>`b
`F38a`[Say hello`p:32]`f
`{f64a846313b874e84a357039807f8c77:/page/hello_partial.mu`0`pid=32|user_name}
`=
``
>Literals
To display literal content, for example source-code, or blocks of text that should not be interpreted by micron, you can use literal blocks, specified by the \\`= tag. Below is the source code of this entire document, presented as a literal block.

View File

@@ -93,6 +93,7 @@ def parse_partial(line):
else:
partial_data = line[0:endpos]
partial_id = None
partial_components = partial_data.split("`")
if len(partial_components) == 1:
partial_url = partial_components[0]
@@ -111,15 +112,21 @@ def parse_partial(line):
partial_fields = ""
partial_refresh = None
if partial_refresh and partial_refresh < 1: partial_refresh = None
if partial_refresh != None and partial_refresh < 1: partial_refresh = None
pf = partial_fields.split("|")
if len(pf) > 0: partial_fields = pf
if len(pf) > 0:
partial_fields = pf
for f in pf:
if f.startswith("pid="):
pcs = f.split("=")
partial_id = pcs[1]
if len(partial_url):
pile = urwid.Pile([urwid.Text(f"")])
partial_descriptor = "|".join(partial_components)
pile.partial_id = RNS.hexrep(RNS.Identity.full_hash(partial_descriptor.encode("utf-8")), delimit=False)
pile.partial_id = partial_id
pile.partial_hash = RNS.hexrep(RNS.Identity.full_hash(partial_descriptor.encode("utf-8")), delimit=False)
pile.partial_url = partial_url
pile.partial_fields = partial_fields
pile.partial_refresh = partial_refresh

View File

@@ -1,7 +1,7 @@
import re
import unicodedata
invalid_rendering = ["🕵️"]
invalid_rendering = ["🕵️", ""]
def strip_modifiers(text):
def process_characters(text):