Inbox: support for private messages
This commit is contained in:
parent
e0bdc593fb
commit
e289867cb8
|
@ -183,7 +183,7 @@ dependencies = [
|
|||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"time",
|
||||
"time 0.3.22",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -250,6 +250,15 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.71"
|
||||
|
@ -369,8 +378,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time 0.1.45",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -748,7 +762,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
@ -1102,6 +1116,29 @@ dependencies = [
|
|||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -1154,6 +1191,15 @@ version = "2.7.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
||||
|
||||
[[package]]
|
||||
name = "isolang"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f80f221db1bc708b71128757b9396727c04de86968081e18e89b0575e03be071"
|
||||
dependencies = [
|
||||
"phf 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
|
@ -1255,6 +1301,7 @@ dependencies = [
|
|||
name = "lemoa"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"html2pango",
|
||||
"lemmy_api_common",
|
||||
"markdown",
|
||||
|
@ -1265,6 +1312,7 @@ dependencies = [
|
|||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"timeago",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1385,7 +1433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
"phf 0.10.1",
|
||||
"phf_codegen",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
|
@ -1443,7 +1491,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -1616,7 +1664,16 @@ version = "0.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||
dependencies = [
|
||||
"phf_shared 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1626,7 +1683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1635,7 +1692,7 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.10.0",
|
||||
"rand",
|
||||
]
|
||||
|
||||
|
@ -1648,6 +1705,15 @@ dependencies = [
|
|||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.0"
|
||||
|
@ -2156,7 +2222,7 @@ dependencies = [
|
|||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"phf_shared 0.10.0",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
@ -2168,7 +2234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.10.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
@ -2284,6 +2350,17 @@ dependencies = [
|
|||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.22"
|
||||
|
@ -2311,6 +2388,16 @@ dependencies = [
|
|||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "timeago"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5082dc942361cdfb74eab98bf995762d6015e5bb3a20bf7c5c71213778b4fcb4"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"isolang",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
@ -2586,6 +2673,12 @@ dependencies = [
|
|||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -2709,6 +2802,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
|
|
|
@ -14,3 +14,5 @@ markdown = "0.3.0"
|
|||
html2pango = "0.5.0"
|
||||
rand = "0.8.5"
|
||||
mime_guess = "2.0.4"
|
||||
chrono = "0.4.26"
|
||||
timeago = "0.4.1"
|
||||
|
|
|
@ -19,9 +19,6 @@ Working:
|
|||
- Voting for or against posts or comments
|
||||
- Editing and deleting posts or comments
|
||||
- Viewing the personal inbox (mentions, replies)
|
||||
|
||||
Not yet supported:
|
||||
|
||||
- Private messages
|
||||
|
||||
# Build dependencies
|
||||
|
@ -61,6 +58,7 @@ sudo docker cp $(CONTAINER_ID):/root/lemoa/target/release/lemoa .
|
|||
Once the build is done, there will be an executable `lemoa` binary file in your current directory, executing it starts Lemoa :tada:.
|
||||
|
||||
# Building with meson
|
||||
|
||||
```
|
||||
meson _build
|
||||
ninja -C _build
|
||||
|
|
|
@ -77,7 +77,6 @@ impl FactoryComponent for CommentRow {
|
|||
set_markup: &markdown_to_pango_markup(self.comment.comment.content.clone()),
|
||||
set_halign: gtk::Align::Start,
|
||||
set_use_markup: true,
|
||||
set_selectable: true,
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
use gtk::prelude::*;
|
||||
use lemmy_api_common::lemmy_db_views_actor::structs::CommentReplyView;
|
||||
use lemmy_api_common::{
|
||||
lemmy_db_views::structs::PrivateMessageView, lemmy_db_views_actor::structs::CommentReplyView,
|
||||
};
|
||||
use relm4::{factory::FactoryVecDeque, prelude::*};
|
||||
|
||||
use crate::api;
|
||||
|
||||
use super::mention_row::MentionRow;
|
||||
use super::{mention_row::MentionRow, private_message_row::PrivateMessageRow};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InboxType {
|
||||
Replies,
|
||||
Mentions,
|
||||
PrivateMessages,
|
||||
}
|
||||
|
||||
pub struct InboxPage {
|
||||
mentions: FactoryVecDeque<MentionRow>,
|
||||
private_messages: FactoryVecDeque<PrivateMessageRow>,
|
||||
page: i64,
|
||||
unread_only: bool,
|
||||
type_: InboxType,
|
||||
|
@ -25,6 +29,7 @@ pub enum InboxInput {
|
|||
ToggleUnreadState,
|
||||
FetchInbox,
|
||||
UpdateInbox(Vec<CommentReplyView>),
|
||||
UpdatePrivateMessages(Vec<PrivateMessageView>),
|
||||
MarkAllAsRead,
|
||||
}
|
||||
|
||||
|
@ -41,32 +46,57 @@ impl SimpleComponent for InboxPage {
|
|||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_margin_all: 15,
|
||||
set_spacing: 10,
|
||||
gtk::Button {
|
||||
gtk::ToggleButton {
|
||||
set_label: "Replies",
|
||||
connect_clicked => InboxInput::UpdateType(InboxType::Replies),
|
||||
#[watch]
|
||||
set_active: model.type_ == InboxType::Replies,
|
||||
},
|
||||
gtk::Button {
|
||||
gtk::ToggleButton {
|
||||
set_label: "Mentions",
|
||||
connect_clicked => InboxInput::UpdateType(InboxType::Mentions),
|
||||
#[watch]
|
||||
set_active: model.type_ == InboxType::Mentions,
|
||||
},
|
||||
gtk::ToggleButton {
|
||||
set_label: "Private messages",
|
||||
connect_clicked => InboxInput::UpdateType(InboxType::PrivateMessages),
|
||||
#[watch]
|
||||
set_active: model.type_ == InboxType::PrivateMessages,
|
||||
},
|
||||
gtk::Box {
|
||||
set_hexpand: true,
|
||||
},
|
||||
gtk::ToggleButton {
|
||||
set_active: false,
|
||||
set_label: "Show unread only",
|
||||
connect_clicked => InboxInput::ToggleUnreadState,
|
||||
},
|
||||
gtk::Box {
|
||||
set_hexpand: true,
|
||||
},
|
||||
gtk::Button {
|
||||
set_label: "Mark all as read",
|
||||
connect_clicked => InboxInput::MarkAllAsRead,
|
||||
}
|
||||
},
|
||||
gtk::ScrolledWindow {
|
||||
#[local_ref]
|
||||
mentions -> gtk::Box {
|
||||
set_vexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
match model.type_ {
|
||||
InboxType::PrivateMessages => {
|
||||
gtk::Box {
|
||||
#[local_ref]
|
||||
private_messages -> gtk::Box {
|
||||
set_vexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
gtk::Box {
|
||||
#[local_ref]
|
||||
mentions -> gtk::Box {
|
||||
set_vexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,13 +108,16 @@ impl SimpleComponent for InboxPage {
|
|||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let mentions = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
|
||||
let private_messages = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
|
||||
let model = Self {
|
||||
mentions,
|
||||
private_messages,
|
||||
page: 1,
|
||||
unread_only: false,
|
||||
type_: InboxType::Replies,
|
||||
};
|
||||
let mentions = model.mentions.widget();
|
||||
let private_messages = model.private_messages.widget();
|
||||
let widgets = view_output!();
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
@ -96,26 +129,40 @@ impl SimpleComponent for InboxPage {
|
|||
let page = self.page.clone();
|
||||
let unread_only = self.unread_only.clone();
|
||||
std::thread::spawn(move || {
|
||||
let comments = match type_ {
|
||||
let message = match type_ {
|
||||
InboxType::Mentions => {
|
||||
if let Ok(response) = api::user::get_mentions(page, unread_only) {
|
||||
// It's just a different object, but its contents are exactly the same
|
||||
let serialised = serde_json::to_string(&response.mentions).unwrap();
|
||||
serde_json::from_str(&serialised).ok()
|
||||
let mentions = serde_json::from_str(&serialised).ok();
|
||||
if let Some(mentions) = mentions {
|
||||
Some(InboxInput::UpdateInbox(mentions))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
InboxType::Replies => {
|
||||
if let Ok(response) = api::user::get_replies(page, unread_only) {
|
||||
Some(response.replies)
|
||||
Some(InboxInput::UpdateInbox(response.replies))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
InboxType::PrivateMessages => {
|
||||
if let Ok(response) =
|
||||
api::private_message::list_private_messages(unread_only, page)
|
||||
{
|
||||
Some(InboxInput::UpdatePrivateMessages(response.private_messages))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
if let Some(comments) = comments {
|
||||
sender.input(InboxInput::UpdateInbox(comments))
|
||||
if let Some(message) = message {
|
||||
sender.input(message)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -133,6 +180,12 @@ impl SimpleComponent for InboxPage {
|
|||
self.mentions.guard().push_back(comment);
|
||||
}
|
||||
}
|
||||
InboxInput::UpdatePrivateMessages(messages) => {
|
||||
self.private_messages.guard().clear();
|
||||
for message in messages {
|
||||
self.private_messages.guard().push_back(message);
|
||||
}
|
||||
}
|
||||
InboxInput::MarkAllAsRead => {
|
||||
let show_unread_only = self.unread_only.clone();
|
||||
std::thread::spawn(move || {
|
||||
|
|
|
@ -30,7 +30,7 @@ impl FactoryComponent for MentionRow {
|
|||
type Input = MentionRowMsg;
|
||||
type Output = crate::AppMsg;
|
||||
type CommandOutput = ();
|
||||
type Widgets = PostViewWidgets;
|
||||
type Widgets = MentionRowWidgets;
|
||||
type ParentInput = crate::AppMsg;
|
||||
type ParentWidget = gtk::Box;
|
||||
|
||||
|
@ -104,7 +104,6 @@ impl FactoryComponent for MentionRow {
|
|||
set_markup: &markdown_to_pango_markup(self.comment.comment.content.clone()),
|
||||
set_halign: gtk::Align::Start,
|
||||
set_use_markup: true,
|
||||
set_selectable: true,
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
|
|
|
@ -5,5 +5,6 @@ pub mod inbox_page;
|
|||
pub mod mention_row;
|
||||
pub mod post_page;
|
||||
pub mod post_row;
|
||||
pub mod private_message_row;
|
||||
pub mod profile_page;
|
||||
pub mod voting_row;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
use gtk::prelude::*;
|
||||
use lemmy_api_common::lemmy_db_views::structs::PrivateMessageView;
|
||||
use relm4::prelude::FactoryComponent;
|
||||
use relm4::prelude::*;
|
||||
use relm4_components::web_image::WebImage;
|
||||
|
||||
use crate::util::{self, get_web_image_url, markdown_to_pango_markup};
|
||||
|
||||
pub struct PrivateMessageRow {
|
||||
message: PrivateMessageView,
|
||||
creator_image: Controller<WebImage>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PrivateMessageRowInput {
|
||||
OpenPerson,
|
||||
}
|
||||
|
||||
#[relm4::factory(pub)]
|
||||
impl FactoryComponent for PrivateMessageRow {
|
||||
type Init = PrivateMessageView;
|
||||
type Input = PrivateMessageRowInput;
|
||||
type Output = crate::AppMsg;
|
||||
type CommandOutput = ();
|
||||
type Widgets = PrivateMessageRowWidgets;
|
||||
type ParentInput = crate::AppMsg;
|
||||
type ParentWidget = gtk::Box;
|
||||
|
||||
view! {
|
||||
root = gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 10,
|
||||
set_margin_end: 10,
|
||||
set_margin_start: 10,
|
||||
set_margin_top: 10,
|
||||
set_vexpand: false,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 10,
|
||||
set_vexpand: false,
|
||||
set_hexpand: true,
|
||||
|
||||
if self.message.creator.avatar.is_some() {
|
||||
gtk::Box {
|
||||
set_hexpand: false,
|
||||
#[local_ref]
|
||||
creator_image -> gtk::Box {}
|
||||
}
|
||||
} else {
|
||||
gtk::Box {}
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: &self.message.creator.name,
|
||||
connect_clicked => PrivateMessageRowInput::OpenPerson,
|
||||
},
|
||||
|
||||
gtk::Label {
|
||||
set_margin_start: 10,
|
||||
set_label: &util::format_elapsed_time(self.message.private_message.published)
|
||||
}
|
||||
},
|
||||
|
||||
gtk::Label {
|
||||
#[watch]
|
||||
set_markup: &markdown_to_pango_markup(self.message.private_message.content.clone()),
|
||||
set_halign: gtk::Align::Start,
|
||||
set_use_markup: true,
|
||||
},
|
||||
|
||||
gtk::Separator {}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_model(init: Self::Init, _index: &Self::Index, _sender: FactorySender<Self>) -> Self {
|
||||
let creator_image = WebImage::builder()
|
||||
.launch(get_web_image_url(init.creator.avatar.clone()))
|
||||
.detach();
|
||||
Self {
|
||||
message: init,
|
||||
creator_image,
|
||||
}
|
||||
}
|
||||
fn init_widgets(
|
||||
&mut self,
|
||||
_index: &Self::Index,
|
||||
root: &Self::Root,
|
||||
_returned_widget: &<Self::ParentWidget as relm4::factory::FactoryView>::ReturnedWidget,
|
||||
sender: FactorySender<Self>,
|
||||
) -> Self::Widgets {
|
||||
let creator_image = self.creator_image.widget();
|
||||
let widgets = view_output!();
|
||||
widgets
|
||||
}
|
||||
|
||||
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||
Some(output)
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
|
||||
match message {
|
||||
PrivateMessageRowInput::OpenPerson => {
|
||||
sender.output(crate::AppMsg::OpenPerson(self.message.creator.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/util.rs
13
src/util.rs
|
@ -10,13 +10,20 @@ pub fn get_web_image_msg(url: Option<DbUrl>) -> WebImageMsg {
|
|||
}
|
||||
|
||||
pub fn get_web_image_url(url: Option<DbUrl>) -> String {
|
||||
return if let Some(url) = url {
|
||||
if let Some(url) = url {
|
||||
url.to_string()
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
"".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markdown_to_pango_markup(text: String) -> String {
|
||||
return html2pango::markup_html(&markdown::to_html(&text)).unwrap_or(text);
|
||||
}
|
||||
|
||||
pub fn format_elapsed_time(time: chrono::NaiveDateTime) -> String {
|
||||
let formatter = timeago::Formatter::new();
|
||||
let current_time = chrono::Utc::now();
|
||||
let published = time.and_utc();
|
||||
formatter.convert_chrono(published, current_time)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue