From fbd505a647c316eab6e5c3661d038bf02ca078fd Mon Sep 17 00:00:00 2001 From: 0xmrtt <0xmrtt@proton.me> Date: Mon, 6 Apr 2026 17:18:35 +0200 Subject: [PATCH] Remove image handling and add Nix docs --- README.md | 35 +++++---- src/widgets/item.blp | 7 +- src/widgets/item.py | 168 ++++++++++++++----------------------------- 3 files changed, 75 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index fad1117..988b7ac 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,6 @@
-
-
-
-
-
@@ -49,6 +43,14 @@ Documentation is available [here](https://bavarder.codeberg.page)
## Installation
+### Nix
+
+Nix is used to develop Bavarder, there is also a Nix flake available at [flake.nix](./flake.nix). You can run Bavarder without installing it by running
+
+``` shell
+nix run github:Bavarder/Bavarder
+```
+
### Flatpak
You can either use your GNOME Software and search for "Bavarder" or you can run
@@ -67,6 +69,18 @@ curl -s -o bavarder.flatpak https://codeberg.org/api/packages/Bavarder/generic/B
#### From Source
+### Nix
+
+Just clone the repo and run `nix develop` and you will be in a shell with all the dependencies installed, you can then run `nix run` to run the app or `nix build` to build it
+
+``` shell
+git clone https://github.com/Bavarder/Bavarder # or https://codeberg.org/Bavarder/Bavarder
+cd Bavarder
+nix develop
+nix run # Run the app
+nix build # Build the app
+```
+
### Flatpak-builder
Clone the repo and run `flatpak-builder`
@@ -115,12 +129,3 @@ You can translate Bavarder using [Codeberg Translate](https://translate.codeberg
## About the name
Bavarder is a french word, the definiton of Bavarder is "Parler abondamment de choses sans grande portée" (Talking a lot about things that don't matter) (Larousse) which can be translated by Chit-Chat (informal conversation about matters that are not important). For non-french speakers, Bavarder can be hard to speak, it's prounouced as [bavaʀde]. Hear [here](https://youtu.be/9Qoogwxo5YA)
-
-## See also
-
-### [Imaginer : Imagine with AI](https://imaginer.codeberg.page)
-
-A tool for generating pictures with AI (GNOME app)
-
-- [GitHub](https://github.com/ImaginerApp/Imaginer)
-- [Codeberg](https://codeberg.org/Imaginer/Imaginer)
diff --git a/src/widgets/item.blp b/src/widgets/item.blp
index 1c7b26c..1fe8e8a 100644
--- a/src/widgets/item.blp
+++ b/src/widgets/item.blp
@@ -105,11 +105,6 @@ menu popover-model {
label: _("Edit");
action: "event.edit";
}
-
- item {
- label: _("Save");
- action: "event.save";
- }
}
section {
@@ -118,4 +113,4 @@ menu popover-model {
action: "event.delete";
}
}
-}
\ No newline at end of file
+}
diff --git a/src/widgets/item.py b/src/widgets/item.py
index c1671da..25d7b40 100644
--- a/src/widgets/item.py
+++ b/src/widgets/item.py
@@ -4,8 +4,6 @@ import re
import io
import base64
-from PIL import Image, UnidentifiedImageError
-
from bavarder.constants import app_id, rootdir
from bavarder.widgets.code_block import CodeBlock
@@ -33,7 +31,7 @@ m2p_styles = [
{ "name": BOLD, "re": re.compile(r"(^|[^\*])(\*\*)(.*)(\*\*)"), "sub": r"\1\3" },
{ "name": BOLD, "re": re.compile(r"(\*\*)(.*)(\*\*)([^\*]|$)"), "sub": r"\3\4" },
{ "name": EMPH, "re": re.compile(r"(^|[^\*])(\*)(.*)(\*)"), "sub": r"\1\3" },
- { "name": EMPH, "re": re.compile(r"(\*)(.*)(\*)([^\*]|$)"), "sub": r"\3\4" },
+ { "name": EMPH, "re": re.compile(r"(\*)(.*)(\*)([^\*]|$)"), "sub": r"\3\4" },
{ "name": PRE, "re": re.compile(r"(`)([^`]*)(`)"), "sub": r"\2" },
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\()(.+)(\))"), "sub": r"\3" },
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\(\))"), "sub": r"\3" },
@@ -82,76 +80,54 @@ class Item(Gtk.Box):
self.app = self.parent.get_application()
self.win = self.app.get_active_window()
- try:
- if not isinstance(self.content_text, Image.Image):
- if isinstance(self.content_text, bytes):
- self.image = Image.open(io.BytesIO(self.content_text))
- else:
- self.image = Image.open(io.BytesIO(base64.b64decode(self.content_text)))
- else:
- self.image = self.content_text
- except Exception:
- self.convert_content_to_pango()
+ self.convert_content_to_pango()
- result = ""
- is_code = False
- for line in self.content_markup:
- if isinstance(line, str):
- if "`" in line.strip():
- if is_code:
- is_code = False
- else:
- is_code = True
- continue
- if is_code or not isinstance(line, str):
- label = Gtk.Label()
- label.set_use_markup(True)
- label.set_wrap(True)
- label.set_xalign(0)
- label.set_wrap_mode(Pango.WrapMode.WORD)
- label.set_markup(result)
- label.set_justify(Gtk.Justification.LEFT)
- label.set_valign(Gtk.Align.START)
- label.set_hexpand(True)
- label.set_halign(Gtk.Align.START)
- self.content.append(label)
-
- if not isinstance(line, str):
- result = "\n".join(line)
+ result = ""
+ is_code = False
+ for line in self.content_markup:
+ if isinstance(line, str):
+ if "`" in line.strip():
+ if is_code:
+ is_code = False
else:
- result = line.strip()
+ is_code = True
+ continue
+ if is_code or not isinstance(line, str):
+ label = Gtk.Label()
+ label.set_use_markup(True)
+ label.set_wrap(True)
+ label.set_xalign(0)
+ label.set_wrap_mode(Pango.WrapMode.WORD)
+ label.set_markup(result)
+ label.set_justify(Gtk.Justification.LEFT)
+ label.set_valign(Gtk.Align.START)
+ label.set_hexpand(True)
+ label.set_halign(Gtk.Align.START)
+ self.content.append(label)
- self.content.append(CodeBlock(result))
- result = ""
- else:
- result += f"{line}\n"
-
+ if not isinstance(line, str):
+ result = "\n".join(line)
+ else:
+ result = line.strip()
+
+ self.content.append(CodeBlock(result))
+ result = ""
else:
- if not result.strip() == "`":
- label = Gtk.Label()
- label.set_use_markup(True)
- label.set_wrap(True)
- label.set_xalign(0)
- label.set_wrap_mode(Pango.WrapMode.WORD)
- label.set_markup(result)
- label.set_justify(Gtk.Justification.LEFT)
- label.set_valign(Gtk.Align.START)
- label.set_hexpand(True)
- label.set_halign(Gtk.Align.START)
- self.content.append(label)
+ result += f"{line}\n"
+
else:
- picture = Gtk.Picture()
- picture.set_halign(Gtk.Align.CENTER)
- picture.set_can_shrink(True)
- picture.set_content_fit(Gtk.ContentFit.FILL)
- picture.set_visible(True)
- picture.add_css_class("card")
- picture.set_margin_start(12)
- picture.set_margin_end(12)
- picture.set_size_request(270, 270)
- self.image.save("/tmp/image.png")
- picture.set_file(Gio.File.new_for_path("/tmp/image.png"))
- self.content.append(picture)
+ if not result.strip() == "`":
+ label = Gtk.Label()
+ label.set_use_markup(True)
+ label.set_wrap(True)
+ label.set_xalign(0)
+ label.set_wrap_mode(Pango.WrapMode.WORD)
+ label.set_markup(result)
+ label.set_justify(Gtk.Justification.LEFT)
+ label.set_valign(Gtk.Align.START)
+ label.set_hexpand(True)
+ label.set_halign(Gtk.Align.START)
+ self.content.append(label)
t = self.item["role"].lower()
@@ -190,7 +166,6 @@ class Item(Gtk.Box):
self.action_group = Gio.SimpleActionGroup()
self.create_action("delete", self.on_delete)
self.create_action("edit", self.on_edit)
- self.create_action("save", self.on_save)
self.create_action("copy", self.on_copy)
self.insert_action_group("event", self.action_group);
@@ -209,41 +184,6 @@ class Item(Gtk.Box):
def on_edit(self, *args):
self.win.message_entry.get_buffer().set_text(self.content_text)
- def on_save(self, *args):
- def on_save_response(dialog, response):
- if response == Gtk.ResponseType.OK:
- toast = Adw.Toast()
- try:
- self.image.save(dialog.get_file().get_path())
- except Exception as e:
- toast.set_title(_("Failed to save the image"))
- else:
- toast.set_title(_("Image saved"))
- finally:
- self.parent.toast_overlay.add_toast(toast)
-
- dialog.destroy()
-
- try:
- self.image
- except AttributeError:
- toast = Adw.Toast()
- toast.set_title(_("No image to save"))
- self.parent.toast_overlay.add_toast(toast)
- else:
- dialog = Gtk.FileChooserDialog(
- title=_("Save message"),
- action=Gtk.FileChooserAction.SAVE,
- modal=True,
- transient_for=self.win,
- )
- dialog.add_button(_("Cancel"), Gtk.ResponseType.CANCEL)
- dialog.add_button(_("Save"), Gtk.ResponseType.OK)
-
- dialog.connect('response', on_save_response)
- dialog.present()
-
-
def on_copy(self, *args):
Gdk.Display.get_default().get_clipboard().set(self.content_text)
@@ -268,7 +208,7 @@ class Item(Gtk.Box):
if self.color_span_open:
output.append('')
self.color_span_open = False
-
+
def try_open_span():
if not self.color_span_open:
output.append('')
@@ -296,7 +236,7 @@ class Item(Gtk.Box):
colors = re_color.match(line)
if colors or re_reset.match(line):
try_close_span()
-
+
if colors:
try_close_span()
@@ -309,19 +249,19 @@ class Item(Gtk.Box):
fg = colors[6]
else:
fg = ""
-
+
if colors[2] == 'bg':
fg = colors[3]
elif colors[5] == 'bg':
fg = colors[6]
else:
fg = ""
-
+
attrs = ''
if fg != '':
attrs += f" foreground='{fg}'"
-
+
if bg != '':
attrs += f" background='{bg}'"
@@ -329,7 +269,7 @@ class Item(Gtk.Box):
if attrs != '':
output.append("")
self.color_span_open = True
-
+
if re_comment.match(line):
continue
@@ -376,22 +316,22 @@ class Item(Gtk.Box):
if is_code and not code_start:
code_lines.append(result)
continue
-
+
if re_h1line.match(line):
output.append(re.sub(m2p_sections[0]["re"], m2p_sections[0]["sub"], f"# {output.pop()}"))
continue
-
+
if re_h2line.match(line):
output.append(re.sub(m2p_sections[1]["re"], m2p_sections[1]["sub"], f"# {output.pop()}"))
continue
-
+
for style in m2p_styles:
regexp = style["re"]
sub = style["sub"]
result = re.sub(regexp, sub, result)
-
+
uri = re_uri.match(result) # look for any URI
href = re_href.match(result) # and for URIs in href=''