Repos / mcross / d3c8cd3d31
commit d3c8cd3d31ef663c9323801251d8f07d6f8ef795
Author: Bùi Thành Nhân <hi@imnhan.com>
Date:   Sun May 17 13:03:34 2020 +0700

    status bar

diff --git a/README.md b/README.md
index 526ecb2..558be81 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,8 @@
 
 ![](https://p.caophim.net/87.png)
 
-Happy-path surfing already works.
-The UX is still terrible though (see feature checklist below).
-I'm still figuring out stuff as I go.
+Surfing plaintext and gemini content is already working well.
+See feature checklist below for more details.
 
 
 # Installation
@@ -50,7 +49,7 @@ # Feature checklist
 - [x] back-forward buttons
 - [x] handle redirects
 - [x] non-blocking I/O using curio
-- [ ] more visual indicators - maybe a status bar at the bottom
+- [x] more visual indicators: waiting cursor, status bar
 - [x] parse gemini's advanced line types
 - [ ] properly handle mime types (gemini/plaintext/binary)
 - [ ] configurable document styling
diff --git a/pyproject.toml b/pyproject.toml
index 89bc860..7899a5f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "mcross"
-version = "0.5.0"
+version = "0.5.1"
 description = "Do you remember www?"
 authors = ["nhanb <hi@imnhan.com>"]
 license = "MIT"
diff --git a/src/mcross/gui/controller.py b/src/mcross/gui/controller.py
index 1e90538..4cea4c4 100644
--- a/src/mcross/gui/controller.py
+++ b/src/mcross/gui/controller.py
@@ -1,3 +1,4 @@
+import logging
 import traceback
 from ssl import SSLCertVerificationError
 from tkinter import TclError, Tk, messagebox
@@ -13,6 +14,8 @@
 from .model import Model
 from .view import WAITING_CURSOR, View
 
+statusbar_logger = logging.getLogger("statusbar")
+
 
 class Controller:
     def __init__(self):
@@ -102,9 +105,13 @@ async def link_click_callback(self, raw_url):
             )
 
     async def visit_link(self, url: GeminiUrl):
-        resp = await self.load_page(url)
-        self.model.history.visit(resp.url)
-        self.view.render_page()
+        try:
+            resp = await self.load_page(url)
+            self.model.history.visit(resp.url)
+            self.view.render_page()
+        except ConnectionError as e:
+            statusbar_logger.info(str(e))
+            raise
 
     async def back_callback(self):
         self.model.history.go_back()
@@ -117,9 +124,15 @@ async def forward_callback(self):
         self.view.render_page()
 
     async def load_page(self, url: GeminiUrl):
-        # print("Requesting", url)
+        statusbar_logger.info(f"Requesting {url}...")
         resp = await get(url)
-        # print("Received", resp)
+        statusbar_logger.info(f"{resp.status} {resp.meta}")
+
+        async def clear_status_bar_later():
+            await curio.sleep(2)
+            statusbar_logger.info("")
+
+        await curio.spawn(clear_status_bar_later(), daemon=True)
 
         if resp.status.startswith("2"):
             self.model.update_content(resp.body.decode())
diff --git a/src/mcross/gui/view.py b/src/mcross/gui/view.py
index c8d5244..6fae076 100644
--- a/src/mcross/gui/view.py
+++ b/src/mcross/gui/view.py
@@ -1,3 +1,4 @@
+import logging
 import sys
 from tkinter import Text, Tk, font, ttk
 
@@ -44,6 +45,16 @@ def pick_font(names):
     return picked
 
 
+def register_status_bar_log_handler(status_bar: ttk.Label):
+    class StatusBarHandler(logging.Handler):
+        def emit(self, record):
+            status_bar.config(text=self.format(record))
+
+    logger = logging.getLogger("statusbar")
+    logger.setLevel(logging.INFO)
+    logger.addHandler(StatusBarHandler())
+
+
 class View:
     model: Model
     address_bar: ttk.Entry
@@ -51,6 +62,7 @@ class View:
     back_btn: ttk.Button
     forward_btn: ttk.Button
     text: Text
+    status_bar: ttk.Label
 
     allow_changing_cursor = True
 
@@ -70,6 +82,13 @@ def __init__(self, root: Tk, model: Model):
         row2 = ttk.Frame(root)
         row2.pack(fill="both", expand=True)
 
+        # third row - status bar
+        status_bar = ttk.Label(root)
+        self.status_bar = status_bar
+        status_bar.config(justify="right")
+        status_bar.pack(fill="x")
+        register_status_bar_log_handler(status_bar)
+
         # Back/Forward buttons
         back_btn = ttk.Button(
             row1, text="🡄", width=3, command=lambda: self.back_callback()
@@ -124,8 +143,9 @@ def __init__(self, root: Tk, model: Model):
             pady=5,
             # hide blinking insertion cursor:
             insertontime=0,
-            # prevent verticle scrollbar from disappearing when window gets small:
+            # prevent text widget from pushing scrollbar/status bar out of the window:
             width=1,
+            height=1,
         )
         text.pack(side="left", fill="both", expand=True)
         text.tag_config("link", foreground="brown")