mirror of
https://github.com/thelounge/thelounge.git
synced 2026-07-31 15:15:52 -04:00
https://ircv3.net/specs/client-tags/typing https://libera.chat/news/new-and-upcoming-features-3#client-tags Very open to style feedback: I took some tips from discord: - bump padding on the bottom to the chat to fit it (20px, not very noticeable) - when scrolled up, a gradient is applied - I dont love adding the padding but idk a better solution and IMO its not noticeable https://github.com/user-attachments/assets/a911994e-1564-45bf-8475-37742ad8b4f5 <img width="1288" height="330" alt="image" src="https://github.com/user-attachments/assets/19441440-be8c-477c-8513-9c43b83c009b" /> <img width="1608" height="1086" alt="image" src="https://github.com/user-attachments/assets/339dff30-6719-450d-9d4f-e01ec354de3f" /> Closes https://github.com/thelounge/thelounge/issues/2419 Supersedes/closes #4611 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
101 lines
1.8 KiB
Vue
101 lines
1.8 KiB
Vue
<template>
|
|
<div class="typing-indicator">
|
|
<template v-if="typingText">
|
|
<span class="typing-dots"><span /><span /><span /></span>
|
|
{{ typingText }}
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
.typing-indicator {
|
|
flex: 0 0 auto;
|
|
padding: 0 10px 4px 11px;
|
|
font-size: 0.65em;
|
|
line-height: 1.2;
|
|
min-height: calc(1.2em + 4px);
|
|
background: var(--form-bg-color);
|
|
color: var(--body-color-muted);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.typing-dots {
|
|
display: inline-flex;
|
|
gap: 2px;
|
|
align-items: center;
|
|
|
|
span {
|
|
width: 3px;
|
|
height: 3px;
|
|
border-radius: 50%;
|
|
background: var(--body-color-muted);
|
|
animation: typing-bounce 1.4s infinite ease-in-out both;
|
|
}
|
|
|
|
/* Stagger the dots animation */
|
|
span:nth-child(1) {
|
|
animation-delay: -0.32s;
|
|
}
|
|
|
|
span:nth-child(2) {
|
|
animation-delay: -0.16s;
|
|
}
|
|
}
|
|
|
|
@keyframes typing-bounce {
|
|
0%,
|
|
80%,
|
|
100% {
|
|
transform: scale(0.6);
|
|
opacity: 0.4;
|
|
}
|
|
|
|
40% {
|
|
transform: scale(1);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script lang="ts">
|
|
import {computed, defineComponent, PropType} from "vue";
|
|
import type {ClientChan} from "../js/types";
|
|
import {useStore} from "../js/store";
|
|
|
|
export default defineComponent({
|
|
name: "TypingIndicator",
|
|
props: {
|
|
channel: {type: Object as PropType<ClientChan>, required: true},
|
|
},
|
|
setup(props) {
|
|
const store = useStore();
|
|
|
|
const typingText = computed(() => {
|
|
if (store.state.settings.typing === "off") {
|
|
return "";
|
|
}
|
|
|
|
const nicks = props.channel.typingNicks;
|
|
|
|
if (nicks.length === 0) {
|
|
return "";
|
|
}
|
|
|
|
if (nicks.length === 1) {
|
|
return `${nicks[0]} is typing...`;
|
|
}
|
|
|
|
if (nicks.length === 2) {
|
|
return `${nicks[0]} and ${nicks[1]} are typing...`;
|
|
}
|
|
|
|
return `${nicks[0]} and ${nicks.length - 1} others are typing...`;
|
|
});
|
|
|
|
return {typingText};
|
|
},
|
|
});
|
|
</script>
|