At-mention popups for chat

polling-api
Noah 2023-09-08 20:27:00 -07:00
parent 3b06676343
commit f091747380
5 changed files with 147 additions and 27 deletions

66
package-lock.json generated
View File

@ -8,8 +8,10 @@
"name": "barertc",
"version": "0.0.0",
"dependencies": {
"floating-vue": "^2.0.0-beta.24",
"interactjs": "^1.10.18",
"vue": "^3.3.4",
"vue-mention": "^2.0.0-alpha.3",
"vue3-emoji-picker": "^1.1.7"
},
"devDependencies": {
@ -447,6 +449,27 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@floating-ui/core": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz",
"integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==",
"dependencies": {
"@floating-ui/utils": "^0.1.1"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.1.tgz",
"integrity": "sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==",
"dependencies": {
"@floating-ui/core": "^1.1.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz",
"integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw=="
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.11",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
@ -1144,6 +1167,24 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"node_modules/floating-vue": {
"version": "2.0.0-beta.24",
"resolved": "https://registry.npmjs.org/floating-vue/-/floating-vue-2.0.0-beta.24.tgz",
"integrity": "sha512-URSzP6YXaF4u1oZ9XGL8Sn8puuM7ivp5jkOUrpy5Q1mfo9BfGppJOn+ierTmsSUfJEeHBae8KT7r5DeI3vQIEw==",
"dependencies": {
"@floating-ui/dom": "~1.1.1",
"vue-resize": "^2.0.0-alpha.1"
},
"peerDependencies": {
"@nuxt/kit": "^3.2.0",
"vue": "^3.2.0"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -1817,6 +1858,11 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"node_modules/textarea-caret": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz",
"integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q=="
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@ -1947,6 +1993,26 @@
"eslint": ">=6.0.0"
}
},
"node_modules/vue-mention": {
"version": "2.0.0-alpha.3",
"resolved": "https://registry.npmjs.org/vue-mention/-/vue-mention-2.0.0-alpha.3.tgz",
"integrity": "sha512-NtM6Z6UpqHByKJPyiy2SrBy3K7wyi/6bvXltaRfWcSQdNwW3YrWzrr1M7lYB4NoWRhDFuk+4X1GpY8HH06g+XQ==",
"dependencies": {
"textarea-caret": "^3.1.0"
},
"peerDependencies": {
"floating-vue": "^2.0.0-beta.1",
"vue": "^3.2"
}
},
"node_modules/vue-resize": {
"version": "2.0.0-alpha.1",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz",
"integrity": "sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue3-emoji-picker": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/vue3-emoji-picker/-/vue3-emoji-picker-1.1.7.tgz",

View File

@ -10,8 +10,10 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
"floating-vue": "^2.0.0-beta.24",
"interactjs": "^1.10.18",
"vue": "^3.3.4",
"vue-mention": "^2.0.0-alpha.3",
"vue3-emoji-picker": "^1.1.7"
},
"devDependencies": {

View File

@ -19,6 +19,10 @@
background-color: rgba(15, 129, 204, 0.25) !important;
}
.has-background-at-mention {
background-color: rgb(50, 50, 0);
}
.tag.is-success {
background-color: #15241d !important;
color: #85dfb6 !important;

View File

@ -22,6 +22,9 @@ body {
.has-background-dm {
background-color: #ffefff;
}
.has-background-at-mention {
background-color: rgb(250, 250, 192);
}
/* Truncate long text, e.g. usernames in the who list */
.truncate-text-line {

View File

@ -1,5 +1,9 @@
<script>
import interact from 'interactjs';
import FloatingVue from 'floating-vue';
import 'floating-vue/dist/style.css';
import { Mentionable } from 'vue-mention';
import LoginModal from './components/LoginModal.vue';
import ExplicitOpenModal from './components/ExplicitOpenModal.vue';
import ReportModal from './components/ReportModal.vue';
@ -32,6 +36,9 @@ const FileUploadMaxSize = 1024 * 1024 * 8; // 8 MB
export default {
name: 'BareRTC',
components: {
FloatingVue,
Mentionable,
LoginModal,
ExplicitOpenModal,
ReportModal,
@ -517,6 +524,27 @@ export default {
// Return the count of other peoples videos we have open.
return Object.keys(this.WebRTC.streams).length;
},
atMentionItems() {
// Available users in chat for the at-mentions support.
let result = [
{
value: "all",
label: "All people in the current room",
},
{
value: "here",
label: "Everybody here in the current room",
},
];
for (let user of this.whoList) {
if (user.username === this.username) continue;
result.push({
value: user.username,
label: user.nickname,
});
}
return result;
},
sortedWhoList() {
let result = [...this.whoList];
@ -2371,6 +2399,14 @@ export default {
}
}
// Were we at mentioned in this message?
if (message.indexOf("@"+this.username) > -1) {
let re = new RegExp("@"+this.username+"\\b");
message = message.replace(re, `<strong class="has-background-at-mention">@${this.username}</strong>`);
}
// And same for @here or @all
message = message.replace(/@(here|all)\b/i, `<strong class="has-background-at-mention">@$1</strong>`);
// Append the message.
this.channels[channel].updated = new Date().getTime();
@ -3617,9 +3653,35 @@ export default {
</div>
<div class="column pr-1" :class="{ 'pl-1': canUploadFile }">
<form @submit.prevent="sendMessage()">
<input type="text" class="input" id="messageBox" v-model="message"
placeholder="Write a message" @keydown="sendTypingNotification()" autocomplete="off"
:disabled="!ws.connected">
<!-- At Mentions -->
<Mentionable
:keys="['@']"
:items="atMentionItems"
offset="12"
insert-space>
<!-- My text entry box -->
<input type="text" class="input" id="messageBox" v-model="message"
placeholder="Write a message" @keydown="sendTypingNotification()" autocomplete="off"
:disabled="!ws.connected">
<!-- At Mention templates-->
<template #no-result>
<div class="has-text-grey m-2">
No result
</div>
</template>
<template #item-@="{ item }">
<div class="has-text-link m-2">
@{{ item.value }}
<span class="has-text-grey">
{{ item.label }}
</span>
</div>
</template>
</Mentionable>
</form>
</div>
<div class="column pl-1 is-narrow">
@ -3763,31 +3825,14 @@ export default {
</div>
</template>
<style scoped>
/* header {
line-height: 1.5;
<style>
/* At-mention styles */
.mention-item {
padding: 4px 10px;
border-radius: 4px;
}
.logo {
display: block;
margin: 0 auto 2rem;
.mention-selected {
background: rgb(192, 250, 153);
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
} */
</style>