diff --git a/monero-sys/monero b/monero-sys/monero
index dbbccecc..5f714f14 160000
--- a/monero-sys/monero
+++ b/monero-sys/monero
@@ -1 +1 @@
-Subproject commit dbbccecc89e1121762a4ad6b531638ece82aa0c7
+Subproject commit 5f714f147fd29228698070e6bd80e41ce2f86fb0
diff --git a/src-gui/src/renderer/components/other/Units.tsx b/src-gui/src/renderer/components/other/Units.tsx
index 32fb7a00..78ab3df7 100644
--- a/src-gui/src/renderer/components/other/Units.tsx
+++ b/src-gui/src/renderer/components/other/Units.tsx
@@ -1,4 +1,4 @@
-import { Tooltip } from "@mui/material";
+import { Box, SxProps, Tooltip, Typography } from "@mui/material";
import { useAppSelector, useSettings } from "store/hooks";
import { getMarkup, piconerosToXmr, satsToBtc } from "utils/conversionUtils";
@@ -10,12 +10,18 @@ export function AmountWithUnit({
fixedPrecision,
exchangeRate,
parenthesisText = null,
+ labelStyles,
+ amountStyles,
+ disableTooltip = false,
}: {
amount: Amount;
unit: string;
fixedPrecision: number;
exchangeRate?: Amount;
parenthesisText?: string;
+ labelStyles?: SxProps;
+ amountStyles?: SxProps;
+ disableTooltip?: boolean;
}) {
const [fetchFiatPrices, fiatCurrency] = useSettings((settings) => [
settings.fetchFiatPrices,
@@ -29,12 +35,25 @@ export function AmountWithUnit({
? `≈ ${(exchangeRate * amount).toFixed(2)} ${fiatCurrency}`
: "";
+ const content = (
+
+
+ {amount != null ? amount.toFixed(fixedPrecision) : "?"}
+ {" "}
+
+ {unit}
+ {parenthesisText != null ? ` (${parenthesisText})` : null}
+
+
+ );
+
+ if (disableTooltip) {
+ return content;
+ }
+
return (
-
- {amount != null ? amount.toFixed(fixedPrecision) : "?"} {unit}
- {parenthesisText != null ? ` (${parenthesisText})` : null}
-
+ {content}
);
}
@@ -89,9 +108,15 @@ export function BitcoinAmount({ amount }: { amount: Amount }) {
export function MoneroAmount({
amount,
fixedPrecision = 4,
+ labelStyles,
+ amountStyles,
+ disableTooltip = false,
}: {
amount: Amount;
fixedPrecision?: number;
+ labelStyles?: SxProps;
+ amountStyles?: SxProps;
+ disableTooltip?: boolean;
}) {
const xmrRate = useAppSelector((state) => state.rates.xmrPrice);
@@ -101,6 +126,9 @@ export function MoneroAmount({
unit="XMR"
fixedPrecision={fixedPrecision}
exchangeRate={xmrRate}
+ labelStyles={labelStyles}
+ amountStyles={amountStyles}
+ disableTooltip={disableTooltip}
/>
);
}
@@ -164,14 +192,23 @@ export function SatsAmount({ amount }: { amount: Amount }) {
export function PiconeroAmount({
amount,
fixedPrecision = 8,
+ labelStyles,
+ amountStyles,
+ disableTooltip = false,
}: {
amount: Amount;
fixedPrecision?: number;
+ labelStyles?: SxProps;
+ amountStyles?: SxProps;
+ disableTooltip?: boolean;
}) {
return (
);
}
diff --git a/src-gui/src/renderer/components/pages/monero/components/ConfirmationsBadge.tsx b/src-gui/src/renderer/components/pages/monero/components/ConfirmationsBadge.tsx
new file mode 100644
index 00000000..cc9f27c2
--- /dev/null
+++ b/src-gui/src/renderer/components/pages/monero/components/ConfirmationsBadge.tsx
@@ -0,0 +1,50 @@
+import { Box, Chip, Tooltip, Typography } from "@mui/material";
+import {
+ AutoAwesome as AutoAwesomeIcon,
+ CheckCircleOutline as CheckCircleOutlineIcon,
+} from "@mui/icons-material";
+
+export default function ConfirmationsBadge({
+ confirmations,
+}: {
+ confirmations: number;
+}) {
+ if (confirmations === 0) {
+ return (
+ }
+ label="Published"
+ color="secondary"
+ size="small"
+ />
+ );
+ } else if (confirmations < 10) {
+ const label = (
+ <>
+
+
+ {confirmations}
+
+ /10
+
+ >
+ );
+ return ;
+ } else {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/src-gui/src/renderer/components/pages/monero/components/TransactionHistory.tsx b/src-gui/src/renderer/components/pages/monero/components/TransactionHistory.tsx
index 4950e077..1075b693 100644
--- a/src-gui/src/renderer/components/pages/monero/components/TransactionHistory.tsx
+++ b/src-gui/src/renderer/components/pages/monero/components/TransactionHistory.tsx
@@ -1,25 +1,8 @@
-import {
- Typography,
- Card,
- CardContent,
- Table,
- TableBody,
- TableCell,
- TableContainer,
- TableHead,
- TableRow,
- Paper,
- Chip,
- IconButton,
- Tooltip,
- Stack,
-} from "@mui/material";
-import { OpenInNew as OpenInNewIcon } from "@mui/icons-material";
-import { open } from "@tauri-apps/plugin-shell";
-import { PiconeroAmount } from "../../../other/Units";
-import { getMoneroTxExplorerUrl } from "../../../../../utils/conversionUtils";
-import { isTestnet } from "store/config";
+import { Typography, Box, Paper } from "@mui/material";
import { TransactionInfo } from "models/tauriModel";
+import _ from "lodash";
+import dayjs from "dayjs";
+import TransactionItem from "./TransactionItem";
interface TransactionHistoryProps {
history?: {
@@ -27,76 +10,52 @@ interface TransactionHistoryProps {
};
}
+interface TransactionGroup {
+ date: string;
+ displayDate: string;
+ transactions: TransactionInfo[];
+}
+
// Component for displaying transaction history
export default function TransactionHistory({
history,
}: TransactionHistoryProps) {
if (!history || !history.transactions || history.transactions.length === 0) {
- return Transaction History;
+ return Transactions;
}
- return (
- <>
- Transaction History
+ const transactions = history.transactions;
-
-
-
-
- Amount
- Fee
- Confirmations
- Explorer
-
-
-
- {[...history.transactions]
- .sort((a, b) => a.confirmations - b.confirmations)
- .map((tx, index) => (
-
-
-
-
-
-
-
-
-
-
-
- = 10 ? "success" : "warning"}
- size="small"
- />
-
-
- {tx.tx_hash && (
-
- {
- const url = getMoneroTxExplorerUrl(
- tx.tx_hash,
- isTestnet(),
- );
- open(url);
- }}
- >
-
-
-
- )}
-
-
+ // Group transactions by date using dayjs and lodash
+ const transactionGroups: TransactionGroup[] = _(transactions)
+ .groupBy((tx) => dayjs(tx.timestamp * 1000).format("YYYY-MM-DD")) // Convert Unix timestamp to date string
+ .map((txs, dateKey) => ({
+ date: dateKey,
+ displayDate: dayjs(dateKey).format("MMMM D, YYYY"), // Human-readable format
+ transactions: _.orderBy(txs, ["timestamp"], ["desc"]), // Sort transactions within group by newest first
+ }))
+ .orderBy(["date"], ["desc"]) // Sort groups by newest date first
+ .value();
+
+ return (
+
+
+ Transactions
+
+
+ {transactionGroups.map((group) => (
+
+
+ {group.displayDate}
+
+
+ {group.transactions.map((tx) => (
+
))}
-
-
-
- >
+
+
+ ))}
+
+
);
}
diff --git a/src-gui/src/renderer/components/pages/monero/components/TransactionItem.tsx b/src-gui/src/renderer/components/pages/monero/components/TransactionItem.tsx
new file mode 100644
index 00000000..0d3faf7c
--- /dev/null
+++ b/src-gui/src/renderer/components/pages/monero/components/TransactionItem.tsx
@@ -0,0 +1,155 @@
+import {
+ Box,
+ Chip,
+ IconButton,
+ Menu,
+ MenuItem,
+ Typography,
+} from "@mui/material";
+import { TransactionDirection, TransactionInfo } from "models/tauriModel";
+import {
+ CallReceived as IncomingIcon,
+ MoreVert as MoreVertIcon,
+} from "@mui/icons-material";
+import { CallMade as OutgoingIcon } from "@mui/icons-material";
+import {
+ FiatPiconeroAmount,
+ PiconeroAmount,
+} from "renderer/components/other/Units";
+import ConfirmationsBadge from "./ConfirmationsBadge";
+import { getMoneroTxExplorerUrl } from "utils/conversionUtils";
+import { isTestnet } from "store/config";
+import { open } from "@tauri-apps/plugin-shell";
+import dayjs from "dayjs";
+import { useState } from "react";
+
+interface TransactionItemProps {
+ transaction: TransactionInfo;
+}
+
+export default function TransactionItem({ transaction }: TransactionItemProps) {
+ const isIncoming = transaction.direction === TransactionDirection.In;
+ const displayDate = dayjs(transaction.timestamp * 1000).format(
+ "MMM DD YYYY, HH:mm",
+ );
+
+ const amountStyles = isIncoming
+ ? { color: "success.tint" }
+ : { color: "error.tint" };
+
+ const [menuAnchorEl, setMenuAnchorEl] = useState(null);
+ const menuOpen = Boolean(menuAnchorEl);
+
+ return (
+
+
+
+ {isIncoming ? : }
+
+
+
+ ‐
+
+
+
+
+
+
+
+
+
+
+
+ {displayDate}
+
+
+ {
+ setMenuAnchorEl(event.currentTarget);
+ }}
+ >
+
+
+
+
+
+ );
+}
diff --git a/src-gui/src/renderer/components/pages/monero/components/WalletOverview.tsx b/src-gui/src/renderer/components/pages/monero/components/WalletOverview.tsx
index 5a0262d3..1f385b9e 100644
--- a/src-gui/src/renderer/components/pages/monero/components/WalletOverview.tsx
+++ b/src-gui/src/renderer/components/pages/monero/components/WalletOverview.tsx
@@ -72,6 +72,7 @@ export default function WalletOverview({