Remove image handling and add Nix docs

This commit is contained in:
2026-04-06 17:18:35 +02:00
parent 86c9d3986b
commit fbd505a647
3 changed files with 75 additions and 135 deletions
+20 -15
View File
@@ -31,12 +31,6 @@
</a>
</p>
<p align="center">
<a href="https://stopthemingmy.app">
<img alt="Please do not theme this app" src="https://stopthemingmy.app/badge.svg"/>
</a>
</p>
<a href="https://bavarder.codeberg.page">
<p align="center">
<img src="./data/screenshots/preview.png" alt="Preview"/>
@@ -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)
+1 -6
View File
@@ -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";
}
}
}
}
+54 -114
View File
@@ -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<b>\3</b>" },
{ "name": BOLD, "re": re.compile(r"(\*\*)(.*)(\*\*)([^\*]|$)"), "sub": r"<b>\3</b>\4" },
{ "name": EMPH, "re": re.compile(r"(^|[^\*])(\*)(.*)(\*)"), "sub": r"\1<i>\3</i>" },
{ "name": EMPH, "re": re.compile(r"(\*)(.*)(\*)([^\*]|$)"), "sub": r"<i>\3</i>\4" },
{ "name": EMPH, "re": re.compile(r"(\*)(.*)(\*)([^\*]|$)"), "sub": r"<i>\3</i>\4" },
{ "name": PRE, "re": re.compile(r"(`)([^`]*)(`)"), "sub": r"<tt>\2</tt>" },
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\()(.+)(\))"), "sub": r"<a href='\5'>\3</a>" },
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\(\))"), "sub": r"<a href='\3'>\3</a>" },
@@ -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 "<tt></tt>`" 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 "<tt></tt>`" 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() == "<tt></tt>`":
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() == "<tt></tt>`":
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('</span>')
self.color_span_open = False
def try_open_span():
if not self.color_span_open:
output.append('</span>')
@@ -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("<span {attrs}>")
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=''