Place time+encryption+read directly right of name

This commit is contained in:
fiaxh 2017-11-26 19:28:44 +01:00
parent 8cbc4e7f89
commit 119e7cce4f
7 changed files with 169 additions and 136 deletions

View file

@ -46,15 +46,14 @@ public class PresenceManager : StreamInteractionModule, Object {
if (stream != null) { if (stream != null) {
Xmpp.Presence.Flag flag = stream.get_flag(Presence.Flag.IDENTITY); Xmpp.Presence.Flag flag = stream.get_flag(Presence.Flag.IDENTITY);
if (flag == null) return null; if (flag == null) return null;
Gee.List<string> resources = flag.get_resources(jid.bare_jid.to_string()); Gee.List<string>? resources = flag.get_resources(jid.bare_jid.to_string());
if (resources == null) { if (resources == null) {
return null; return null;
} }
ArrayList<Jid> ret = new ArrayList<Jid>(Jid.equals_func); ArrayList<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
resources.foreach((resource) => { foreach (string resource in resources) {
ret.add(new Jid(resource)); ret.add(new Jid(resource));
return true; }
});
return ret; return ret;
} }
return null; return null;

View file

@ -12,6 +12,7 @@ find_packages(MAIN_PACKAGES REQUIRED
) )
set(RESOURCE_LIST set(RESOURCE_LIST
icons/dino-changes-prevent-symbolic.svg
icons/dino-double-tick-symbolic.svg icons/dino-double-tick-symbolic.svg
icons/dino-status-away.svg icons/dino-status-away.svg
icons/dino-status-chat.svg icons/dino-status-chat.svg
@ -32,7 +33,6 @@ set(RESOURCE_LIST
conversation_selector/chat_row_tooltip.ui conversation_selector/chat_row_tooltip.ui
conversation_selector/conversation_row.ui conversation_selector/conversation_row.ui
conversation_summary/image_toolbar.ui conversation_summary/image_toolbar.ui
conversation_summary/message_item.ui
conversation_summary/view.ui conversation_summary/view.ui
manage_accounts/account_row.ui manage_accounts/account_row.ui
manage_accounts/add_account_dialog.ui manage_accounts/add_account_dialog.ui
@ -159,6 +159,7 @@ install(FILES
data/icons/dino-status-dnd.svg data/icons/dino-status-dnd.svg
data/icons/dino-status-online.svg data/icons/dino-status-online.svg
data/icons/dino-changes-prevent-symbolic.svg
data/icons/dino-double-tick-symbolic.svg data/icons/dino-double-tick-symbolic.svg
data/icons/dino-tick-symbolic.svg data/icons/dino-tick-symbolic.svg
DESTINATION DESTINATION

View file

@ -1,72 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="DinoUiConversationSummaryConversationItemSkeleton">
<property name="hexpand">True</property>
<property name="column-spacing">7</property>
<property name="orientation">horizontal</property>
<property name="visible">True</property>
<child>
<object class="GtkImage" id="image">
<property name="expand">False</property>
<property name="height_request">30</property>
<property name="margin_top">2</property>
<property name="width_request">30</property>
<property name="yalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="time_label">
<property name="xalign">1</property>
<property name="valign">start</property>
<property name="visible">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="received_image">
<property name="visible">False</property>
<property name="xalign">1</property>
<property name="valign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="encryption_image">
<property name="visible">False</property>
<property name="xalign">1</property>
<property name="valign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</template>
</interface>

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="16"
version="1.1"
id="svg7384"
height="12">
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="layer9">
<path
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.76307714;marker:none"
id="rect4063"
d="m 188.13566,241.5 c -1.44483,0 -2.63542,1.19893 -2.63542,2.65384 v 2.65385 h -0.87847 c -0.48668,0 -0.87847,0.39453 -0.87847,0.88462 V 248.16225 253 h 4.39236 1.75695 4.39235 v -4.83775 -0.46994 c 0,-0.49009 -0.39179,-0.88462 -0.87846,-0.88462 h -0.87848 v -2.65385 c 0,-1.45491 -1.19059,-2.65384 -2.63541,-2.65384 z m 0,1.76922 h 1.75695 c 0.50187,0 0.87848,0.37925 0.87848,0.88462 v 2.65385 h -3.5139 v -2.65385 c 0,-0.50537 0.3766,-0.88462 0.87847,-0.88462 z" />
</g>
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="layer10" />
<g
transform="translate(-181.0002,-241)"
id="layer11" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="layer13" />
<g
transform="translate(-181.0002,-241)"
id="layer14" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="layer15" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="g71291" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="g4953" />
<g
transform="translate(-181.0002,-241)"
style="display:inline"
id="layer12" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -7,42 +7,51 @@ using Dino.Entities;
namespace Dino.Ui.ConversationSummary { namespace Dino.Ui.ConversationSummary {
[GtkTemplate (ui = "/im/dino/Dino/conversation_summary/message_item.ui")] public class ConversationItemSkeleton : Box {
public class ConversationItemSkeleton : Grid {
[GtkChild] private Image image; private Image image = new Image() { margin_top=2, valign=Align.START, visible=true };
[GtkChild] private Label time_label;
[GtkChild] private Image encryption_image;
[GtkChild] private Image received_image;
public StreamInteractor stream_interactor; public StreamInteractor stream_interactor;
public Conversation conversation { get; set; } public Conversation conversation { get; set; }
public ArrayList<Plugins.MetaConversationItem> items = new ArrayList<Plugins.MetaConversationItem>(); public ArrayList<Plugins.MetaConversationItem> items = new ArrayList<Plugins.MetaConversationItem>();
private Box box = new Box(Orientation.VERTICAL, 2) { visible=true }; private Grid grid = new Grid() { visible=true };
private HashMap<Plugins.MetaConversationItem, Widget> item_widgets = new HashMap<Plugins.MetaConversationItem, Widget>(); private HashMap<Plugins.MetaConversationItem, Widget> item_widgets = new HashMap<Plugins.MetaConversationItem, Widget>();
private DefaultSkeletonHeader default_header;
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation) { public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item) {
this.conversation = conversation; this.conversation = conversation;
this.stream_interactor = stream_interactor; this.stream_interactor = stream_interactor;
set_main_widget(box); if (item.requires_avatar) {
Util.image_set_from_scaled_pixbuf(image, (new AvatarGenerator(32, 32, image.scale_factor)).set_greyscale(item.dim).draw_jid(stream_interactor, item.jid, conversation.account));
}
if (item.display_time != null) {
default_header = new DefaultSkeletonHeader(stream_interactor, conversation, item) { visible=true };
if (!item.requires_header) {
default_header.name_label.visible = false;
default_header.dot_label.visible = false;
}
grid.attach(default_header, 0, 0, 1, 1);
}
add_meta_item(item);
Box image_content_box = new Box(Orientation.HORIZONTAL, 8) { visible=true };
image_content_box.add(image);
image_content_box.add(grid);
this.add(image_content_box);
} }
public void add_meta_item(Plugins.MetaConversationItem item) { public void add_meta_item(Plugins.MetaConversationItem item) {
items.add(item); items.add(item);
if (items.size == 1) { if (default_header != null) {
setup(item); default_header.add_item(item);
} }
Widget widget = (Widget) item.get_widget(Plugins.WidgetType.GTK); Widget? widget = item.get_widget(Plugins.WidgetType.GTK) as Widget;
if (item.requires_header) { if (widget != null) {
box.add(widget); grid.attach(widget, 0, items.size, 1, 1);
item_widgets[item] = widget; item_widgets[item] = widget;
} else {
set_title_widget(widget);
} }
item.notify["mark"].connect_after(update_received_mark);
update_received_mark();
} }
public void remove_meta_item(Plugins.MetaConversationItem item) { public void remove_meta_item(Plugins.MetaConversationItem item) {
@ -51,45 +60,74 @@ public class ConversationItemSkeleton : Grid {
items.remove(item); items.remove(item);
} }
public void set_title_widget(Widget w) { public void update_time() {
attach(w, 1, 0, 1, 1); if (default_header != null) {
default_header.update_time();
}
}
}
public class DefaultSkeletonHeader : Box {
private Box box = new Box(Orientation.HORIZONTAL, 4) { visible=true };
public Label name_label = new Label("") { use_markup=true, xalign=0, visible=true };
public Label time_label = new Label("") { use_markup=true, xalign=0, visible=true };
public Label dot_label = new Label("<span size='small'>·</span>") { use_markup=true, xalign=0, visible=true };
public Image encryption_image = new Image();
public Image received_image = new Image();
private StreamInteractor stream_interactor;
private Conversation conversation;
private Plugins.MetaConversationItem item;
private ArrayList<Plugins.MetaConversationItem> items = new ArrayList<Plugins.MetaConversationItem>();
public static IconSize ICON_SIZE_HEADER = Gtk.icon_size_register("im.dino.Dino.HEADER_ICON", 17, 12);
public virtual string TEXT_SIZE { get { return "small"; } }
construct {
time_label.get_style_context().add_class("dim-label");
dot_label.get_style_context().add_class("dim-label");
encryption_image.opacity = 0.4;
received_image.opacity = 0.4;
} }
public void set_main_widget(Widget w) { public DefaultSkeletonHeader(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item) {
attach(w, 1, 1, 2, 1); this.stream_interactor = stream_interactor;
this.conversation = conversation;
this.item = item;
box.add(name_label);
box.add(dot_label);
box.add(time_label);
box.add(received_image);
box.add(encryption_image);
this.add(box);
update_name_label();
name_label.style_updated.connect(update_name_label);
if (item.encryption != null && item.encryption != Encryption.NONE) {
encryption_image.visible = true;
encryption_image.set_from_icon_name("dino-changes-prevent-symbolic", ICON_SIZE_HEADER);
}
update_time();
add_item(item);
}
public void add_item(Plugins.MetaConversationItem item) {
items.add(item);
item.notify["mark"].connect_after(update_received_mark);
update_received_mark();
} }
public void update_time() { public void update_time() {
if (items.size > 0 && items[0].display_time != null) { if (item.display_time != null) {
time_label.label = get_relative_time(items[0].display_time.to_local()); time_label.label = @"<span size='$TEXT_SIZE'>" + get_relative_time(item.display_time.to_local()) + "</span>";
} }
} }
private void setup(Plugins.MetaConversationItem item) { private void update_name_label() {
update_time(); string display_name = Util.get_display_name(stream_interactor, item.jid, conversation.account);
if (item.requires_avatar) { string color = Util.get_name_hex_color(stream_interactor, conversation.account, item.jid, Util.is_dark_theme(name_label));
image.visible = true; name_label.label = @"<span size='$TEXT_SIZE' foreground=\"#$color\">$display_name</span>";
Util.image_set_from_scaled_pixbuf(image, (new AvatarGenerator(30, 30, image.scale_factor)).set_greyscale(item.dim).draw_jid(stream_interactor, item.jid, conversation.account));
}
if (item.requires_header) {
set_default_title_widget(item.jid);
}
if (item.encryption != null && item.encryption != Encryption.NONE) {
encryption_image.visible = true;
encryption_image.set_from_icon_name("changes-prevent-symbolic", IconSize.SMALL_TOOLBAR);
}
}
private void set_default_title_widget(Jid jid) {
Label name_label = new Label("") { use_markup=true, xalign=0, hexpand=true, visible=true };
string display_name = Util.get_display_name(stream_interactor, jid, conversation.account);
string color = Util.get_name_hex_color(stream_interactor, conversation.account, jid, Util.is_dark_theme(name_label));
name_label.label = @"<span foreground=\"#$color\">$display_name</span>";
name_label.style_updated.connect(() => {
string new_color = Util.get_name_hex_color(stream_interactor, conversation.account, jid, Util.is_dark_theme(name_label));
name_label.set_markup(@"<span foreground=\"#$new_color\">$display_name</span>");
});
set_title_widget(name_label);
} }
private void update_received_mark() { private void update_received_mark() {
@ -99,7 +137,7 @@ public class ConversationItemSkeleton : Grid {
foreach (Plugins.MetaConversationItem item in items) { foreach (Plugins.MetaConversationItem item in items) {
if (item.mark == Message.Marked.WONTSEND) { if (item.mark == Message.Marked.WONTSEND) {
received_image.visible = true; received_image.visible = true;
received_image.set_from_icon_name("dialog-warning-symbolic", IconSize.SMALL_TOOLBAR); received_image.set_from_icon_name("dialog-warning-symbolic", ICON_SIZE_HEADER);
Util.force_error_color(received_image); Util.force_error_color(received_image);
Util.force_error_color(encryption_image); Util.force_error_color(encryption_image);
Util.force_error_color(time_label); Util.force_error_color(time_label);
@ -116,19 +154,20 @@ public class ConversationItemSkeleton : Grid {
} }
if (all_read) { if (all_read) {
received_image.visible = true; received_image.visible = true;
received_image.set_from_icon_name("dino-double-tick-symbolic", IconSize.SMALL_TOOLBAR); received_image.set_from_icon_name("dino-double-tick-symbolic", ICON_SIZE_HEADER);
} else if (all_received) { } else if (all_received) {
received_image.visible = true; received_image.visible = true;
received_image.set_from_icon_name("dino-tick-symbolic", IconSize.SMALL_TOOLBAR); received_image.set_from_icon_name("dino-tick-symbolic", ICON_SIZE_HEADER);
} else if (!all_sent) { } else if (!all_sent) {
received_image.visible = true; received_image.visible = true;
received_image.set_from_icon_name("image-loading-symbolic", IconSize.SMALL_TOOLBAR); received_image.set_from_icon_name("image-loading-symbolic", ICON_SIZE_HEADER);
} else if (received_image.visible) { } else if (received_image.visible) {
received_image.set_from_icon_name("image-loading-symbolic", IconSize.SMALL_TOOLBAR); received_image.set_from_icon_name("image-loading-symbolic", ICON_SIZE_HEADER);
} }
} }
private static string format_time(DateTime datetime, string format_24h, string format_12h) { public static string format_time(DateTime datetime, string format_24h, string format_12h) {
string format = Util.is_24h_format() ? format_24h : format_12h; string format = Util.is_24h_format() ? format_24h : format_12h;
if (!get_charset(null)) { if (!get_charset(null)) {
// No UTF-8 support, use simple colon for time instead // No UTF-8 support, use simple colon for time instead
@ -137,7 +176,7 @@ public class ConversationItemSkeleton : Grid {
return datetime.format(format); return datetime.format(format);
} }
private static string get_relative_time(DateTime datetime) { public virtual string get_relative_time(DateTime datetime) {
DateTime now = new DateTime.now_local(); DateTime now = new DateTime.now_local();
TimeSpan timespan = now.difference(datetime); TimeSpan timespan = now.difference(datetime);
if (timespan > 365 * TimeSpan.DAY) { if (timespan > 365 * TimeSpan.DAY) {

View file

@ -161,8 +161,7 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
} }
// Fill datastructure // Fill datastructure
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation); ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item) { visible=true };
item_skeleton.add_meta_item(item);
item_item_skeletons[item] = item_skeleton; item_item_skeletons[item] = item_skeleton;
int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0; int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0;
item_skeletons.insert(index, item_skeleton); item_skeletons.insert(index, item_skeleton);

View file

@ -59,8 +59,8 @@ public class MetaSlashmeItem : Plugins.MetaConversationItem {
TextIter iter; TextIter iter;
text_view.buffer.get_start_iter(out iter); text_view.buffer.get_start_iter(out iter);
text_view.buffer.insert_with_tags(ref iter, display_name, display_name.length, nick_tag); text_view.buffer.insert_with_tags(ref iter, display_name, display_name.length, nick_tag);
text_view.add_text(message.body.substring(3)); text_view.add_text(message.body.substring(3));
text_view.style_updated.connect(update_style); text_view.style_updated.connect(update_style);
text_view.realize.connect(update_style); text_view.realize.connect(update_style);
return text_view; return text_view;