Skip to content

Commit

Permalink
Add did:web + cecr message source
Browse files Browse the repository at this point in the history
Signed-off-by: Marlon Baeten <[email protected]>
  • Loading branch information
marlonbaeten committed Jul 30, 2024
1 parent ade4791 commit f0b88d3
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 74 deletions.
8 changes: 6 additions & 2 deletions demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface ContentProps {
active: number | null;
mobile: boolean;
contacts: Contact[];
createIdentity: (name: string) => void;
createIdentity: (name: string, web: boolean) => void;
deleteContact: (index: number) => void;
deleteIdentity: () => void;
deleteMessage: (contactIndex: number, index: number) => void;
Expand Down Expand Up @@ -39,7 +39,11 @@ function Content({
verifyContact,
}: ContentProps) {
if (!initialized) {
return <Initialize onClick={(name: string) => createIdentity(name)} />;
return (
<Initialize
onClick={(name: string, web: boolean) => createIdentity(name, web)}
/>
);
}

if (active !== null) {
Expand Down
23 changes: 13 additions & 10 deletions demo/src/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,19 @@ export default function Chat({
gap="sm"
py="sm"
>
{contact.messages.map(({ date, me, message, encoded }, i) => (
<ChatMessage
key={date}
date={date}
me={me}
message={message}
encoded={encoded}
deleteMessage={() => deleteMessage(index, i)}
/>
))}
{contact.messages.map(
({ date, me, message, encoded, timestampSignature }, i) => (
<ChatMessage
key={date}
date={date}
me={me}
message={message}
encoded={encoded}
timestampSignature={timestampSignature}
deleteMessage={() => deleteMessage(index, i)}
/>
)
)}
</Flex>
</Box>
<ChatInput
Expand Down
44 changes: 39 additions & 5 deletions demo/src/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ import {
rem,
Modal,
Badge,
Text,
Box,
CheckIcon,
} from '@mantine/core';
import { IconDotsVertical, IconTrash, IconCode, IconCheck } from '@tabler/icons-react';
import {
IconDotsVertical,
IconTrash,
IconCode,
IconCheck,
} from '@tabler/icons-react';
import { useDisclosure, useHover } from '@mantine/hooks';
import EncodedMessage from './EncodedMessage';

interface ChatMessageProps {
date: string;
me: boolean;
deleteMessage: () => void;
message: string;
timestampSignature: string;
encoded:
| string
| {
Expand All @@ -30,6 +40,7 @@ export default function ChatMessage({
me,
message,
encoded,
timestampSignature,
deleteMessage,
}: ChatMessageProps) {
const { hovered, ref } = useHover();
Expand All @@ -54,18 +65,41 @@ export default function ChatMessage({
size="sm"
radius="sm"
mb="xs"
onClick={open}
style={{ cursor: 'pointer' }}
>
{date.slice(11, 19)}
</Badge>

<Modal
opened={opened}
onClose={close}
title={<strong>CESR encoded message</strong>}
title={<strong>TSP message</strong>}
size="lg"
>
<code style={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
{typeof encoded === 'object' ? encoded.size : encoded}
</code>
<Box c="green" mb="lg">
<CheckIcon size={14} color="green" />
&nbsp; Verified by the time server
</Box>
<Box c="dimmed">Full date</Box>
<Box mb="lg">{date.replace('T', ' ').slice(0, 19)}</Box>
{typeof encoded === 'string' && (
<>
<Box c="dimmed">Signature</Box>
<Box mb="lg">
<code
style={{
display: 'block',
wordWrap: 'break-word',
wordBreak: 'break-all',
}}
>
{timestampSignature}
</code>
</Box>
</>
)}
<EncodedMessage encoded={encoded} plain={message} />
</Modal>
<Menu shadow="md" width={180}>
<Menu.Target>
Expand Down
85 changes: 85 additions & 0 deletions demo/src/EncodedMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useEffect, useState } from 'react';
import { message_parts } from '../pkg/tsp_demo';
import { base64ToBuffer, bufferToBase64 } from './util';
import { Box } from '@mantine/core';

interface EncodedMessageProps {
plain: string;
encoded:
| string
| {
name: string;
href: string;
size: string;
};
}

// render a TSP message with debug information
function EncodedMessageParts({ message }: { message: any }) {
const parts = [
'prefix',
'sender',
'receiver',
'nonconfidentialData',
'ciphertext',
'signature',
];
const colors = [
'#800000',
'#911eb4',
'#000075',
'#3cb44b',
'#9A6324',
'#469990',
];

return (
<code style={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
{parts
.map((part, index) => [part, message[part], index])
.filter(([_part, messagePart, _index]) => messagePart)
.map(([part, messagePart, index]) => (
<span
key={part}
className="message-part"
style={{ color: colors[index] }}
>
{bufferToBase64(messagePart.data)}
</span>
))}
</code>
);
}

export default function EncodedMessage({ encoded }: EncodedMessageProps) {
const [parts, setParts] = useState<null | any>(null);

useEffect(() => {
const getParts = async () => {
if (typeof encoded === 'string') {
const data = base64ToBuffer(encoded);
setParts(JSON.parse(message_parts(data)));
}
};
getParts();
}, [encoded]);

if (typeof encoded === 'object') {
return <code>{encoded.size}</code>;
}

if (parts) {
return (
<>
<Box c="dimmed">CECR encoded message</Box>
<EncodedMessageParts message={parts} />
</>
);
}

return (
<code style={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
{encoded}
</code>
);
}
28 changes: 22 additions & 6 deletions demo/src/Initialize.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { Button, Center, Flex, Input, Modal, Title } from '@mantine/core';
import { useDisclosure, useFocusTrap } from '@mantine/hooks';
import { IconUserPlus } from '@tabler/icons-react';
import { useState } from 'react';
import { FormEvent, useState } from 'react';
import logo from './trust-over-ip.svg';

interface InitializeProps {
onClick: (name: string) => void;
onClick: (name: string, web: boolean) => void;
}

export default function Initialize({ onClick }: InitializeProps) {
const [opened, { open, close }] = useDisclosure(false);
const [label, setLabel] = useState<string>('');
const [web, setWeb] = useState<boolean>(true);
const [error, setError] = useState<string>('');
const focusTrapRef = useFocusTrap();

const save = () => {
const save = (e: FormEvent) => {
e.preventDefault();

if (label.length > 0) {
onClick(label);
onClick(label, web);
setLabel('');
setError('');
close();
Expand Down Expand Up @@ -49,8 +52,21 @@ export default function Initialize({ onClick }: InitializeProps) {
/>
</Input.Wrapper>
<Flex mih={60} gap="md" justify="flex-end" align="flex-end">
<Button size="md" variant="filled" type="submit">
Create
<Button
size="md"
variant="filled"
type="submit"
onClick={() => setWeb(true)}
>
Create did:web
</Button>
<Button
size="md"
variant="filled"
type="submit"
onClick={() => setWeb(false)}
>
Create did:peer
</Button>
</Flex>
</form>
Expand Down
3 changes: 2 additions & 1 deletion demo/src/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { QRCode } from 'react-qrcode-logo';
import { Identity } from './useStore';
import { Button, CopyButton, Flex, Stack, Title } from '@mantine/core';
import { Box, Button, CopyButton, Flex, Stack, Title } from '@mantine/core';
import { useElementSize } from '@mantine/hooks';
import { identityToUrl } from './util';
import logo from './trust-over-ip.svg';
Expand Down Expand Up @@ -48,6 +48,7 @@ export default function Profile({
{width !== null && (
<QRCode quietZone={0} value={url} size={Math.min(width * 0.8, 512)} />
)}
<Box>{id.vid.id.length < 128 && <pre>{id.vid.id}</pre>}</Box>
<Flex gap="md" align="center">
<CopyButton value={url}>
{({ copied, copy }) => (
Expand Down
Loading

0 comments on commit f0b88d3

Please sign in to comment.