mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-20 05:02:04 +00:00
feat: support leaving chat, chat message toasts for non-guests IF logged into chat
Some checks are pending
Check / check (push) Waiting to run
Some checks are pending
Check / check (push) Waiting to run
This commit is contained in:
parent
361ca69f42
commit
56a1cfbc98
5 changed files with 43 additions and 17 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"version": "6.3.66",
|
||||
"version": "6.3.67",
|
||||
"license": "BUSL-1.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.14.4",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang='ts'>
|
||||
|
||||
import DoorOpen from 'lucide-svelte/icons/door-open'
|
||||
import SendHorizontal from 'lucide-svelte/icons/send-horizontal'
|
||||
|
||||
import { Button } from '../button'
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
import type MessageClient from '$lib/modules/irc'
|
||||
|
||||
import { goto } from '$app/navigation'
|
||||
import { Textarea } from '$lib/components/ui/textarea'
|
||||
import { prevAgreed } from '$lib/modules/irc'
|
||||
|
||||
export let client: MessageClient
|
||||
|
||||
|
|
@ -37,13 +39,22 @@
|
|||
$: users = client.users
|
||||
|
||||
$: processedUsers = Object.values($users)
|
||||
|
||||
function quit () {
|
||||
$prevAgreed = false
|
||||
client.destroy()
|
||||
goto('/app/home')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class='flex flex-col w-full relative px-md-4 h-full overflow-hidden'>
|
||||
<div class='flex md:flex-row flex-col-reverse w-full h-full pt-4'>
|
||||
<div class='flex flex-col justify-end overflow-hidden flex-grow px-4 md:pb-4'>
|
||||
<Messages messages={client.messages} />
|
||||
<div class='flex mt-4'>
|
||||
<div class='flex mt-4 gap-2'>
|
||||
<Button on:click={quit} size='icon' class='border-0 shrink-0' variant='outline'>
|
||||
<DoorOpen size={18} />
|
||||
</Button>
|
||||
<Textarea
|
||||
bind:value={message}
|
||||
class='h-auto px-3 w-full flex-grow-1 resize-none min-h-0 border-0 bg-background select:bg-accent select:text-accent-foreground'
|
||||
|
|
@ -51,7 +62,7 @@
|
|||
autocomplete='off'
|
||||
maxlength={256}
|
||||
placeholder='Message' on:keydown={checkInput} on:input={updateRows} />
|
||||
<Button on:click={sendMessage} size='icon' class='mt-auto ml-2 border-0' variant='outline'>
|
||||
<Button on:click={sendMessage} size='icon' class='mt-auto border-0' variant='outline'>
|
||||
<SendHorizontal size={18} />
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { arr2hex, arr2text, bin2hex, hex2arr, hex2bin, text2arr } from 'uint8-util'
|
||||
|
||||
// could use a simple XOR encryption/decryption but meh, some1 could easily brute force it
|
||||
const key = new Uint8Array([104, 97, 121, 97, 115, 101, 45, 111, 118, 101, 114, 45, 97, 108, 108, 45, 251, 249, 0, 204, 242, 221, 119, 44, 147, 27, 83, 227, 225, 179, 149, 80, 70, 163, 58, 97, 201, 1, 10, 33, 78, 172, 195, 239, 171, 119, 51, 199, 127, 248, 221, 31, 90, 114, 200, 255, 252, 158, 158, 57, 245, 153, 44, 126, 130, 232, 230, 192, 0, 223, 204, 137, 211, 115, 33, 42, 68, 227, 65, 161, 17, 116, 138, 195, 51, 51, 181, 183, 124, 119, 161, 74, 202, 21, 182, 195, 134, 198, 191, 182, 223, 205, 60, 175, 207, 223, 232, 94, 133, 70, 10, 127, 100, 170, 109, 22])
|
||||
const key = new Uint8Array([104, 97, 121, 97, 115, 101, 45, 111, 118, 101, 114, 45, 97, 108, 108, 45, 251, 249, 0, 204, 242, 221, 119, 44, 147, 27, 83, 227, 225, 179, 149, 80, 70, 163, 58, 97, 201, 1, 10, 33, 78, 172, 195, 239, 171, 119, 51, 199, 127, 248, 221, 31, 90, 114, 200, 255, 252, 158, 158, 57, 245, 153, 44, 126, 130, 232, 230, 192, 0, 223, 204, 137, 211, 115, 33, 42, 68, 227, 65, 161, 17, 116, 138, 195, 51, 51, 181, 183, 124, 119, 161, 74, 202, 21, 182, 195, 134, 198, 191, 182, 223, 205, 60, 175, 207, 223, 232, 94, 133, 70, 10, 127, 100, 170, 109, 22]).slice(0, 16)
|
||||
|
||||
const derived = (async () => {
|
||||
const keyMaterial = await crypto.subtle.importKey(
|
||||
|
|
@ -21,7 +21,7 @@ const derived = (async () => {
|
|||
},
|
||||
keyMaterial,
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
name: 'AES-CBC',
|
||||
length: 256
|
||||
},
|
||||
false,
|
||||
|
|
@ -32,7 +32,7 @@ const derived = (async () => {
|
|||
export async function encryptMessage (message: string) {
|
||||
return hex2bin(arr2hex(new Uint8Array(await crypto.subtle.encrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
name: 'AES-CBC',
|
||||
iv: key
|
||||
},
|
||||
await derived,
|
||||
|
|
@ -43,7 +43,7 @@ export async function encryptMessage (message: string) {
|
|||
export async function decryptMessage (encryptedMessage: string) {
|
||||
return arr2text(await crypto.subtle.decrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
name: 'AES-CBC',
|
||||
iv: key
|
||||
},
|
||||
await derived,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
import Client, { createChannelConstructor } from '@thaunknown/web-irc'
|
||||
import { writable } from 'simple-store-svelte'
|
||||
import { toast } from 'svelte-sonner'
|
||||
|
||||
import { decryptMessage, encryptMessage } from './crypt'
|
||||
|
||||
import type { ChatMessage, ChatUser } from '$lib/components/ui/chat'
|
||||
import type IrcChannel from '@thaunknown/web-irc/channel'
|
||||
import type IrcClient from '@thaunknown/web-irc/client'
|
||||
import type { EventEmitter } from 'events'
|
||||
|
||||
import { page } from '$app/state'
|
||||
import { MessageToast, type ChatMessage, type ChatUser } from '$lib/components/ui/chat'
|
||||
|
||||
export const prevAgreed = writable(false)
|
||||
|
||||
export type UserType = 'al' | 'guest'
|
||||
export interface IRCChatUser {
|
||||
nick: string
|
||||
|
|
@ -99,12 +104,20 @@ export default class MessageClient {
|
|||
this.irc.on('privmsg', async priv => {
|
||||
try {
|
||||
const message = await decryptMessage(priv.message)
|
||||
this.messages.update(messages => [...messages, {
|
||||
const msg: ChatMessage = {
|
||||
message,
|
||||
user: this.users.value[priv.ident]!,
|
||||
type: 'incoming',
|
||||
date: new Date(priv.time)
|
||||
}])
|
||||
}
|
||||
|
||||
if (page.route.id !== '/app/chat' && !msg.user.name.startsWith('Guest-')) {
|
||||
toast.custom(MessageToast, {
|
||||
classes: { toast: '!bg-transparent w-full !shadow-none h-auto flex' },
|
||||
componentProps: { msg }
|
||||
})
|
||||
}
|
||||
this.messages.update(messages => [...messages, msg])
|
||||
} catch (e) {
|
||||
// some1 sent a message without encryption
|
||||
console.error(e)
|
||||
|
|
@ -154,4 +167,9 @@ export default class MessageClient {
|
|||
})
|
||||
return client
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.irc.removeAllListeners()
|
||||
this.irc.connection?.end()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
<script lang='ts' context='module'>
|
||||
let prevAgreed = false
|
||||
</script>
|
||||
|
||||
<script lang='ts'>
|
||||
import TriangleAlert from 'lucide-svelte/icons/triangle-alert'
|
||||
|
||||
import { Button } from '$lib/components/ui/button'
|
||||
import { IRC } from '$lib/components/ui/irc'
|
||||
import { prevAgreed } from '$lib/modules/irc'
|
||||
|
||||
let agreed = prevAgreed
|
||||
let agreed = $prevAgreed
|
||||
function agree () {
|
||||
agreed = prevAgreed = true
|
||||
agreed = $prevAgreed = true
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue