feat: implement whisper, (double)click on avatar
Users can insert a mention by clicking, and initiate a whisper by double-clicking on the avatar on a user's chat message
This commit is contained in:
		@@ -1,6 +1,10 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
 import type { Message } from "fedwave-chat-client";
 | 
			
		||||
 import { room, username } from "./chat";
 | 
			
		||||
 import { room } from "./chat";
 | 
			
		||||
 | 
			
		||||
 import { createEventDispatcher } from "svelte";
 | 
			
		||||
 const dispatch = createEventDispatcher();
 | 
			
		||||
 | 
			
		||||
 export let globalMode = false;
 | 
			
		||||
 export let message: Message;
 | 
			
		||||
 export let isHeader: boolean = true;
 | 
			
		||||
@@ -8,7 +12,11 @@
 | 
			
		||||
 | 
			
		||||
<div class="message d-flex p-relative pl-8 pr-24" class:subseq="{!isHeader}">
 | 
			
		||||
    {#if isHeader}
 | 
			
		||||
	<div class="avatar radius-pill overflow-hidden no-select" style="background-color: {message.color}">
 | 
			
		||||
	<!-- TODO: Use <Avatar/> here	 -->
 | 
			
		||||
	<div class="avatar radius-pill overflow-hidden no-select clickable"
 | 
			
		||||
	     on:click="{() => dispatch('avatar:click', message)}"
 | 
			
		||||
	     on:dblclick="{() => dispatch('avatar:dblclick', message)}"
 | 
			
		||||
	     style="background-color: {message.color}">
 | 
			
		||||
	    <img class="w-100" alt="{message.username}'s avatar" src="{message.avatar || '/troll_haz2.png'}">
 | 
			
		||||
	</div>
 | 
			
		||||
    {/if}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,8 @@
 | 
			
		||||
  let viewport: Element, contents: Element;
 | 
			
		||||
  let tweet: HTMLAudioElement;
 | 
			
		||||
 | 
			
		||||
  let input: string = '';
 | 
			
		||||
 | 
			
		||||
  shouldTweet.subscribe((should) => {
 | 
			
		||||
    if (should) {
 | 
			
		||||
      if (tweet) {
 | 
			
		||||
@@ -91,6 +93,10 @@
 | 
			
		||||
    bind:viewport
 | 
			
		||||
    bind:contents
 | 
			
		||||
    on:scroll={onScroll}
 | 
			
		||||
    on:avatar:click={(e) => (
 | 
			
		||||
      (input += ` @${e.detail.username}#${e.detail.unum} `), (input = input.trim())
 | 
			
		||||
    )}
 | 
			
		||||
    on:avatar:dblclick={(e) => (input = `/w ${e.detail.username}#${e.detail.unum} `)}
 | 
			
		||||
  />
 | 
			
		||||
  {#if !stickToBottom}
 | 
			
		||||
    <FAB --background={'var(--base-700)'} on:click={() => scrollToBottom()}
 | 
			
		||||
@@ -98,7 +104,7 @@
 | 
			
		||||
    >
 | 
			
		||||
  {/if}
 | 
			
		||||
</div>
 | 
			
		||||
<Input />
 | 
			
		||||
<Input bind:input />
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
  .scroller {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,20 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
 import { tick } from "svelte"
 | 
			
		||||
 import { send } from "./chat";
 | 
			
		||||
 import { send, whisper } from "./chat";
 | 
			
		||||
 | 
			
		||||
 let input = "";
 | 
			
		||||
 export let input = "";
 | 
			
		||||
 async function keydown(e: KeyboardEvent) {
 | 
			
		||||
     if(e.key === "Enter") {
 | 
			
		||||
	 send(input);
 | 
			
		||||
	 console.log(e);
 | 
			
		||||
	 const tokens = input.trim().split(" ");
 | 
			
		||||
 | 
			
		||||
	 if(tokens[0] === '/w') {
 | 
			
		||||
	     const who = tokens[1];
 | 
			
		||||
	     const m = tokens.slice(2).join(' ');
 | 
			
		||||
	     whisper(who, m);
 | 
			
		||||
	 } else {
 | 
			
		||||
	     send(input);
 | 
			
		||||
	 }
 | 
			
		||||
	 e.preventDefault();
 | 
			
		||||
	 await tick();
 | 
			
		||||
	 input = "";
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,10 @@
 | 
			
		||||
<div class="viewport" bind:this={viewport} on:scroll>
 | 
			
		||||
    <div class="contents" bind:this={contents}>
 | 
			
		||||
	{#each messages as message}
 | 
			
		||||
            <ChatMessage message={message.m} isHeader={message.isHeader} globalMode={showChannel} />
 | 
			
		||||
            <ChatMessage message={message.m}
 | 
			
		||||
			 isHeader={message.isHeader}
 | 
			
		||||
			 globalMode={showChannel}
 | 
			
		||||
			 on:avatar:click on:avatar:dblclick />
 | 
			
		||||
	{/each}
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,10 @@ export function send(m: string | OutgoingMessage) {
 | 
			
		||||
  chat.sendMessage(m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function whisper(who: string, m: string) {
 | 
			
		||||
  chat.sendWhisper(who, m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let setConnected: Subscriber<boolean> | undefined;
 | 
			
		||||
export const connected = readable<boolean>(false, (setf) => {
 | 
			
		||||
  setConnected = setf;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@
 | 
			
		||||
    flex-grow: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.shrink-0 {
 | 
			
		||||
    flex-shrink: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.basis-0 {
 | 
			
		||||
    flex-basis: 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -62,8 +66,10 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.d-flex {
 | 
			
		||||
    display: flex;
 | 
			
		||||
@each $i in (block, inline, inline-block, flex, grid, contents) {
 | 
			
		||||
    .d-#{$i} {
 | 
			
		||||
	display: #{$i};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.col {
 | 
			
		||||
@@ -82,9 +88,16 @@
 | 
			
		||||
    width: 100vw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mw-0 { min-width: 0 }
 | 
			
		||||
 | 
			
		||||
.w-100 { width: 100%; }
 | 
			
		||||
.h-100 { height: 100%; }
 | 
			
		||||
 | 
			
		||||
.ellipsis {
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hide-scrollbar {
 | 
			
		||||
    /* hide scrollbar */
 | 
			
		||||
    -ms-overflow-style: none !important;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user