mirror of
https://github.com/Discreetly/frontend.git
synced 2026-01-10 05:18:06 -05:00
checkpoint progress on experiences/demo
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Group from 'svelte-material-icons/AccountGroup.svelte';
|
||||
import MemberSecret from 'svelte-material-icons/AccountKey.svelte';
|
||||
import FingerPrint from 'svelte-material-icons/Fingerprint.svelte';
|
||||
</script>
|
||||
|
||||
<div class="flex flex-row gap-3 place-items-center text-xl">
|
||||
<FingerPrint />(<MemberSecret />)
|
||||
<div>∈</div>
|
||||
<Group />
|
||||
</div>
|
||||
|
||||
@@ -1,31 +1,45 @@
|
||||
<script>
|
||||
import Button from '$lib/components/button.svelte';
|
||||
import Demo from '$lib/components/Demo.svelte';
|
||||
</script>
|
||||
|
||||
<div class="mx-auto mt-10 max-w-[80ch]">
|
||||
<img src="/logo-text.png" alt="discreetly" class="max-h-20 mb-5" />
|
||||
<h5 class="italic mb-4 mt-1">A new take on anonymous communication.</h5>
|
||||
<h5 class="italic mb-4 mt-1">A new take on group chats.</h5>
|
||||
<p class="text-justify my-3">
|
||||
This feels like a mostly familiar chat application, with random numbers as usernames, but I
|
||||
assure you there is more going on here.
|
||||
This feels like a mostly familiar chat application, except there aren't user names. Under the
|
||||
hood, there is no "login", the server doesn't know who you are, you are anonymous. You're
|
||||
completely anonymous. <i class="italic">Unless you break the rules.</i>
|
||||
</p>
|
||||
|
||||
<p class="text-justify my-3">
|
||||
Under the hood, there is no "login", the server doesn't know who you are, you are anonymous.
|
||||
The beauty of this system is that it fosters trust among group members, knowing that everyone in
|
||||
the chat is a verified member. At the same time, it provides the freedom to express oneself
|
||||
anonymously.
|
||||
</p>
|
||||
|
||||
<p class="text-justify my-3">
|
||||
There is one catch, if you send messages too fast, someone can figure out which identity you
|
||||
are, and remove you from the chat. So if you try to break the rules, you will be removed, and
|
||||
there is no undo.
|
||||
When you want to send a message in a room, you need to verify your membership in that room, but
|
||||
without giving away your identity. This is accomplished using a zero-knowledge proof, a clever
|
||||
piece of cryptography that lets you prove you know something, without having to reveal what that
|
||||
something is.
|
||||
</p>
|
||||
<p>
|
||||
When you send a message, your device generates a zk proof that you are a member of that room,
|
||||
and that you haven't sent too many messages during some time period (an epoch), but doesn't
|
||||
reveal which member you are.
|
||||
|
||||
<p class="text-justify my-3">
|
||||
However, there's a small catch. To prevent spam, each time you send a message, you "share" a
|
||||
tiny piece of your identity that is only useful for that epoch (time period). If you send too
|
||||
many messages during an epoch, someone can reassemble your identity, all of your messages can be
|
||||
linked together, and you will be removed from the chat for spamming. This is done automatically
|
||||
and permanently, there is no unban.
|
||||
</p>
|
||||
|
||||
<p class="text-justify my-3">
|
||||
Read more about <a class="anchor" href="https://rate-limiting-nullifier.github.io/rln-docs/"
|
||||
>RLN</a
|
||||
>.
|
||||
</p>
|
||||
<a href="https://discord.gg/brJQ36KVxk" class="btn variant-ghost-secondary">Join our Discord</a>
|
||||
<div>
|
||||
<Demo />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
<style>
|
||||
#chat-wrapper {
|
||||
height: 100%;
|
||||
height: 100vh;
|
||||
max-height: calc(100vh - 56px);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(17%, 300px) 1fr;
|
||||
grid-template-rows: auto;
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
<script lang="ts">
|
||||
import ChatRoomHeader from './ChatRoomHeader.svelte';
|
||||
|
||||
import InputPrompt from './InputPrompt.svelte';
|
||||
import Conversation from './Conversation.svelte';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { selectedServer, currentSelectedRoom, messageStore, rateLimitStore } from '$lib/stores';
|
||||
import { io } from 'socket.io-client';
|
||||
import type { Socket } from 'socket.io-client';
|
||||
import type { MessageI } from 'discreetly-interfaces';
|
||||
import { getEpochFromTimestamp, getTimestampFromEpoch, updateMessages } from '$lib/utils';
|
||||
import Loading from '$lib/components/loading.svelte';
|
||||
import {
|
||||
currentSelectedRoom,
|
||||
messageStore,
|
||||
rateLimitStore,
|
||||
selectedServer,
|
||||
configStore
|
||||
} from '$lib/stores';
|
||||
import { Experiences } from '$lib/types';
|
||||
import { getEpochFromTimestamp, getTimestampFromEpoch, updateMessages } from '$lib/utils';
|
||||
import { toastStore } from '@skeletonlabs/skeleton';
|
||||
import type { MessageI } from 'discreetly-interfaces';
|
||||
import type { Socket } from 'socket.io-client';
|
||||
import { io } from 'socket.io-client';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import Conversation from './Conversation.svelte';
|
||||
import Draw from './Draw.svelte';
|
||||
import InputPrompt from './InputPrompt.svelte';
|
||||
|
||||
let scrollChatToBottom: () => {};
|
||||
let socket: Socket;
|
||||
let connected: boolean = false;
|
||||
let lastRoom = '';
|
||||
let onlineMembers = '?';
|
||||
$: currentEpoch = 0;
|
||||
$: timeLeftInEpoch = '0';
|
||||
$: roomId = $currentSelectedRoom.roomId!.toString();
|
||||
@@ -41,8 +49,8 @@
|
||||
messagesSent: 0
|
||||
};
|
||||
console.debug('MessagesLeft() resetting epoch for room', roomId);
|
||||
return userMessageLimit;
|
||||
} else {
|
||||
return userMessageLimit;
|
||||
} else {
|
||||
console.debug('MessagesLeft() returning messages left for room', roomId);
|
||||
return userMessageLimit - $rateLimitStore[roomId].messagesSent;
|
||||
}
|
||||
@@ -71,13 +79,16 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
console.log('MESSAGES LEFT: ' + messagesLeft());
|
||||
socket = io($selectedServer);
|
||||
socket.on('connect', () => {
|
||||
connected = true;
|
||||
const engine = socket.io.engine;
|
||||
|
||||
updateMessages($selectedServer, $currentSelectedRoom?.roomId.toString());
|
||||
scrollChatToBottom();
|
||||
if ($configStore.experience == Experiences.Chat) {
|
||||
scrollChatToBottom();
|
||||
}
|
||||
|
||||
engine.once('upgrade', () => {
|
||||
console.debug('Upgraded connection to', engine.transport.name);
|
||||
@@ -131,7 +142,8 @@
|
||||
scrollChatToBottom();
|
||||
}
|
||||
socket.on('Members', (data: string) => {
|
||||
console.debug(data);
|
||||
console.debug(`Members Online: ${data}`);
|
||||
onlineMembers = data;
|
||||
});
|
||||
|
||||
socket.on('systemBroadcast', (data: string) => {
|
||||
@@ -153,7 +165,6 @@
|
||||
|
||||
{#if $currentSelectedRoom}
|
||||
<div id="chat" class="grid grid-rows-[auto,1fr,auto]">
|
||||
<!-- Header -->
|
||||
<ChatRoomHeader
|
||||
{connected}
|
||||
{currentEpoch}
|
||||
@@ -163,19 +174,36 @@
|
||||
{messagesLeft}
|
||||
{roomRateLimit}
|
||||
/>
|
||||
{#if $configStore.experience == Experiences.Chat}
|
||||
{#key $currentSelectedRoom.roomId}
|
||||
<Conversation bind:scrollChatBottom={scrollChatToBottom} {roomRateLimit} />
|
||||
{/key}
|
||||
<InputPrompt
|
||||
{socket}
|
||||
{connected}
|
||||
{currentEpoch}
|
||||
{userMessageLimit}
|
||||
{messageId}
|
||||
{messagesLeft}
|
||||
/>
|
||||
{:else if $configStore.experience == Experiences.Draw}
|
||||
<Draw />
|
||||
{:else}
|
||||
{#key $currentSelectedRoom.roomId}
|
||||
<Conversation bind:scrollChatBottom={scrollChatToBottom} {roomRateLimit} />
|
||||
{/key}
|
||||
<InputPrompt
|
||||
{socket}
|
||||
{connected}
|
||||
{currentEpoch}
|
||||
{userMessageLimit}
|
||||
{messageId}
|
||||
{messagesLeft}
|
||||
/>
|
||||
{/if}
|
||||
<!-- Conversation -->
|
||||
{#key $currentSelectedRoom.roomId}
|
||||
<Conversation bind:scrollChatBottom={scrollChatToBottom} {roomRateLimit} />
|
||||
{/key}
|
||||
|
||||
<!-- Prompt -->
|
||||
<InputPrompt
|
||||
{socket}
|
||||
{connected}
|
||||
{currentEpoch}
|
||||
{userMessageLimit}
|
||||
{messageId}
|
||||
{messagesLeft}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<Loading />
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import AP from '$lib/components/AP.svelte';
|
||||
import Clock from '$lib/components/Clock.svelte';
|
||||
import { configStore, currentSelectedRoom } from '$lib/stores';
|
||||
import { currentSelectedRoom } from '$lib/stores';
|
||||
import { ProgressBar } from '@skeletonlabs/skeleton';
|
||||
import FullCircle from 'svelte-material-icons/Circle.svelte';
|
||||
import ExperienceMenu from './ExperienceMenu.svelte';
|
||||
export let connected: boolean;
|
||||
export let currentEpoch: number;
|
||||
export let timeLeftInEpoch: string;
|
||||
@@ -40,6 +41,7 @@
|
||||
class="flex flex-row place-content-center"
|
||||
title={`These are action points, you get ${userMessageLimit} every ${epochLengthSeconds} seconds`}
|
||||
>
|
||||
<ExperienceMenu />
|
||||
<AP health={messagesLeft()} maxHealth={userMessageLimit} />
|
||||
<div class="block sm:hidden">
|
||||
<Clock time={timeToNextEpoch} maxTime={epochLengthSeconds} />
|
||||
|
||||
43
src/routes/chat/Draw.svelte
Normal file
43
src/routes/chat/Draw.svelte
Normal file
@@ -0,0 +1,43 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let ctx: CanvasRenderingContext2D;
|
||||
|
||||
const aspectRatio = 1;
|
||||
|
||||
// Resize function
|
||||
function resizeCanvas() {
|
||||
const parent = canvas.parentElement;
|
||||
console.log(parent);
|
||||
const parentWidth = parent!.clientWidth;
|
||||
const parentHeight = parent!.clientHeight;
|
||||
console.log(parentWidth, parentHeight);
|
||||
let height, width;
|
||||
|
||||
if (parentHeight < parentWidth / aspectRatio) {
|
||||
height = parentHeight;
|
||||
width = height * aspectRatio;
|
||||
} else {
|
||||
width = parentWidth;
|
||||
height = width / aspectRatio;
|
||||
}
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
canvas = document.getElementById('drawing-canvas') as HTMLCanvasElement;
|
||||
ctx = canvas.getContext('2d')!;
|
||||
resizeCanvas();
|
||||
window.addEventListener('resize', resizeCanvas);
|
||||
});
|
||||
</script>
|
||||
|
||||
<canvas
|
||||
id="drawing-canvas"
|
||||
width="250"
|
||||
height="250"
|
||||
class="border border-surface-300-600-token m-1 sm:m-3"
|
||||
/>
|
||||
27
src/routes/chat/ExperienceMenu.svelte
Normal file
27
src/routes/chat/ExperienceMenu.svelte
Normal file
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { Experiences } from '$lib/types';
|
||||
import Palette from 'svelte-material-icons/Palette.svelte';
|
||||
import Chat from 'svelte-material-icons/Chat.svelte';
|
||||
import { configStore } from '$lib/stores';
|
||||
|
||||
$: experience = $configStore.experience;
|
||||
function nextExperience() {
|
||||
if (experience == Experiences.Chat) {
|
||||
$configStore.experience = Experiences.Draw;
|
||||
} else if (experience == Experiences.Draw) {
|
||||
$configStore.experience = Experiences.Chat;
|
||||
} else {
|
||||
$configStore.experience = Experiences.Chat;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<span on:click={nextExperience} class="flex flex-row ms-2 place-items-center">
|
||||
{#if experience == Experiences.Chat}
|
||||
<Palette class="w-5 h-5" />
|
||||
{:else if experience == Experiences.Draw}
|
||||
<Chat class="w-5 h-5" />
|
||||
{:else}
|
||||
<Palette class="w-5 h-5" />
|
||||
{/if}
|
||||
</span>
|
||||
@@ -73,6 +73,13 @@
|
||||
$rateLimitStore[$currentSelectedRoom.roomId!.toString()].messagesSent,
|
||||
'messages sent this epoch'
|
||||
);
|
||||
} else {
|
||||
$rateLimitStore[$currentSelectedRoom.roomId!.toString()].lastEpoch = currentEpoch;
|
||||
$rateLimitStore[$currentSelectedRoom.roomId!.toString()].messagesSent = 1;
|
||||
console.debug(
|
||||
$rateLimitStore[$currentSelectedRoom.roomId!.toString()].messagesSent,
|
||||
'messages sent this epoch'
|
||||
);
|
||||
}
|
||||
socket.emit('validateMessage', msg);
|
||||
console.debug('Sending message: ', msg);
|
||||
|
||||
Reference in New Issue
Block a user