New Date Separator
This commit is contained in:
parent
921f28c84b
commit
3aa3912dc3
|
@ -209,6 +209,7 @@ SOURCES
|
||||||
src/ui/util/sizing_bin.vala
|
src/ui/util/sizing_bin.vala
|
||||||
src/ui/util/size_request_box.vala
|
src/ui/util/size_request_box.vala
|
||||||
|
|
||||||
|
src/ui/widgets/date_separator.vala
|
||||||
src/ui/widgets/fixed_ratio_picture.vala
|
src/ui/widgets/fixed_ratio_picture.vala
|
||||||
src/ui/widgets/natural_size_increase.vala
|
src/ui/widgets/natural_size_increase.vala
|
||||||
CUSTOM_VAPIS
|
CUSTOM_VAPIS
|
||||||
|
|
|
@ -15,7 +15,6 @@ class DateSeparatorPopulator : Plugins.ConversationItemPopulator, Plugins.Conver
|
||||||
private Plugins.ConversationItemCollection? item_collection;
|
private Plugins.ConversationItemCollection? item_collection;
|
||||||
private Gee.TreeSet<DateTime> insert_times;
|
private Gee.TreeSet<DateTime> insert_times;
|
||||||
|
|
||||||
|
|
||||||
public DateSeparatorPopulator(StreamInteractor stream_interactor) {
|
public DateSeparatorPopulator(StreamInteractor stream_interactor) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
}
|
}
|
||||||
|
@ -54,92 +53,15 @@ class DateSeparatorPopulator : Plugins.ConversationItemPopulator, Plugins.Conver
|
||||||
public class MetaDateItem : Plugins.MetaConversationItem {
|
public class MetaDateItem : Plugins.MetaConversationItem {
|
||||||
public override DateTime time { get; set; }
|
public override DateTime time { get; set; }
|
||||||
|
|
||||||
private DateTime date;
|
|
||||||
|
|
||||||
public MetaDateItem(DateTime date) {
|
public MetaDateItem(DateTime date) {
|
||||||
this.date = date;
|
|
||||||
this.time = date;
|
this.time = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType widget_type) {
|
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType widget_type) {
|
||||||
return new DateSeparatorWidget(date);
|
return new DateSeparator() { model = new ViewModel.CompatDateSeparatorModel(time) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }
|
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DateSeparatorWidget : Box {
|
|
||||||
|
|
||||||
private DateTime date;
|
|
||||||
private Label label;
|
|
||||||
private uint time_update_timeout = 0;
|
|
||||||
|
|
||||||
public DateSeparatorWidget(DateTime date) {
|
|
||||||
Object(orientation:Orientation.HORIZONTAL, spacing:10);
|
|
||||||
width_request = 300;
|
|
||||||
halign = Align.CENTER;
|
|
||||||
visible = true;
|
|
||||||
this.date = date;
|
|
||||||
|
|
||||||
label = new Label("") { use_markup=true, halign=Align.CENTER, hexpand=false };
|
|
||||||
label.add_css_class("dim-label");
|
|
||||||
|
|
||||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
|
||||||
this.append(label);
|
|
||||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
|
||||||
|
|
||||||
update_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update_time() {
|
|
||||||
label.label = @"<span size='small'>$(get_relative_time(date))</span>";
|
|
||||||
time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => {
|
|
||||||
if (this.parent == null) return false;
|
|
||||||
update_time();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string get_relative_time(DateTime time) {
|
|
||||||
DateTime time_local = time.to_local();
|
|
||||||
DateTime now_local = new DateTime.now_local();
|
|
||||||
if (time_local.get_year() == now_local.get_year() &&
|
|
||||||
time_local.get_month() == now_local.get_month() &&
|
|
||||||
time_local.get_day_of_month() == now_local.get_day_of_month()) {
|
|
||||||
return _("Today");
|
|
||||||
}
|
|
||||||
DateTime now_local_minus = now_local.add_days(-1);
|
|
||||||
if (time_local.get_year() == now_local_minus.get_year() &&
|
|
||||||
time_local.get_month() == now_local_minus.get_month() &&
|
|
||||||
time_local.get_day_of_month() == now_local_minus.get_day_of_month()) {
|
|
||||||
return _("Yesterday");
|
|
||||||
}
|
|
||||||
if (time_local.get_year() != now_local.get_year()) {
|
|
||||||
return time_local.format("%x");
|
|
||||||
}
|
|
||||||
TimeSpan timespan = now_local.difference(time_local);
|
|
||||||
if (timespan < 7 * TimeSpan.DAY) {
|
|
||||||
return time_local.format(_("%a, %b %d"));
|
|
||||||
} else {
|
|
||||||
return time_local.format(_("%b %d"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int get_next_time_change() {
|
|
||||||
DateTime now = new DateTime.now_local();
|
|
||||||
return (23 - now.get_hour()) * 3600 + (59 - now.get_minute()) * 60 + (59 - now.get_second()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void dispose() {
|
|
||||||
base.dispose();
|
|
||||||
|
|
||||||
if (time_update_timeout != 0) {
|
|
||||||
Source.remove(time_update_timeout);
|
|
||||||
time_update_timeout = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
110
main/src/ui/widgets/date_separator.vala
Normal file
110
main/src/ui/widgets/date_separator.vala
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
public class Dino.Ui.ViewModel.DateSeparatorModel : Object {
|
||||||
|
public string date_label { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Dino.Ui.ViewModel.CompatDateSeparatorModel : DateSeparatorModel {
|
||||||
|
private DateTime date;
|
||||||
|
private uint time_update_timeout = 0;
|
||||||
|
|
||||||
|
public CompatDateSeparatorModel(DateTime date) {
|
||||||
|
this.date = date;
|
||||||
|
update_time_label();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string get_relative_time(DateTime time) {
|
||||||
|
DateTime time_local = time.to_local();
|
||||||
|
DateTime now_local = new DateTime.now_local();
|
||||||
|
if (time_local.get_year() == now_local.get_year() &&
|
||||||
|
time_local.get_month() == now_local.get_month() &&
|
||||||
|
time_local.get_day_of_month() == now_local.get_day_of_month()) {
|
||||||
|
return _("Today");
|
||||||
|
}
|
||||||
|
DateTime now_local_minus = now_local.add_days(-1);
|
||||||
|
if (time_local.get_year() == now_local_minus.get_year() &&
|
||||||
|
time_local.get_month() == now_local_minus.get_month() &&
|
||||||
|
time_local.get_day_of_month() == now_local_minus.get_day_of_month()) {
|
||||||
|
return _("Yesterday");
|
||||||
|
}
|
||||||
|
if (time_local.get_year() != now_local.get_year()) {
|
||||||
|
return time_local.format("%x");
|
||||||
|
}
|
||||||
|
TimeSpan timespan = now_local.difference(time_local);
|
||||||
|
if (timespan < 7 * TimeSpan.DAY) {
|
||||||
|
return time_local.format(_("%a, %b %d"));
|
||||||
|
} else {
|
||||||
|
return time_local.format(_("%b %d"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_time_label() {
|
||||||
|
date_label = get_relative_time(date);
|
||||||
|
time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => {
|
||||||
|
if (time_update_timeout != 0) update_time_label();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private int get_next_time_change() {
|
||||||
|
DateTime now = new DateTime.now_local();
|
||||||
|
return (23 - now.get_hour()) * 3600 + (59 - now.get_minute()) * 60 + (59 - now.get_second()) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void dispose() {
|
||||||
|
base.dispose();
|
||||||
|
|
||||||
|
if (time_update_timeout != 0) {
|
||||||
|
Source.remove(time_update_timeout);
|
||||||
|
time_update_timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Dino.Ui.DateSeparator : Gtk.Widget {
|
||||||
|
public ViewModel.DateSeparatorModel? model { get; set; }
|
||||||
|
public string date_label { get { return label.get_text(); } set { label.set_text(value); } }
|
||||||
|
|
||||||
|
private Label label = new Label("") { halign = Align.CENTER, hexpand = false };
|
||||||
|
private Binding? label_text_binding;
|
||||||
|
|
||||||
|
construct {
|
||||||
|
layout_manager = new BinLayout();
|
||||||
|
halign = Align.CENTER;
|
||||||
|
hexpand = true;
|
||||||
|
|
||||||
|
label.add_css_class("dim-label");
|
||||||
|
label.attributes = new Pango.AttrList();
|
||||||
|
label.attributes.insert(Pango.attr_scale_new(Pango.Scale.SMALL));
|
||||||
|
|
||||||
|
Box box = new Box(Orientation.HORIZONTAL, 10);
|
||||||
|
box.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
||||||
|
box.append(label);
|
||||||
|
box.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
||||||
|
|
||||||
|
Adw.Clamp clamp = new Adw.Clamp() { maximum_size = 300, tightening_threshold = 300, child = box, halign = Align.CENTER };
|
||||||
|
clamp.insert_after(this, null);
|
||||||
|
|
||||||
|
notify["model"].connect(on_model_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void on_model_changed() {
|
||||||
|
if (label_text_binding != null) label_text_binding.unbind();
|
||||||
|
if (model != null) {
|
||||||
|
label_text_binding = model.bind_property("date-label", this, "date-label", BindingFlags.SYNC_CREATE);
|
||||||
|
} else {
|
||||||
|
label_text_binding = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void dispose() {
|
||||||
|
if (label_text_binding != null) label_text_binding.unbind();
|
||||||
|
label_text_binding = null;
|
||||||
|
var clamp = get_first_child();
|
||||||
|
if (clamp != null) {
|
||||||
|
clamp.unparent();
|
||||||
|
clamp.dispose();
|
||||||
|
}
|
||||||
|
base.dispose();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue