Refactor thread responses into an enum.
Lays ground work for different types of views, i.e. email, news, docs, etc.
This commit is contained in:
parent
446fcfe37f
commit
760cec01a8
@ -32,8 +32,13 @@ pub struct ThreadSummary {
|
|||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Union)]
|
||||||
|
pub enum Thread {
|
||||||
|
Email(EmailThread),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
pub struct Thread {
|
pub struct EmailThread {
|
||||||
pub thread_id: String,
|
pub thread_id: String,
|
||||||
pub subject: String,
|
pub subject: String,
|
||||||
pub messages: Vec<Message>,
|
pub messages: Vec<Message>,
|
||||||
@ -369,11 +374,13 @@ impl QueryRoot {
|
|||||||
.field("contentTree")
|
.field("contentTree")
|
||||||
.exists();
|
.exists();
|
||||||
// TODO: look at thread_id and conditionally load newsreader
|
// TODO: look at thread_id and conditionally load newsreader
|
||||||
if newsreader::is_newsreader_thread(&thread_id) {
|
Ok(Thread::Email(
|
||||||
Ok(newsreader::thread(pool, thread_id).await?)
|
if newsreader::is_newsreader_thread(&thread_id) {
|
||||||
} else {
|
newsreader::thread(pool, thread_id).await?
|
||||||
Ok(nm::thread(nm, thread_id, debug_content_tree).await?)
|
} else {
|
||||||
}
|
nm::thread(nm, thread_id, debug_content_tree).await?
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const THREAD_PREFIX: &'static str = "news:";
|
|||||||
use crate::{
|
use crate::{
|
||||||
compute_offset_limit,
|
compute_offset_limit,
|
||||||
error::ServerError,
|
error::ServerError,
|
||||||
graphql::{Body, Email, Html, Message, Tag, Thread, ThreadSummary},
|
graphql::{Body, Email, EmailThread, Html, Message, Tag, ThreadSummary},
|
||||||
AddOutlink, EscapeHtml, InlineStyle, SanitizeHtml, SlurpContents, StripHtml, Transformer,
|
AddOutlink, EscapeHtml, InlineStyle, SanitizeHtml, SlurpContents, StripHtml, Transformer,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ pub async fn tags(pool: &PgPool, _needs_unread: bool) -> Result<Vec<Tag>, Server
|
|||||||
Ok(tags)
|
Ok(tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerError> {
|
pub async fn thread(pool: &PgPool, thread_id: String) -> Result<EmailThread, ServerError> {
|
||||||
let id = thread_id
|
let id = thread_id
|
||||||
.strip_prefix(THREAD_PREFIX)
|
.strip_prefix(THREAD_PREFIX)
|
||||||
.expect("news thread doesn't start with '{THREAD_PREFIX}'")
|
.expect("news thread doesn't start with '{THREAD_PREFIX}'")
|
||||||
@ -198,7 +198,6 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
|
|||||||
// * Grafana does <div class="image-wrapp"><img class="lazyload>"<img src="/media/...>"</img></div>
|
// * Grafana does <div class="image-wrapp"><img class="lazyload>"<img src="/media/...>"</img></div>
|
||||||
// * Some sites appear to be HTML encoded, unencode them, i.e. imperialviolent
|
// * Some sites appear to be HTML encoded, unencode them, i.e. imperialviolent
|
||||||
let body_tranformers: Vec<Box<dyn Transformer>> = vec![
|
let body_tranformers: Vec<Box<dyn Transformer>> = vec![
|
||||||
// TODO: add a map of urls and selectors
|
|
||||||
Box::new(SlurpContents {
|
Box::new(SlurpContents {
|
||||||
site_selectors: hashmap![
|
site_selectors: hashmap![
|
||||||
"hackaday.com".to_string() => vec![
|
"hackaday.com".to_string() => vec![
|
||||||
@ -237,7 +236,7 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
|
|||||||
name: r.name,
|
name: r.name,
|
||||||
addr: addr.map(|a| a.to_string()),
|
addr: addr.map(|a| a.to_string()),
|
||||||
});
|
});
|
||||||
Ok(Thread {
|
Ok(EmailThread {
|
||||||
thread_id,
|
thread_id,
|
||||||
subject: title.clone(),
|
subject: title.clone(),
|
||||||
messages: vec![Message {
|
messages: vec![Message {
|
||||||
|
|||||||
@ -14,8 +14,8 @@ use crate::{
|
|||||||
compute_offset_limit,
|
compute_offset_limit,
|
||||||
error::ServerError,
|
error::ServerError,
|
||||||
graphql::{
|
graphql::{
|
||||||
Attachment, Body, DispositionType, Email, Header, Html, Message, PlainText, Tag, Thread,
|
Attachment, Body, DispositionType, Email, EmailThread, Header, Html, Message, PlainText,
|
||||||
ThreadSummary, UnhandledContentType,
|
Tag, ThreadSummary, UnhandledContentType,
|
||||||
},
|
},
|
||||||
linkify_html, sanitize_html,
|
linkify_html, sanitize_html,
|
||||||
};
|
};
|
||||||
@ -125,7 +125,7 @@ pub async fn thread(
|
|||||||
nm: &Notmuch,
|
nm: &Notmuch,
|
||||||
thread_id: String,
|
thread_id: String,
|
||||||
debug_content_tree: bool,
|
debug_content_tree: bool,
|
||||||
) -> Result<Thread, ServerError> {
|
) -> Result<EmailThread, ServerError> {
|
||||||
// TODO(wathiede): normalize all email addresses through an address book with preferred
|
// TODO(wathiede): normalize all email addresses through an address book with preferred
|
||||||
// display names (that default to the most commonly seen name).
|
// display names (that default to the most commonly seen name).
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
@ -246,7 +246,7 @@ pub async fn thread(
|
|||||||
.next()
|
.next()
|
||||||
.and_then(|m| m.subject.clone())
|
.and_then(|m| m.subject.clone())
|
||||||
.unwrap_or("(NO SUBJECT)".to_string());
|
.unwrap_or("(NO SUBJECT)".to_string());
|
||||||
Ok(Thread {
|
Ok(EmailThread {
|
||||||
thread_id,
|
thread_id,
|
||||||
subject,
|
subject,
|
||||||
messages,
|
messages,
|
||||||
|
|||||||
@ -290,6 +290,73 @@
|
|||||||
"name": "Email",
|
"name": "Email",
|
||||||
"possibleTypes": null
|
"possibleTypes": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": null,
|
||||||
|
"enumValues": null,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"args": [],
|
||||||
|
"deprecationReason": null,
|
||||||
|
"description": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"name": "threadId",
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": [],
|
||||||
|
"deprecationReason": null,
|
||||||
|
"description": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"name": "subject",
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": [],
|
||||||
|
"deprecationReason": null,
|
||||||
|
"description": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"name": "messages",
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "LIST",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Message",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inputFields": null,
|
||||||
|
"interfaces": [],
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "EmailThread",
|
||||||
|
"possibleTypes": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).",
|
"description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).",
|
||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
@ -1056,7 +1123,7 @@
|
|||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "UNION",
|
||||||
"name": "Thread",
|
"name": "Thread",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
@ -1157,69 +1224,18 @@
|
|||||||
{
|
{
|
||||||
"description": null,
|
"description": null,
|
||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
"fields": [
|
"fields": null,
|
||||||
{
|
|
||||||
"args": [],
|
|
||||||
"deprecationReason": null,
|
|
||||||
"description": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"name": "threadId",
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"args": [],
|
|
||||||
"deprecationReason": null,
|
|
||||||
"description": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"name": "subject",
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"args": [],
|
|
||||||
"deprecationReason": null,
|
|
||||||
"description": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"name": "messages",
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "LIST",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "OBJECT",
|
|
||||||
"name": "Message",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inputFields": null,
|
"inputFields": null,
|
||||||
"interfaces": [],
|
"interfaces": null,
|
||||||
"kind": "OBJECT",
|
"kind": "UNION",
|
||||||
"name": "Thread",
|
"name": "Thread",
|
||||||
"possibleTypes": null
|
"possibleTypes": [
|
||||||
|
{
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "EmailThread",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": null,
|
"description": null,
|
||||||
|
|||||||
@ -1,47 +1,49 @@
|
|||||||
query ShowThreadQuery($threadId: String!) {
|
query ShowThreadQuery($threadId: String!) {
|
||||||
thread(threadId: $threadId) {
|
thread(threadId: $threadId) {
|
||||||
threadId,
|
__typename ... on EmailThread{
|
||||||
subject
|
threadId,
|
||||||
messages {
|
|
||||||
id
|
|
||||||
subject
|
subject
|
||||||
tags
|
messages {
|
||||||
from {
|
|
||||||
name
|
|
||||||
addr
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
name
|
|
||||||
addr
|
|
||||||
}
|
|
||||||
cc {
|
|
||||||
name
|
|
||||||
addr
|
|
||||||
}
|
|
||||||
timestamp
|
|
||||||
body {
|
|
||||||
__typename
|
|
||||||
... on UnhandledContentType {
|
|
||||||
contents
|
|
||||||
contentTree
|
|
||||||
}
|
|
||||||
... on PlainText {
|
|
||||||
contents
|
|
||||||
contentTree
|
|
||||||
}
|
|
||||||
... on Html {
|
|
||||||
contents
|
|
||||||
contentTree
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path
|
|
||||||
attachments {
|
|
||||||
id
|
id
|
||||||
idx
|
subject
|
||||||
filename
|
tags
|
||||||
contentType
|
from {
|
||||||
contentId
|
name
|
||||||
size
|
addr
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
name
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
cc {
|
||||||
|
name
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
timestamp
|
||||||
|
body {
|
||||||
|
__typename
|
||||||
|
... on UnhandledContentType {
|
||||||
|
contents
|
||||||
|
contentTree
|
||||||
|
}
|
||||||
|
... on PlainText {
|
||||||
|
contents
|
||||||
|
contentTree
|
||||||
|
}
|
||||||
|
... on Html {
|
||||||
|
contents
|
||||||
|
contentTree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path
|
||||||
|
attachments {
|
||||||
|
id
|
||||||
|
idx
|
||||||
|
filename
|
||||||
|
contentType
|
||||||
|
contentId
|
||||||
|
size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -341,25 +341,28 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
let mut open_messages: HashSet<_> = data
|
match &data.thread {
|
||||||
.thread
|
graphql::show_thread_query::ShowThreadQueryThread::EmailThread(
|
||||||
.messages
|
ShowThreadQueryThreadOnEmailThread {
|
||||||
.iter()
|
thread_id,
|
||||||
.filter(|msg| msg.tags.iter().any(|t| t == "unread"))
|
subject,
|
||||||
.map(|msg| msg.id.clone())
|
messages,
|
||||||
.collect();
|
},
|
||||||
if open_messages.is_empty() {
|
) => {
|
||||||
open_messages = data
|
let mut open_messages: HashSet<_> = messages
|
||||||
.thread
|
.iter()
|
||||||
.messages
|
.filter(|msg| msg.tags.iter().any(|t| t == "unread"))
|
||||||
.iter()
|
.map(|msg| msg.id.clone())
|
||||||
.map(|msg| msg.id.clone())
|
.collect();
|
||||||
.collect();
|
if open_messages.is_empty() {
|
||||||
|
open_messages = messages.iter().map(|msg| msg.id.clone()).collect();
|
||||||
|
}
|
||||||
|
model.context = Context::ThreadResult {
|
||||||
|
thread: data.thread,
|
||||||
|
open_messages,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
model.context = Context::ThreadResult {
|
|
||||||
thread: data.thread,
|
|
||||||
open_messages,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Msg::ShowThreadResult(bad) => {
|
Msg::ShowThreadResult(bad) => {
|
||||||
error!("show_thread_query error: {bad:#?}");
|
error!("show_thread_query error: {bad:#?}");
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use seed_hooks::{state_access::CloneState, topo, use_state};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::urls,
|
api::urls,
|
||||||
|
graphql::show_thread_query::*,
|
||||||
state::{Context, Model, Msg},
|
state::{Context, Model, Msg},
|
||||||
view::{self, view_header, view_search_results, view_tags},
|
view::{self, view_header, view_search_results, view_tags},
|
||||||
};
|
};
|
||||||
@ -15,7 +16,7 @@ pub(super) fn view(model: &Model) -> Node<Msg> {
|
|||||||
let content = match &model.context {
|
let content = match &model.context {
|
||||||
Context::None => div![h1!["Loading"]],
|
Context::None => div![h1!["Loading"]],
|
||||||
Context::ThreadResult {
|
Context::ThreadResult {
|
||||||
thread,
|
thread: ShowThreadQueryThread::EmailThread(thread),
|
||||||
open_messages,
|
open_messages,
|
||||||
} => view::thread(thread, open_messages, show_icon_text),
|
} => view::thread(thread, open_messages, show_icon_text),
|
||||||
Context::SearchResult {
|
Context::SearchResult {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use seed::{prelude::*, *};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::urls,
|
api::urls,
|
||||||
graphql::front_page_query::*,
|
graphql::{front_page_query::*, show_thread_query::*},
|
||||||
state::{Context, Model, Msg},
|
state::{Context, Model, Msg},
|
||||||
view::{
|
view::{
|
||||||
self, human_age, pretty_authors, search_toolbar, set_title, tags_chiclet, view_header,
|
self, human_age, pretty_authors, search_toolbar, set_title, tags_chiclet, view_header,
|
||||||
@ -18,7 +18,7 @@ pub(super) fn view(model: &Model) -> Node<Msg> {
|
|||||||
let content = match &model.context {
|
let content = match &model.context {
|
||||||
Context::None => div![h1!["Loading"]],
|
Context::None => div![h1!["Loading"]],
|
||||||
Context::ThreadResult {
|
Context::ThreadResult {
|
||||||
thread,
|
thread: ShowThreadQueryThread::EmailThread(thread),
|
||||||
open_messages,
|
open_messages,
|
||||||
} => view::thread(thread, open_messages, show_icon_text),
|
} => view::thread(thread, open_messages, show_icon_text),
|
||||||
Context::SearchResult {
|
Context::SearchResult {
|
||||||
|
|||||||
@ -394,9 +394,9 @@ macro_rules! implement_email {
|
|||||||
}
|
}
|
||||||
|
|
||||||
implement_email!(
|
implement_email!(
|
||||||
ShowThreadQueryThreadMessagesTo,
|
ShowThreadQueryThreadOnEmailThreadMessagesTo,
|
||||||
ShowThreadQueryThreadMessagesCc,
|
ShowThreadQueryThreadOnEmailThreadMessagesCc,
|
||||||
ShowThreadQueryThreadMessagesFrom
|
ShowThreadQueryThreadOnEmailThreadMessagesFrom
|
||||||
);
|
);
|
||||||
|
|
||||||
fn raw_text_message(contents: &str) -> Node<Msg> {
|
fn raw_text_message(contents: &str) -> Node<Msg> {
|
||||||
@ -467,13 +467,13 @@ fn render_avatar(avatar: Option<String>, from: &str) -> Node<Msg> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
fn render_open_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<Msg> {
|
||||||
let (from, from_detail) = match &msg.from {
|
let (from, from_detail) = match &msg.from {
|
||||||
Some(ShowThreadQueryThreadMessagesFrom {
|
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
addr,
|
addr,
|
||||||
}) => (name.to_string(), addr.clone()),
|
}) => (name.to_string(), addr.clone()),
|
||||||
Some(ShowThreadQueryThreadMessagesFrom {
|
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
|
||||||
addr: Some(addr), ..
|
addr: Some(addr), ..
|
||||||
}) => (addr.to_string(), None),
|
}) => (addr.to_string(), None),
|
||||||
_ => (String::from("UNKNOWN"), None),
|
_ => (String::from("UNKNOWN"), None),
|
||||||
@ -516,15 +516,15 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
|||||||
if i>0 { ", " }else { "" },
|
if i>0 { ", " }else { "" },
|
||||||
{
|
{
|
||||||
let to = match to {
|
let to = match to {
|
||||||
ShowThreadQueryThreadMessagesTo {
|
ShowThreadQueryThreadOnEmailThreadMessagesTo {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
addr:Some(addr),
|
addr:Some(addr),
|
||||||
} => format!("{name} <{addr}>"),
|
} => format!("{name} <{addr}>"),
|
||||||
ShowThreadQueryThreadMessagesTo {
|
ShowThreadQueryThreadOnEmailThreadMessagesTo {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
addr:None
|
addr:None
|
||||||
} => format!("{name}"),
|
} => format!("{name}"),
|
||||||
ShowThreadQueryThreadMessagesTo {
|
ShowThreadQueryThreadOnEmailThreadMessagesTo {
|
||||||
addr: Some(addr), ..
|
addr: Some(addr), ..
|
||||||
} => format!("{addr}"),
|
} => format!("{addr}"),
|
||||||
_ => String::from("UNKNOWN"),
|
_ => String::from("UNKNOWN"),
|
||||||
@ -553,15 +553,15 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
|||||||
if i>0 { ", " }else { "" },
|
if i>0 { ", " }else { "" },
|
||||||
{
|
{
|
||||||
let cc = match cc {
|
let cc = match cc {
|
||||||
ShowThreadQueryThreadMessagesCc {
|
ShowThreadQueryThreadOnEmailThreadMessagesCc {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
addr:Some(addr),
|
addr:Some(addr),
|
||||||
} => format!("{name} <{addr}>"),
|
} => format!("{name} <{addr}>"),
|
||||||
ShowThreadQueryThreadMessagesCc {
|
ShowThreadQueryThreadOnEmailThreadMessagesCc {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
addr:None
|
addr:None
|
||||||
} => format!("{name}"),
|
} => format!("{name}"),
|
||||||
ShowThreadQueryThreadMessagesCc {
|
ShowThreadQueryThreadOnEmailThreadMessagesCc {
|
||||||
addr: Some(addr), ..
|
addr: Some(addr), ..
|
||||||
} => format!("<{addr}>"),
|
} => format!("<{addr}>"),
|
||||||
_ => String::from("UNKNOWN"),
|
_ => String::from("UNKNOWN"),
|
||||||
@ -609,12 +609,12 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_closed_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
fn render_closed_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<Msg> {
|
||||||
let from: String = match &msg.from {
|
let from: String = match &msg.from {
|
||||||
Some(ShowThreadQueryThreadMessagesFrom {
|
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
|
||||||
name: Some(name), ..
|
name: Some(name), ..
|
||||||
}) => name.to_string(),
|
}) => name.to_string(),
|
||||||
Some(ShowThreadQueryThreadMessagesFrom {
|
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
|
||||||
addr: Some(addr), ..
|
addr: Some(addr), ..
|
||||||
}) => addr.to_string(),
|
}) => addr.to_string(),
|
||||||
_ => String::from("UNKNOWN"),
|
_ => String::from("UNKNOWN"),
|
||||||
@ -683,7 +683,7 @@ fn render_closed_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg> {
|
fn message_render(msg: &ShowThreadQueryThreadOnEmailThreadMessages, open: bool) -> Node<Msg> {
|
||||||
let expand_id = msg.id.clone();
|
let expand_id = msg.id.clone();
|
||||||
div![
|
div![
|
||||||
C!["message"],
|
C!["message"],
|
||||||
@ -707,16 +707,16 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
|
|||||||
div![
|
div![
|
||||||
C!["body"],
|
C!["body"],
|
||||||
match &msg.body {
|
match &msg.body {
|
||||||
ShowThreadQueryThreadMessagesBody::UnhandledContentType(
|
ShowThreadQueryThreadOnEmailThreadMessagesBody::UnhandledContentType(
|
||||||
ShowThreadQueryThreadMessagesBodyOnUnhandledContentType { contents ,content_tree},
|
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnUnhandledContentType { contents ,content_tree},
|
||||||
) => div![
|
) => div![
|
||||||
raw_text_message(&contents),
|
raw_text_message(&contents),
|
||||||
div![C!["error"],
|
div![C!["error"],
|
||||||
view_content_tree(&content_tree),
|
view_content_tree(&content_tree),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
ShowThreadQueryThreadMessagesBody::PlainText(
|
ShowThreadQueryThreadOnEmailThreadMessagesBody::PlainText(
|
||||||
ShowThreadQueryThreadMessagesBodyOnPlainText {
|
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnPlainText {
|
||||||
contents,
|
contents,
|
||||||
content_tree,
|
content_tree,
|
||||||
},
|
},
|
||||||
@ -724,8 +724,8 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
|
|||||||
raw_text_message(&contents),
|
raw_text_message(&contents),
|
||||||
view_content_tree(&content_tree),
|
view_content_tree(&content_tree),
|
||||||
],
|
],
|
||||||
ShowThreadQueryThreadMessagesBody::Html(
|
ShowThreadQueryThreadOnEmailThreadMessagesBody::Html(
|
||||||
ShowThreadQueryThreadMessagesBodyOnHtml {
|
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnHtml {
|
||||||
contents,
|
contents,
|
||||||
content_tree,
|
content_tree,
|
||||||
},
|
},
|
||||||
@ -792,7 +792,7 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
|
|||||||
|
|
||||||
#[topo::nested]
|
#[topo::nested]
|
||||||
fn thread(
|
fn thread(
|
||||||
thread: &ShowThreadQueryThread,
|
thread: &ShowThreadQueryThreadOnEmailThread,
|
||||||
open_messages: &HashSet<String>,
|
open_messages: &HashSet<String>,
|
||||||
show_icon_text: bool,
|
show_icon_text: bool,
|
||||||
) -> Node<Msg> {
|
) -> Node<Msg> {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use seed::{prelude::*, *};
|
use seed::{prelude::*, *};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
graphql::show_thread_query::*,
|
||||||
state::{Context, Model, Msg},
|
state::{Context, Model, Msg},
|
||||||
view::{self, view_header, view_search_results, view_tags},
|
view::{self, view_header, view_search_results, view_tags},
|
||||||
};
|
};
|
||||||
@ -12,7 +13,7 @@ pub(super) fn view(model: &Model) -> Node<Msg> {
|
|||||||
let content = match &model.context {
|
let content = match &model.context {
|
||||||
Context::None => div![h1!["Loading"]],
|
Context::None => div![h1!["Loading"]],
|
||||||
Context::ThreadResult {
|
Context::ThreadResult {
|
||||||
thread,
|
thread: ShowThreadQueryThread::EmailThread(thread),
|
||||||
open_messages,
|
open_messages,
|
||||||
} => view::thread(thread, open_messages, show_icon_text),
|
} => view::thread(thread, open_messages, show_icon_text),
|
||||||
Context::SearchResult {
|
Context::SearchResult {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user