Private
Public Access
1
0

gtk: implement get_attachment_fd and texture/attachment cache, viewport loading

This commit is contained in:
2026-02-21 23:28:21 -08:00
parent f0ec6b8cb4
commit 7cf2724a75
5 changed files with 145 additions and 84 deletions

View File

@@ -13,30 +13,52 @@ private class SizeCache
return instance;
}
public Graphene.Size? get_size(string image_path) {
return size_cache.get(image_path);
public Graphene.Size? get_size(string attachment_guid) {
return size_cache.get(attachment_guid);
}
public void set_size(string image_path, Graphene.Size size) {
size_cache.set(image_path, size);
public void set_size(string attachment_guid, Graphene.Size size) {
size_cache.set(attachment_guid, size);
}
}
private class TextureCache
{
private static TextureCache instance = null;
private HashMap<string, Gdk.Texture> texture_cache = new HashMap<string, Gdk.Texture>();
public static TextureCache get_instance() {
if (instance == null) {
instance = new TextureCache();
}
return instance;
}
public Gdk.Texture? get_texture(string attachment_guid) {
return texture_cache.get(attachment_guid);
}
public void set_texture(string attachment_guid, Gdk.Texture texture) {
texture_cache.set(attachment_guid, texture);
}
}
private class ImageBubbleLayout : BubbleLayout
{
public string image_path;
public string attachment_guid;
public bool is_downloaded;
public string? attachment_guid;
private Graphene.Size image_size;
private Gdk.Texture? cached_texture = null;
private bool preview_download_queued = false;
public ImageBubbleLayout(string image_path, bool from_me, Widget parent, float max_width, Graphene.Size? image_size = null) {
public ImageBubbleLayout(string attachment_guid, bool from_me, Widget parent, float max_width, Graphene.Size? image_size = null) {
base(parent, max_width);
this.from_me = from_me;
this.image_path = image_path;
this.attachment_guid = attachment_guid;
this.is_downloaded = false;
this.cached_texture = TextureCache.get_instance().get_texture(attachment_guid);
// Calculate image dimensions for layout
calculate_image_dimensions(image_size);
@@ -48,26 +70,25 @@ private class ImageBubbleLayout : BubbleLayout
return;
}
var cached_size = SizeCache.get_instance().get_size(image_path);
var cached_size = SizeCache.get_instance().get_size(attachment_guid);
if (cached_size != null) {
this.image_size = cached_size;
return;
}
// Try to load the image to get its dimensions
this.image_size = Graphene.Size() { width = 200.0f, height = 150.0f };
}
private void queue_preview_download_if_needed() {
if (is_downloaded || preview_download_queued || attachment_guid == "") {
return;
}
try {
warning("No image size provided, loading image to get dimensions");
var texture = Gdk.Texture.from_filename(image_path);
var original_width = (float)texture.get_width();
var original_height = (float)texture.get_height();
this.image_size = Graphene.Size() { width = original_width, height = original_height };
SizeCache.get_instance().set_size(image_path, this.image_size);
} catch (Error e) {
// Fallback dimensions if image can't be loaded
warning("Failed to load image %s: %s", image_path, e.message);
this.image_size = Graphene.Size() { width = 200.0f, height = 150.0f };
Repository.get_instance().download_attachment(attachment_guid, true);
preview_download_queued = true;
} catch (GLib.Error e) {
warning("Failed to queue preview download for %s: %s", attachment_guid, e.message);
}
}
@@ -81,9 +102,22 @@ private class ImageBubbleLayout : BubbleLayout
}
try {
cached_texture = Gdk.Texture.from_filename(image_path);
int fd = Repository.get_instance().open_attachment_fd(attachment_guid, true);
var stream = new UnixInputStream(fd, true);
var pixbuf = new Gdk.Pixbuf.from_stream(stream, null);
cached_texture = Gdk.Texture.for_pixbuf(pixbuf);
if (cached_texture != null) {
TextureCache.get_instance().set_texture(attachment_guid, cached_texture);
this.image_size = Graphene.Size() {
width = (float)cached_texture.get_width(),
height = (float)cached_texture.get_height()
};
SizeCache.get_instance().set_size(attachment_guid, this.image_size);
parent.queue_allocate();
}
} catch (Error e) {
warning("Failed to load image %s: %s", image_path, e.message);
warning("Failed to load preview image for %s: %s", attachment_guid, e.message);
}
}
@@ -110,6 +144,7 @@ private class ImageBubbleLayout : BubbleLayout
}
public override void draw_content(Snapshot snapshot) {
queue_preview_download_if_needed();
load_image_if_needed();
snapshot.save();
@@ -137,4 +172,4 @@ private class ImageBubbleLayout : BubbleLayout
public override void copy(Gdk.Clipboard clipboard) {
clipboard.set_texture(cached_texture);
}
}
}