Reimplement Conversations

This commit is contained in:
Bleak Grey 2020-08-02 00:47:22 +03:00 committed by GitHub
parent ddde3edd67
commit c9d0717e6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 73 deletions

View File

@ -24,7 +24,7 @@
</object> </object>
<template class="TootleWidgetsStatus" parent="GtkListBoxRow"> <template class="TootleWidgetsStatus" parent="GtkListBoxRow">
<property name="visible">True</property> <property name="visible">True</property>
<property name="activatable">True</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkGrid" id="grid"> <object class="GtkGrid" id="grid">
<property name="visible">True</property> <property name="visible">True</property>
@ -212,7 +212,6 @@
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="height">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -252,7 +251,6 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="vexpand">True</property> <property name="vexpand">True</property>
<property name="valign">fill</property>
<property name="row_homogeneous">True</property> <property name="row_homogeneous">True</property>
<child> <child>
<object class="TootleWidgetsRichLabel" id="name_label"> <object class="TootleWidgetsRichLabel" id="name_label">
@ -265,7 +263,7 @@
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
<property name="top_attach">0</property> <property name="top_attach">0</property>
<property name="width">2</property> <property name="width">3</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -283,33 +281,57 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkImage" id="pin_indicator"> <object class="GtkBox" id="indicators">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="margin_left">8</property> <property name="halign">end</property>
<property name="valign">start</property>
<property name="margin_start">8</property> <property name="margin_start">8</property>
<property name="icon_name">view-pin-symbolic</property> <property name="spacing">8</property>
<property name="icon_size">1</property> <child>
<object class="GtkImage" id="pin_indicator">
<property name="can_focus">False</property>
<property name="icon_name">view-pin-symbolic</property>
<property name="icon_size">1</property>
<property name="opacity">0.5</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkImage" id="indicator">
<property name="can_focus">False</property>
<property name="icon_name">unknown</property>
<property name="icon_size">1</property>
<property name="opacity">0.5</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="TootleWidgetsRichLabel" id="date_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="no">Yesterday</property>
<property name="opacity">0.5</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="top_attach">0</property> <property name="top_attach">0</property>
</packing> <property name="width">2</property>
</child>
<child>
<object class="TootleWidgetsRichLabel" id="date_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="opacity">0.5</property>
<property name="margin_left">8</property>
<property name="margin_start">8</property>
<property name="label" translatable="no">Yesterday</property>
<property name="halign">end</property>
<property name="valign">start</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">0</property>
</packing> </packing>
</child> </child>
</object> </object>

View File

@ -79,6 +79,7 @@ executable(
'src/Widgets/RichLabel.vala', 'src/Widgets/RichLabel.vala',
'src/Widgets/Status.vala', 'src/Widgets/Status.vala',
'src/Widgets/Notification.vala', 'src/Widgets/Notification.vala',
'src/Widgets/Conversation.vala',
'src/Widgets/VisibilityPopover.vala', 'src/Widgets/VisibilityPopover.vala',
'src/Widgets/Attachment/Box.vala', 'src/Widgets/Attachment/Box.vala',
'src/Widgets/Attachment/Slot.vala', 'src/Widgets/Attachment/Slot.vala',

View File

@ -1,6 +1,30 @@
public class Tootle.API.Conversation : Entity, Widgetizable { public class Tootle.API.Conversation : Entity, Widgetizable {
public string id { get; construct set; } public string id { get; set; }
public Gee.ArrayList<API.Account> accounts { get; set; }
public bool unread { get; set; default = false; } public bool unread { get; set; default = false; }
public API.Status? last_status { get; set; default = null; }
public override Gtk.Widget to_widget () {
return new Widgets.Conversation (this);
}
public override void open () {
var view = new Views.ExpandedStatus (last_status.formal);
window.open_view (view);
if (unread)
mark_read ();
}
public void mark_read () {
new Request.POST (@"/api/v1/conversations/$id/read")
.with_account (Tootle.accounts.active)
.then (() => {
unread = false;
})
.on_error (() => {})
.exec ();
}
} }

View File

@ -4,13 +4,14 @@ public class Tootle.Views.Conversations : Views.Timeline {
Object ( Object (
url: "/api/v1/conversations", url: "/api/v1/conversations",
label: _("Conversations"), label: _("Conversations"),
icon: API.Visibility.DIRECT.get_icon (), icon: API.Visibility.DIRECT.get_icon ()
accepts: typeof (API.Conversation)
); );
accepts = typeof (API.Conversation);
} }
public override string? get_stream_url () { // TODO: Reload when an update is received
return @"/api/v1/streaming/?stream=direct&access_token=$(account.access_token)"; // public override string? get_stream_url () {
} // return @"/api/v1/streaming/?stream=direct&access_token=$(account.access_token)";
// }
} }

View File

@ -17,37 +17,6 @@ public class Tootle.Widgets.Attachment.Box : FlowBox {
Object (editing: editing); Object (editing: editing);
} }
//TODO: Upload attachments in Compose dialog
public void select () {
var filter = new Gtk.FileFilter ();
filter.add_mime_type ("image/jpeg");
filter.add_mime_type ("image/png");
filter.add_mime_type ("image/gif");
filter.add_mime_type ("video/webm");
filter.add_mime_type ("video/mp4");
var chooser = new Gtk.FileChooserDialog (
_("Select media files to add"),
null,
Gtk.FileChooserAction.OPEN,
_("_Cancel"),
Gtk.ResponseType.CANCEL,
_("_Open"),
Gtk.ResponseType.ACCEPT);
chooser.select_multiple = true;
chooser.set_filter (filter);
if (chooser.run () == ResponseType.ACCEPT) {
show ();
foreach (unowned string uri in chooser.get_uris ()) {
//var widget = new ImageAttachment.upload (uri);
//append_widget (widget);
}
}
chooser.close ();
}
public bool populate (ArrayList<API.Attachment>? list) { public bool populate (ArrayList<API.Attachment>? list) {
if (list == null) if (list == null)
return false; return false;

View File

@ -0,0 +1,53 @@
using Gtk;
public class Tootle.Widgets.Conversation : Widgets.Status {
public API.Conversation conversation { get; construct set; }
public Conversation (API.Conversation entity) {
Object (conversation: entity, status: entity.last_status);
conversation.bind_property ("unread", this.indicator, "visible", BindingFlags.SYNC_CREATE);
this.indicators.child_set_property (this.indicator, "position", 2);
this.indicator.opacity = 1;
this.indicator.icon_name = Desktop.fallback_icon (
"software-update-urgent-symbolic",
"dialog-warning-symbolic");
this.actions.destroy ();
}
public new string title_text {
owned get {
var label = "";
foreach (API.Account account in conversation.accounts) {
label += "<b>" + Html.simplify (account.display_name) + "</b>";
if (conversation.accounts.last () != account)
label += ", ";
}
return @"$label";
}
}
public new string subtitle_text {
owned get {
var label = "";
foreach (API.Account account in conversation.accounts) {
label += account.handle + " ";
}
return @"<small>$label</small>";
}
}
public new string? avatar_url {
owned get {
if (conversation.accounts.size > 1)
return null;
else
return conversation.accounts.get (0).avatar;
}
}
public override void on_open () {
conversation.open ();
}
}

View File

@ -22,10 +22,14 @@ public class Tootle.Widgets.Status : ListBoxRow {
[GtkChild] [GtkChild]
protected Widgets.RichLabel handle_label; protected Widgets.RichLabel handle_label;
[GtkChild] [GtkChild]
protected Box indicators;
[GtkChild]
protected Widgets.RichLabel date_label; protected Widgets.RichLabel date_label;
[GtkChild] [GtkChild]
protected Image pin_indicator; protected Image pin_indicator;
[GtkChild] [GtkChild]
protected Image indicator;
[GtkChild]
public Revealer revealer; public Revealer revealer;
[GtkChild] [GtkChild]
protected Widgets.RichLabel content; protected Widgets.RichLabel content;
@ -68,13 +72,6 @@ public class Tootle.Widgets.Status : ListBoxRow {
} }
} }
protected string display_name {
owned get {
var name = Html.simplify (status.formal.account.display_name);
return @"<b>$name</b>";
}
}
protected string date { protected string date {
owned get { owned get {
var date = new GLib.DateTime.from_iso8601 (status.formal.created_at, null); var date = new GLib.DateTime.from_iso8601 (status.formal.created_at, null);
@ -83,13 +80,28 @@ public class Tootle.Widgets.Status : ListBoxRow {
} }
} }
protected string handle { public string title_text {
owned get {
var name = Html.simplify (status.formal.account.display_name);
return @"<b>$name</b>";
}
}
public string subtitle_text {
owned get { owned get {
return @"<small>$(status.formal.account.handle)</small>"; return @"<small>$(status.formal.account.handle)</small>";
} }
} }
public virtual signal void open () { public string? avatar_url {
owned get {
return status.formal.account.avatar;
}
}
public signal void open ();
public virtual void on_open () {
if (status.id == "") if (status.id == "")
on_avatar_clicked (); on_avatar_clicked ();
else else
@ -99,6 +111,7 @@ public class Tootle.Widgets.Status : ListBoxRow {
construct { construct {
content.activate_link.connect (on_toggle_spoiler); content.activate_link.connect (on_toggle_spoiler);
notify["kind"].connect (on_kind_changed); notify["kind"].connect (on_kind_changed);
open.connect (on_open);
if (kind == null) { if (kind == null) {
if (status.reblog != null) if (status.reblog != null)
@ -124,11 +137,11 @@ public class Tootle.Widgets.Status : ListBoxRow {
bind_property ("escaped-spoiler", content, "text", BindingFlags.SYNC_CREATE); bind_property ("escaped-spoiler", content, "text", BindingFlags.SYNC_CREATE);
bind_property ("escaped-content", revealer_content, "text", BindingFlags.SYNC_CREATE); bind_property ("escaped-content", revealer_content, "text", BindingFlags.SYNC_CREATE);
status.formal.account.bind_property ("avatar", avatar, "url", BindingFlags.SYNC_CREATE); bind_property ("title_text", name_label, "text", BindingFlags.SYNC_CREATE);
bind_property ("handle", handle_label, "label", BindingFlags.SYNC_CREATE); bind_property ("subtitle_text", handle_label, "text", BindingFlags.SYNC_CREATE);
bind_property ("display_name", name_label, "text", BindingFlags.SYNC_CREATE);
bind_property ("date", date_label, "label", BindingFlags.SYNC_CREATE); bind_property ("date", date_label, "label", BindingFlags.SYNC_CREATE);
status.formal.bind_property ("pinned", pin_indicator, "visible", BindingFlags.SYNC_CREATE); status.formal.bind_property ("pinned", pin_indicator, "visible", BindingFlags.SYNC_CREATE);
bind_property ("avatar_url", avatar, "url", BindingFlags.SYNC_CREATE);
status.formal.bind_property ("has_spoiler", revealer_content, "visible", BindingFlags.SYNC_CREATE); status.formal.bind_property ("has_spoiler", revealer_content, "visible", BindingFlags.SYNC_CREATE);
revealer.reveal_child = !status.formal.has_spoiler; revealer.reveal_child = !status.formal.has_spoiler;