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:
2024-08-26 21:48:53 -07:00
parent 446fcfe37f
commit 760cec01a8
10 changed files with 190 additions and 161 deletions

View File

@@ -290,6 +290,73 @@
"name": "Email",
"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).",
"enumValues": null,
@@ -1056,7 +1123,7 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"kind": "UNION",
"name": "Thread",
"ofType": null
}
@@ -1157,69 +1224,18 @@
{
"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
}
}
}
}
}
],
"fields": null,
"inputFields": null,
"interfaces": [],
"kind": "OBJECT",
"interfaces": null,
"kind": "UNION",
"name": "Thread",
"possibleTypes": null
"possibleTypes": [
{
"kind": "OBJECT",
"name": "EmailThread",
"ofType": null
}
]
},
{
"description": null,

View File

@@ -1,47 +1,49 @@
query ShowThreadQuery($threadId: String!) {
thread(threadId: $threadId) {
threadId,
subject
messages {
id
__typename ... on EmailThread{
threadId,
subject
tags
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 {
messages {
id
idx
filename
contentType
contentId
size
subject
tags
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
idx
filename
contentType
contentId
size
}
}
}
}

View File

@@ -341,25 +341,28 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
})
.collect(),
);
let mut open_messages: HashSet<_> = data
.thread
.messages
.iter()
.filter(|msg| msg.tags.iter().any(|t| t == "unread"))
.map(|msg| msg.id.clone())
.collect();
if open_messages.is_empty() {
open_messages = data
.thread
.messages
.iter()
.map(|msg| msg.id.clone())
.collect();
match &data.thread {
graphql::show_thread_query::ShowThreadQueryThread::EmailThread(
ShowThreadQueryThreadOnEmailThread {
thread_id,
subject,
messages,
},
) => {
let mut open_messages: HashSet<_> = messages
.iter()
.filter(|msg| msg.tags.iter().any(|t| t == "unread"))
.map(|msg| msg.id.clone())
.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) => {
error!("show_thread_query error: {bad:#?}");

View File

@@ -3,6 +3,7 @@ use seed_hooks::{state_access::CloneState, topo, use_state};
use crate::{
api::urls,
graphql::show_thread_query::*,
state::{Context, Model, Msg},
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 {
Context::None => div![h1!["Loading"]],
Context::ThreadResult {
thread,
thread: ShowThreadQueryThread::EmailThread(thread),
open_messages,
} => view::thread(thread, open_messages, show_icon_text),
Context::SearchResult {

View File

@@ -4,7 +4,7 @@ use seed::{prelude::*, *};
use crate::{
api::urls,
graphql::front_page_query::*,
graphql::{front_page_query::*, show_thread_query::*},
state::{Context, Model, Msg},
view::{
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 {
Context::None => div![h1!["Loading"]],
Context::ThreadResult {
thread,
thread: ShowThreadQueryThread::EmailThread(thread),
open_messages,
} => view::thread(thread, open_messages, show_icon_text),
Context::SearchResult {

View File

@@ -394,9 +394,9 @@ macro_rules! implement_email {
}
implement_email!(
ShowThreadQueryThreadMessagesTo,
ShowThreadQueryThreadMessagesCc,
ShowThreadQueryThreadMessagesFrom
ShowThreadQueryThreadOnEmailThreadMessagesTo,
ShowThreadQueryThreadOnEmailThreadMessagesCc,
ShowThreadQueryThreadOnEmailThreadMessagesFrom
);
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 {
Some(ShowThreadQueryThreadMessagesFrom {
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
name: Some(name),
addr,
}) => (name.to_string(), addr.clone()),
Some(ShowThreadQueryThreadMessagesFrom {
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
addr: Some(addr), ..
}) => (addr.to_string(), None),
_ => (String::from("UNKNOWN"), None),
@@ -516,15 +516,15 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
if i>0 { ", " }else { "" },
{
let to = match to {
ShowThreadQueryThreadMessagesTo {
ShowThreadQueryThreadOnEmailThreadMessagesTo {
name: Some(name),
addr:Some(addr),
} => format!("{name} <{addr}>"),
ShowThreadQueryThreadMessagesTo {
ShowThreadQueryThreadOnEmailThreadMessagesTo {
name: Some(name),
addr:None
} => format!("{name}"),
ShowThreadQueryThreadMessagesTo {
ShowThreadQueryThreadOnEmailThreadMessagesTo {
addr: Some(addr), ..
} => format!("{addr}"),
_ => String::from("UNKNOWN"),
@@ -553,15 +553,15 @@ fn render_open_header(msg: &ShowThreadQueryThreadMessages) -> Node<Msg> {
if i>0 { ", " }else { "" },
{
let cc = match cc {
ShowThreadQueryThreadMessagesCc {
ShowThreadQueryThreadOnEmailThreadMessagesCc {
name: Some(name),
addr:Some(addr),
} => format!("{name} <{addr}>"),
ShowThreadQueryThreadMessagesCc {
ShowThreadQueryThreadOnEmailThreadMessagesCc {
name: Some(name),
addr:None
} => format!("{name}"),
ShowThreadQueryThreadMessagesCc {
ShowThreadQueryThreadOnEmailThreadMessagesCc {
addr: Some(addr), ..
} => format!("<{addr}>"),
_ => 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 {
Some(ShowThreadQueryThreadMessagesFrom {
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
name: Some(name), ..
}) => name.to_string(),
Some(ShowThreadQueryThreadMessagesFrom {
Some(ShowThreadQueryThreadOnEmailThreadMessagesFrom {
addr: Some(addr), ..
}) => addr.to_string(),
_ => 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();
div![
C!["message"],
@@ -707,16 +707,16 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
div![
C!["body"],
match &msg.body {
ShowThreadQueryThreadMessagesBody::UnhandledContentType(
ShowThreadQueryThreadMessagesBodyOnUnhandledContentType { contents ,content_tree},
ShowThreadQueryThreadOnEmailThreadMessagesBody::UnhandledContentType(
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnUnhandledContentType { contents ,content_tree},
) => div![
raw_text_message(&contents),
div![C!["error"],
view_content_tree(&content_tree),
]
],
ShowThreadQueryThreadMessagesBody::PlainText(
ShowThreadQueryThreadMessagesBodyOnPlainText {
ShowThreadQueryThreadOnEmailThreadMessagesBody::PlainText(
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnPlainText {
contents,
content_tree,
},
@@ -724,8 +724,8 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
raw_text_message(&contents),
view_content_tree(&content_tree),
],
ShowThreadQueryThreadMessagesBody::Html(
ShowThreadQueryThreadMessagesBodyOnHtml {
ShowThreadQueryThreadOnEmailThreadMessagesBody::Html(
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnHtml {
contents,
content_tree,
},
@@ -792,7 +792,7 @@ fn message_render(msg: &ShowThreadQueryThreadMessages, open: bool) -> Node<Msg>
#[topo::nested]
fn thread(
thread: &ShowThreadQueryThread,
thread: &ShowThreadQueryThreadOnEmailThread,
open_messages: &HashSet<String>,
show_icon_text: bool,
) -> Node<Msg> {

View File

@@ -1,6 +1,7 @@
use seed::{prelude::*, *};
use crate::{
graphql::show_thread_query::*,
state::{Context, Model, Msg},
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 {
Context::None => div![h1!["Loading"]],
Context::ThreadResult {
thread,
thread: ShowThreadQueryThread::EmailThread(thread),
open_messages,
} => view::thread(thread, open_messages, show_icon_text),
Context::SearchResult {