diff --git a/apps/web/src/index.tsx b/apps/web/src/index.tsx
index 16eac67..01fd1af 100644
--- a/apps/web/src/index.tsx
+++ b/apps/web/src/index.tsx
@@ -146,9 +146,11 @@ function AppShell() {
-
-
-
+
+
+
+
+
@@ -162,14 +164,6 @@ function CallInit() {
return null;
}
-function Chat() {
- return (
-
-
-
- );
-}
-
const rootRoute = createRootRoute({
component: RootShell,
});
@@ -234,7 +228,7 @@ const homeRoute = createRoute({
const chatRoute = createRoute({
getParentRoute: () => appRoute,
path: "chat",
- component: Chat,
+ component: ChatScreen,
validateSearch: z.object({
id: z.number().optional(),
}),
diff --git a/bun.lock b/bun.lock
index c93e836..70f4ecb 100644
--- a/bun.lock
+++ b/bun.lock
@@ -168,6 +168,8 @@
"name": "@tensamin/notifications",
"version": "0.0.0",
"dependencies": {
+ "@tauri-apps/api": "^2.11.0",
+ "@tensamin/chat": "workspace:*",
"@tensamin/crypto": "workspace:*",
"@tensamin/shared": "workspace:*",
"@tensamin/storage": "workspace:*",
@@ -1670,6 +1672,8 @@
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "@tensamin/notifications/@tauri-apps/api": ["@tauri-apps/api@2.11.0", "", {}, "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA=="],
+
"@tensamin/shared/sonner": ["sonner@1.7.4", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw=="],
"@tensamin/tauri/lucide-react": ["lucide-react@1.8.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-WuvlsjngSk7TnTBJ1hsCy3ql9V9VOdcPkd3PKcSmM34vJD8KG6molxz7m7zbYFgICwsanQWmJ13JlYs4Zp7Arw=="],
diff --git a/packages/call/todo.md b/packages/call/todo.md
index cbe5aa7..23ec7d7 100644
--- a/packages/call/todo.md
+++ b/packages/call/todo.md
@@ -5,4 +5,6 @@
- Avatar in the center
- Mobile
- Call invite popup
+ - Save call invite in `calls` array
- Sounds
+- Fullscreen button for screenshares
diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx
index 419c6fe..db4fc20 100644
--- a/packages/chat/src/components/message.tsx
+++ b/packages/chat/src/components/message.tsx
@@ -3,7 +3,7 @@ import type { RawMessage } from "../values";
import Text from "@tensamin/markdown/text";
import { AlertTriangle, Clock } from "lucide-react";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
+import { cn, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
import { useIsMobile } from "@tensamin/ui";
import {
ContextMenu,
@@ -20,22 +20,27 @@ function MessageComponent({
};
}) {
const isMobile = useIsMobile();
+ const actuallyFailed = message.failed && message.message_state === "awaiting";
return (
{message.failed && message.message_state === "awaiting" && (
diff --git a/packages/notifications/package.json b/packages/notifications/package.json
index 71c4fb2..af90c45 100644
--- a/packages/notifications/package.json
+++ b/packages/notifications/package.json
@@ -12,10 +12,12 @@
"build": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
- "@tensamin/ttp": "workspace:*",
- "@tensamin/shared": "workspace:*",
+ "@tauri-apps/api": "^2.11.0",
"@tensamin/crypto": "workspace:*",
+ "@tensamin/shared": "workspace:*",
+ "@tensamin/chat": "workspace:*",
"@tensamin/storage": "workspace:*",
+ "@tensamin/ttp": "workspace:*",
"@tensamin/user": "workspace:*",
"react": "^19.2.0",
"react-dom": "^19.2.0",
diff --git a/packages/notifications/src/context.tsx b/packages/notifications/src/context.tsx
index 1367eb5..7ba0d11 100644
--- a/packages/notifications/src/context.tsx
+++ b/packages/notifications/src/context.tsx
@@ -1,43 +1,92 @@
import { useCrypto } from "@tensamin/crypto/context";
import { useStorage } from "@tensamin/storage/context";
import { useUser } from "@tensamin/user/context";
+import { useChat } from "@tensamin/chat/context";
import { useTTP } from "@tensamin/ttp";
import { createContext, useEffect, useContext } from "react";
import z from "zod";
import { toast as sonnerToast } from "sonner";
import { message as messageSchema } from "@tensamin/shared/data";
+import { Avatar, AvatarFallback, AvatarImage } from "@tensamin/ui";
+import { isTauri } from "@tauri-apps/api/core";
export const context = createContext(undefined);
+function reduceDisplay(display: string) {
+ const words = display.split(" ");
+ if (words.length === 1) {
+ return display.slice(0, 2).toUpperCase();
+ } else {
+ return words[0].charAt(0).toUpperCase() + words[1].charAt(0).toUpperCase();
+ }
+}
+
export default function Provider(props: { children: React.ReactNode }) {
const { subscribePush } = useTTP();
const { load } = useStorage();
const { get } = useUser();
const { decryptText, getSharedSecret } = useCrypto();
+ const { addLiveMessage, userId } = useChat();
useEffect(() => {
- subscribePush(async (ttpMessage) => {
+ return subscribePush(async (ttpMessage) => {
if (ttpMessage.type === "message_live") {
const { message, sender_id } = ttpMessage.data as {
message: z.infer;
sender_id: number;
};
+ const user = await get(sender_id);
+
const decryptedContent = await decryptText(
await getSharedSecret(
await load("private_key"),
await get(await load("user_id")).then((data) => data.public_key),
- await get(sender_id).then((data) => data.public_key),
+ user.public_key,
),
message.content,
);
- sonnerToast(decryptedContent, {
- icon: A
,
- });
+ console.log(userId, sender_id, userId === sender_id);
+ if (userId === sender_id) {
+ addLiveMessage({
+ ...message,
+ content: decryptedContent,
+ sent_by_self: false,
+ });
+
+ return;
+ }
+
+ // add notification symbol to conversation cards
+
+ if (isTauri()) {
+ console.log("weewoo");
+ } else {
+ sonnerToast(user.display, {
+ classNames: {
+ content: "pl-4",
+ },
+ description: decryptedContent,
+ icon: (
+
+
+ {reduceDisplay(user.display)}
+
+ ),
+ });
+ }
}
});
- }, [subscribePush, decryptText, getSharedSecret, load, get]);
+ }, [
+ subscribePush,
+ decryptText,
+ getSharedSecret,
+ load,
+ get,
+ addLiveMessage,
+ userId,
+ ]);
return (
{} }}>
diff --git a/packages/notifications/todo.md b/packages/notifications/todo.md
new file mode 100644
index 0000000..599b984
--- /dev/null
+++ b/packages/notifications/todo.md
@@ -0,0 +1,3 @@
+- Tauri notifications
+- Mobile notifications channel setup
+- Add notification symbol / outline to user modal
diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts
index 3a73f95..3302875 100644
--- a/packages/shared/src/data.ts
+++ b/packages/shared/src/data.ts
@@ -22,7 +22,9 @@ export const message = z.object({
tint: z.string().length(7).startsWith("#").optional(),
avatar: z.boolean().optional(),
display: z.boolean().optional(),
- message_state: z.enum(["read", "received", "sent", "sending", "awaiting"]), // awaiting for 'internal' use
+ message_state: z
+ .enum(["read", "received", "sent", "sending", "awaiting"])
+ .default("received"), // awaiting for 'internal' use
});
export const failedUser = {