From 5cae71653fb3b973e61c61c109e2aac05a463cc1 Mon Sep 17 00:00:00 2001
From: Eli Ribble <eli@theribbles.org>
Date: Wed, 4 Sep 2024 11:39:44 -0700
Subject: [PATCH] Space between when sent time, from, and subject in email
 summary

This is the first time I'm creating some custom style. There's probably
a way to do this with Bootstrap that I'm not expert enough to know
about.

For now I'm just scratching itches.
---
 src/EmailSummary.tsx         | 23 +++++++++++++----------
 src/client/Client.tsx        |  2 +-
 src/client/types.tsx         |  2 +-
 src/components/DateTime.tsx  | 30 ++++++++++++++++++++++--------
 src/components/EmailFrom.tsx | 20 ++++++++++++++++++++
 src/style.scss               | 12 ++++++++++++
 6 files changed, 69 insertions(+), 20 deletions(-)
 create mode 100644 src/components/EmailFrom.tsx

diff --git a/src/EmailSummary.tsx b/src/EmailSummary.tsx
index 66d3517..334231d 100644
--- a/src/EmailSummary.tsx
+++ b/src/EmailSummary.tsx
@@ -4,9 +4,11 @@ import ButtonGroup from "react-bootstrap/ButtonGroup";
 import ButtonToolbar from "react-bootstrap/ButtonToolbar";
 import Placeholder from "react-bootstrap/Placeholder";
 import React from "react";
+import Stack from "react-bootstrap/Stack";
 
 import Client from "./client/Client";
 import DateTime from "./components/DateTime";
+import EmailFrom from "./components/EmailFrom";
 import { IAccount, IEmailStub, IMailbox } from "./client/types";
 
 type EmailSummaryProps = {
@@ -49,17 +51,18 @@ class EmailSummary extends React.Component<
 			return <Placeholder />;
 		}
 		return (
-			<div className="p-2 border" key={this.props.emailId}>
+			<Stack
+				direction="horizontal"
+				className="email-summary"
+				key={this.props.emailId}
+			>
+				<DateTime className="received" d={stub.receivedAt} />
+				<EmailFrom froms={stub.from} />
+				<div>{stub.from == null ? "?" : stub.from[0].name}</div>
 				<a className="btn" href={href}>
-					<DateTime d={stub.receivedAt} />
-					<span>
-						{" - " +
-							(stub.from == null ? "?" : stub.from[0].name) +
-							" - " +
-							stub.subject}
-					</span>
+					<div>{stub.subject}</div>
 				</a>
-				<ButtonToolbar>
+				<ButtonToolbar className="ms-auto">
 					<ButtonGroup className="me-2">
 						<Button
 							onClick={() => {
@@ -74,7 +77,7 @@ class EmailSummary extends React.Component<
 						<Button>2</Button>
 					</ButtonGroup>
 				</ButtonToolbar>
-			</div>
+			</Stack>
 		);
 	}
 }
diff --git a/src/client/Client.tsx b/src/client/Client.tsx
index 25eb9ab..bd3e460 100644
--- a/src/client/Client.tsx
+++ b/src/client/Client.tsx
@@ -241,7 +241,7 @@ export default class Client {
 						);
 					}
 					this.state.session.emailStubs[e.id] = {
-						from: e.from,
+						from: e.from === null ? [] : e.from,
 						id: e.id,
 						mailboxIds: e.mailboxIds,
 						receivedAt: e.receivedAt,
diff --git a/src/client/types.tsx b/src/client/types.tsx
index e8fa48c..a251cd0 100644
--- a/src/client/types.tsx
+++ b/src/client/types.tsx
@@ -2,7 +2,7 @@ import * as client from "./jmap-client-ts/src/types";
 
 export type MailboxIdMap = { [mailboxId: string]: boolean };
 export interface IEmailStub {
-	from: Array<client.IEmailAddress> | null;
+	from: Array<client.IEmailAddress>;
 	id: string;
 	mailboxIds: MailboxIdMap;
 	receivedAt: string;
diff --git a/src/components/DateTime.tsx b/src/components/DateTime.tsx
index 38c2148..91222cd 100644
--- a/src/components/DateTime.tsx
+++ b/src/components/DateTime.tsx
@@ -4,16 +4,30 @@ type DateTimeProps = {
 	d: string;
 };
 
-const DateTime: React.FC<DateTimeProps> = ({ d }) => {
-	const datetime = Date.parse(d);
+const DateTime: React.FC<
+	DateTimeProps & React.HTMLAttributes<HTMLSpanElement>
+> = (props) => {
+	const datetime = Date.parse(props.d);
 	const now = Date.now();
 	const diff = (now - datetime) / 1000;
-	if (diff < 30) return <span>moments ago</span>;
-	if (diff < 60) return <span>{diff}s</span>;
-	if (diff < 60 * 60) return <span>{Math.round(diff / 60)}m</span>;
-	if (diff < 60 * 60 * 48) return <span>{Math.round(diff / (60 * 60))}h</span>;
+	if (diff < 30) return <span className={props.className}>moments ago</span>;
+	if (diff < 60) return <span className={props.className}>{diff}s</span>;
+	if (diff < 60 * 60)
+		return <span className={props.className}>{Math.round(diff / 60)}m</span>;
+	if (diff < 60 * 60 * 48)
+		return (
+			<span className={props.className}>{Math.round(diff / (60 * 60))}h</span>
+		);
 	if (diff < 60 * 60 * 24 * 365)
-		return <span>{Math.round(diff / (60 * 60 * 24))}d</span>;
-	return <span>{Math.round(diff / (60 * 60 * 24 * 365))}y</span>;
+		return (
+			<span className={props.className}>
+				{Math.round(diff / (60 * 60 * 24))}d
+			</span>
+		);
+	return (
+		<span className={props.className}>
+			{Math.round(diff / (60 * 60 * 24 * 365))}y
+		</span>
+	);
 };
 export default DateTime;
diff --git a/src/components/EmailFrom.tsx b/src/components/EmailFrom.tsx
new file mode 100644
index 0000000..aa174a2
--- /dev/null
+++ b/src/components/EmailFrom.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+import * as client from "../client/jmap-client-ts/src/types";
+
+type EmailFromProps = {
+	froms: Array<client.IEmailAddress>;
+};
+
+const EmailFrom: React.FC<EmailFromProps> = ({ froms }) => {
+	if (froms.length === 0) {
+		return <span className="email-from">None</span>;
+	}
+	if (froms.length > 1) {
+		return <span className="email-from">MANY?</span>;
+	}
+	if (froms[0].name) {
+		return <span className="email-from">{froms[0].name}</span>;
+	}
+	return <span className="email-from">{froms[0].email}</span>;
+};
+export default EmailFrom;
diff --git a/src/style.scss b/src/style.scss
index 5de3350..e8cabd0 100644
--- a/src/style.scss
+++ b/src/style.scss
@@ -1 +1,13 @@
 @import '~bootstrap/scss/bootstrap';
+
+.email-summary {
+	.email-from {
+		overflow: hidden;
+		text-overflow: ellipsis;
+		width: 200px;
+	}
+	.received {
+		width: 50px;
+	}
+}
+