adds image bubble layout for attachments
This commit is contained in:
@@ -89,7 +89,6 @@ public class ConversationListModel : Object, ListModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update changed conversations
|
// Update changed conversations
|
||||||
GLib.message("Changed conversations: %d", changed_conversations.size);
|
|
||||||
foreach (var conv in changed_conversations) {
|
foreach (var conv in changed_conversations) {
|
||||||
// Find position of old conversation
|
// Find position of old conversation
|
||||||
uint old_pos = 0;
|
uint old_pos = 0;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ sources = [
|
|||||||
'transcript/layouts/bubble-layout.vala',
|
'transcript/layouts/bubble-layout.vala',
|
||||||
'transcript/layouts/chat-item-layout.vala',
|
'transcript/layouts/chat-item-layout.vala',
|
||||||
'transcript/layouts/date-item-layout.vala',
|
'transcript/layouts/date-item-layout.vala',
|
||||||
|
'transcript/layouts/image-bubble-layout.vala',
|
||||||
'transcript/layouts/sender-annotation-layout.vala',
|
'transcript/layouts/sender-annotation-layout.vala',
|
||||||
'transcript/layouts/text-bubble-layout.vala',
|
'transcript/layouts/text-bubble-layout.vala',
|
||||||
|
|
||||||
|
|||||||
98
src/transcript/layouts/image-bubble-layout.vala
Normal file
98
src/transcript/layouts/image-bubble-layout.vala
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using Gtk;
|
||||||
|
|
||||||
|
private class ImageBubbleLayout : BubbleLayout
|
||||||
|
{
|
||||||
|
public string image_path;
|
||||||
|
public bool is_downloaded;
|
||||||
|
|
||||||
|
private Graphene.Size image_size;
|
||||||
|
private Gdk.Texture? cached_texture = null;
|
||||||
|
private const float max_image_width = 300.0f;
|
||||||
|
private const float max_image_height = 400.0f;
|
||||||
|
|
||||||
|
public ImageBubbleLayout(string image_path, 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.is_downloaded = false;
|
||||||
|
|
||||||
|
// Calculate image dimensions for layout
|
||||||
|
calculate_image_dimensions(image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculate_image_dimensions(Graphene.Size? image_size) {
|
||||||
|
if (image_size != null) {
|
||||||
|
this.image_size = image_size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load the image to get its dimensions
|
||||||
|
try {
|
||||||
|
var texture = Gdk.Texture.from_filename(image_path);
|
||||||
|
var original_width = (float)texture.get_width();
|
||||||
|
var original_height = (float)texture.get_height();
|
||||||
|
|
||||||
|
// Calculate scaled dimensions while maintaining aspect ratio
|
||||||
|
var scale_factor = float.min(
|
||||||
|
max_image_width / original_width,
|
||||||
|
max_image_height / original_height
|
||||||
|
);
|
||||||
|
scale_factor = float.min(scale_factor, 1.0f); // Don't scale up
|
||||||
|
|
||||||
|
this.image_size = Graphene.Size() { width = original_width * scale_factor, height = original_height * scale_factor };
|
||||||
|
} 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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load_image_if_needed() {
|
||||||
|
if (cached_texture != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_downloaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cached_texture = Gdk.Texture.from_filename(image_path);
|
||||||
|
} catch (Error e) {
|
||||||
|
warning("Failed to load image %s: %s", image_path, e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float get_height() {
|
||||||
|
float aspect_ratio = image_size.width / image_size.height;
|
||||||
|
if (image_size.width > max_width) {
|
||||||
|
return max_width / aspect_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image_size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float get_width() {
|
||||||
|
return float.min(image_size.width, max_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void draw_content(Snapshot snapshot) {
|
||||||
|
load_image_if_needed();
|
||||||
|
|
||||||
|
snapshot.save();
|
||||||
|
|
||||||
|
var image_rect = Graphene.Rect () {
|
||||||
|
origin = Graphene.Point() { x = 0, y = 0 },
|
||||||
|
size = Graphene.Size() { width = get_width(), height = get_height() }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cached_texture != null) {
|
||||||
|
snapshot.append_texture(cached_texture, image_rect);
|
||||||
|
} else {
|
||||||
|
snapshot.append_color(Gdk.RGBA() { red = 0.6f, green = 0.6f, blue = 0.6f, alpha = 0.5f }, image_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user