Usability improvements, fix Firefox message hovering.
This commit is contained in:
Troplo 2022-08-31 21:41:59 +10:00
parent 7125909046
commit d6f64de95e
6 changed files with 594 additions and 797 deletions

View file

@ -992,13 +992,24 @@ router.delete("/:id/message/:mId", auth, async (req, res, next) => {
] ]
}) })
if (chat) { if (chat) {
const message = await Message.findOne({ let options
if (chat.rank === "admin") {
options = {
where: {
id: req.params.mId,
chatId: chat.chat.id
}
}
} else {
options = {
where: { where: {
id: req.params.mId, id: req.params.mId,
chatId: chat.chat.id, chatId: chat.chat.id,
userId: req.user.id userId: req.user.id
} }
}) }
}
const message = await Message.findOne(options)
if (message) { if (message) {
await message.destroy() await message.destroy()
chat.chat.users.forEach((user) => { chat.chat.users.forEach((user) => {

View file

@ -1,6 +1,6 @@
{ {
"name": "colubrina", "name": "colubrina",
"version": "1.0.26", "version": "1.0.27",
"description": "Simple instant communication.", "description": "Simple instant communication.",
"private": true, "private": true,
"author": "Troplo <troplo@troplo.com>", "author": "Troplo <troplo@troplo.com>",

View file

@ -753,6 +753,8 @@ export default {
} }
}, },
async mounted() { async mounted() {
if (localStorage.getItem("forceEnableDevMode"))
this.$store.state.release = "dev"
await this.$store.dispatch("doInit") await this.$store.dispatch("doInit")
if (this.$vuetify.breakpoint.mobile) { if (this.$vuetify.breakpoint.mobile) {
this.$store.state.drawer = false this.$store.state.drawer = false

View file

@ -15,6 +15,7 @@
right: 0; right: 0;
margin-top: -15px; margin-top: -15px;
margin-right: 5px; margin-right: 5px;
visibility: hidden;
} }
/* large codeblock */ /* large codeblock */
code { code {
@ -23,13 +24,25 @@ code {
display: block; display: block;
padding: 20px; padding: 20px;
} }
.message-hover { .message:hover {
background-color: var(--v-bg-lighten1); background-color: var(--v-bg-lighten1);
border-radius: 5px; border-radius: 5px;
} }
.message-toast { .message-toast {
background-color: rgba(47, 47, 47, 0.9) !important; background-color: rgba(47, 47, 47, 0.9) !important;
} }
.message-date {
visibility: hidden;
}
.message:hover .message-date {
visibility: visible;
}
.message:hover .message-action-card {
visibility: visible;
}
.message:hover .hide-on-hover {
visibility: hidden;
}
img.emoji { img.emoji {
/* Since we are using SVGs, you have to change the width using CSS */ /* Since we are using SVGs, you have to change the width using CSS */
height: 1.4em; height: 1.4em;

View file

@ -601,9 +601,27 @@
</v-tooltip> </v-tooltip>
</template> </template>
<template v-else> <template v-else>
<v-toolbar-title> <v-toolbar-title
{{ $route.name }} v-if="!$vuetify.breakpoint.mobile"
</v-toolbar-title> id="bettercompass-title"
:style="
'color: ' +
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light']
.primary
"
class="troplo-title"
@click="$router.push('/')"
style="cursor: pointer"
>{{ $store.state.site.name }}</v-toolbar-title
><v-app-bar-nav-icon
v-if="
!$vuetify.breakpoint.mobile &&
$store.state.site.release !== 'stable'
"
style="z-index: 1000"
disabled
>{{ $store.state.site.release }}</v-app-bar-nav-icon
>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-tooltip bottom> <v-tooltip bottom>
<template v-slot:activator="{ on }"> <template v-slot:activator="{ on }">
@ -954,6 +972,12 @@ export default {
}, },
methods: { methods: {
goToRoute() { goToRoute() {
if (this.route.value === "forceEnableDevMode") {
this.$store.state.site.release = "dev"
localStorage.setItem("forceEnableDevMode", "true")
this.$toast.success("OK")
return
}
this.$router.push(this.route.value) this.$router.push(this.route.value)
this.route.modal = false this.route.modal = false
this.route.value = "" this.route.value = ""

View file

@ -1,8 +1,6 @@
<template> <template>
<div> <div>
<v-hover v-slot="{ hover }"> <template>
<span>
<template v-if="!message.type">
<v-toolbar <v-toolbar
@click="jumpToMessage(message.replyId)" @click="jumpToMessage(message.replyId)"
:key="message.keyId + '-reply-toolbar'" :key="message.keyId + '-reply-toolbar'"
@ -16,9 +14,7 @@
<v-avatar size="24" class="mr-2"> <v-avatar size="24" class="mr-2">
<v-img <v-img
:src=" :src="
$store.state.baseURL + $store.state.baseURL + '/usercontent/' + message.reply.user.avatar
'/usercontent/' +
message.reply.user.avatar
" "
v-if="message.reply.user.avatar" v-if="message.reply.user.avatar"
class="elevation-1" class="elevation-1"
@ -38,34 +34,76 @@
<v-list-item <v-list-item
:key="message.keyId" :key="message.keyId"
:class="{ :class="{
'message-hover': hover,
'pa-0': $vuetify.breakpoint.mobile, 'pa-0': $vuetify.breakpoint.mobile,
'mentioned-message': mentioned 'mentioned-message': mentioned
}" }"
class="message"
:dense="lastMessage" :dense="lastMessage"
:id="'message-' + index" :id="'message-' + index"
@contextmenu="show($event, 'message', message)" @contextmenu="show($event, 'message', message)"
:style="lastMessage ? 'margin-bottom: -5px; margin-top: -5px;' : ''" :style="lastMessage ? 'margin-bottom: -5px; margin-top: -5px;' : ''"
> >
<v-avatar size="45" class="mr-2" v-if="!lastMessage"> <v-avatar
size="45"
class="mr-2"
v-if="!lastMessage"
:class="{ 'hide-on-hover': message.type }"
>
<v-img <v-img
:src=" :src="$store.state.baseURL + '/usercontent/' + message.user.avatar"
$store.state.baseURL + '/usercontent/' + message.user.avatar v-if="message.user.avatar && !message.type"
"
v-if="message.user.avatar"
class="elevation-1" class="elevation-1"
/> />
<v-icon v-else class="elevation-1"> mdi-account </v-icon> <v-icon class="elevation-1" v-else-if="!message.type">
mdi-account
</v-icon>
<v-icon
v-else-if="message.type === 'leave'"
color="red"
class="mr-2 ml-1"
size="32"
>
mdi-arrow-left
</v-icon>
<v-icon
v-else-if="message.type === 'join'"
size="32"
color="success"
class="mr-2 ml-1"
>
mdi-arrow-right
</v-icon>
<v-icon
v-else-if="message.type === 'pin'"
size="32"
color="grey"
class="mr-2 ml-1"
>
mdi-pin-outline
</v-icon>
<v-icon v-else size="32" color="grey" class="mr-2 ml-1">
mdi-pencil
</v-icon>
</v-avatar> </v-avatar>
<v-tooltip top style="z-index: 15">
<template v-slot:activator="{ on }">
<small <small
v-on="on"
style="font-size: 9px; position: absolute" style="font-size: 9px; position: absolute"
class="grey--text" class="grey--text message-date"
v-if="lastMessage && hover" v-if="lastMessage || message.type"
> >
{{ $date(message.createdAt).format("hh:mm A") }} {{ $date(message.createdAt).format("hh:mm A") }}
</small> </small>
</template>
<span>
{{
$date(message.createdAt).format("DD/MM/YYYY, hh:mm:ss A")
}}</span
>
</v-tooltip>
<v-list-item-content :class="{ 'offset-message': lastMessage }"> <v-list-item-content :class="{ 'offset-message': lastMessage }">
<v-list-item-subtitle v-if="!lastMessage"> <v-list-item-subtitle v-if="!lastMessage && !message.type">
{{ getName(message.user) }} {{ getName(message.user) }}
<v-chip <v-chip
v-if="message.user.bot" v-if="message.user.bot"
@ -94,16 +132,11 @@
</span> </span>
</template> </template>
<span> <span>
{{ {{ $date(message.editedAt).format("DD/MM/YYYY hh:mm:ss A") }}
$date(message.editedAt).format("DD/MM/YYYY hh:mm:ss A")
}}
</span> </span>
</v-tooltip> </v-tooltip>
</v-list-item-subtitle> </v-list-item-subtitle>
<span <span v-if="edit.id !== message.id" style="overflow-wrap: anywhere">
v-if="edit.id !== message.id"
style="overflow-wrap: anywhere"
>
<span v-markdown> <span v-markdown>
{{ message.content }} {{ message.content }}
</span> </span>
@ -114,9 +147,7 @@
</v-icon> </v-icon>
</template> </template>
<span> <span>
{{ {{ $date(message.editedAt).format("DD/MM/YYYY hh:mm:ss A") }}
$date(message.editedAt).format("DD/MM/YYYY hh:mm:ss A")
}}
</span> </span>
</v-tooltip> </v-tooltip>
</span> </span>
@ -141,6 +172,8 @@
contain contain
:max-width="500" :max-width="500"
:max-height="500" :max-height="500"
:min-height="250"
:min-width="250"
:src="$store.state.baseURL + embed.mediaProxyLink" :src="$store.state.baseURL + embed.mediaProxyLink"
> >
<template v-slot:placeholder> <template v-slot:placeholder>
@ -400,6 +433,8 @@
'/usercontent/' + '/usercontent/' +
attachment.attachment attachment.attachment
" "
:min-height="250"
:min-width="250"
> >
<template v-slot:placeholder> <template v-slot:placeholder>
<v-row <v-row
@ -409,8 +444,6 @@
> >
<v-progress-circular <v-progress-circular
indeterminate indeterminate
width="500"
height="500"
color="grey lighten-5" color="grey lighten-5"
></v-progress-circular> ></v-progress-circular>
</v-row> </v-row>
@ -471,7 +504,7 @@
elevation="8" elevation="8"
color="card" color="card"
class="message-action-card" class="message-action-card"
v-if="!$vuetify.breakpoint.mobile && hover" v-if="!$vuetify.breakpoint.mobile"
> >
<v-tooltip top> <v-tooltip top>
<template v-slot:activator="{ on }"> <template v-slot:activator="{ on }">
@ -479,7 +512,10 @@
<v-btn <v-btn
icon icon
v-on="on" v-on="on"
v-if="message.userId === $store.state.user.id" v-if="
message.userId === $store.state.user.id ||
chat.rank === 'admin'
"
@click="deleteMessage(message)" @click="deleteMessage(message)"
> >
<v-icon> mdi-delete </v-icon> <v-icon> mdi-delete </v-icon>
@ -555,9 +591,7 @@
<v-btn <v-btn
v-on="on" v-on="on"
icon icon
v-if=" v-if="chat.rank === 'admin' || chat.chat.type === 'direct'"
chat.rank === 'admin' || chat.chat.type === 'direct'
"
@click=" @click="
pinMessage() pinMessage()
focusInput() focusInput()
@ -569,306 +603,19 @@
</template> </template>
<span> Pin to Chat </span> <span> Pin to Chat </span>
</v-tooltip> </v-tooltip>
<v-menu offset-y v-if="$store.state.site.release === 'dev'">
<template v-slot:activator="{ on, attrs }">
<v-btn v-on="on" icon v-bind="attrs">
<v-icon> mdi-dots-horizontal </v-icon>
</v-btn>
</template>
<v-list>
<v-list-item><v-icon>mdi-delete</v-icon> Delete </v-list-item>
</v-list>
</v-menu>
</v-card> </v-card>
</v-list-item> </v-list-item>
</template> </template>
<template v-else-if="message.type === 'leave'">
<v-list-item :key="message.keyId" :id="'message-' + index">
<v-icon color="red" class="mr-2 ml-1"> mdi-arrow-left </v-icon>
<v-list-item-content>
{{ message.content }}
</v-list-item-content>
<v-list-item-action>
<v-list-item-subtitle>
{{ $date(message.createdAt).format("DD/MM/YYYY hh:mm A") }}
</v-list-item-subtitle>
<v-list-item-subtitle>
<v-btn
icon
v-if="message.userId === $store.state.user.id"
@click="deleteMessage(message)"
>
<v-icon> mdi-delete </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = message.content
edit.editing = true
edit.id = message.id
"
v-if="
message.userId === $store.state.user.id &&
edit.id !== message.id
"
>
<v-icon> mdi-pencil </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = ''
edit.editing = false
edit.id = null
"
v-if="
message.userId === $store.state.user.id &&
edit.id === message.id
"
>
<v-icon> mdi-close </v-icon>
</v-btn>
<v-btn
icon
@click="
replying(message)
focusInput()
"
>
<v-icon> mdi-reply </v-icon>
</v-btn>
</v-list-item-subtitle>
</v-list-item-action>
</v-list-item>
</template>
<template v-else-if="message.type === 'join'">
<v-list-item :key="message.keyId" :id="'message-' + index">
<v-icon color="success" class="mr-2 ml-1"> mdi-arrow-right </v-icon>
<v-list-item-content>
{{ message.content }}
</v-list-item-content>
<v-list-item-action>
<v-list-item-subtitle>
{{ $date(message.createdAt).format("DD/MM/YYYY hh:mm A") }}
</v-list-item-subtitle>
<v-list-item-subtitle>
<v-btn
icon
v-if="message.userId === $store.state.user.id"
@click="deleteMessage(message)"
>
<v-icon> mdi-delete </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = message.content
edit.editing = true
edit.id = message.id
"
v-if="
message.userId === $store.state.user.id &&
edit.id !== message.id
"
>
<v-icon> mdi-pencil </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = ''
edit.editing = false
edit.id = null
"
v-if="
message.userId === $store.state.user.id &&
edit.id === message.id
"
>
<v-icon> mdi-close </v-icon>
</v-btn>
<v-btn
icon
@click="
replying(message)
focusInput()
"
>
<v-icon> mdi-reply </v-icon>
</v-btn>
</v-list-item-subtitle>
</v-list-item-action>
</v-list-item>
</template>
<template v-else-if="message.type === 'rename'">
<v-list-item :key="message.keyId" :id="'message-' + index">
<v-icon color="grey" class="mr-2 ml-1"> mdi-pencil </v-icon>
<v-list-item-content>
{{ message.content }}
</v-list-item-content>
<v-list-item-action>
<v-list-item-subtitle>
{{ $date(message.createdAt).format("DD/MM/YYYY hh:mm A") }}
</v-list-item-subtitle>
<v-list-item-subtitle>
<v-btn
icon
v-if="message.userId === $store.state.user.id"
@click="deleteMessage(message)"
>
<v-icon> mdi-delete </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = message.content
edit.editing = true
edit.id = message.id
"
v-if="
message.userId === $store.state.user.id &&
edit.id !== message.id
"
>
<v-icon> mdi-pencil </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = ''
edit.editing = false
edit.id = null
"
v-if="
message.userId === $store.state.user.id &&
edit.id === message.id
"
>
<v-icon> mdi-close </v-icon>
</v-btn>
<v-btn
icon
@click="
replying(message)
focusInput()
"
>
<v-icon> mdi-reply </v-icon>
</v-btn>
</v-list-item-subtitle>
</v-list-item-action>
</v-list-item>
</template>
<template v-else-if="message.type === 'pin'">
<v-list-item :key="message.keyId" :id="'message-' + index">
<v-icon color="grey" class="mr-2 ml-1"> mdi-pin-outline </v-icon>
<v-list-item-content>
{{ message.content }}
</v-list-item-content>
<v-list-item-action>
<v-list-item-subtitle>
{{ $date(message.createdAt).format("DD/MM/YYYY hh:mm A") }}
</v-list-item-subtitle>
<v-list-item-subtitle>
<v-btn
icon
v-if="message.userId === $store.state.user.id"
@click="deleteMessage(message)"
>
<v-icon> mdi-delete </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = message.content
edit.editing = true
edit.id = message.id
"
v-if="
message.userId === $store.state.user.id &&
edit.id !== message.id
"
>
<v-icon> mdi-pencil </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = ''
edit.editing = false
edit.id = null
"
v-if="
message.userId === $store.state.user.id &&
edit.id === message.id
"
>
<v-icon> mdi-close </v-icon>
</v-btn>
<v-btn
icon
@click="
replying(message)
focusInput()
"
>
<v-icon> mdi-reply </v-icon>
</v-btn>
</v-list-item-subtitle>
</v-list-item-action>
</v-list-item>
</template>
<template v-else>
<v-list-item :key="message.keyId" :id="'message-' + index">
<v-icon color="grey" class="mr-2 ml-1"> mdi-pencil </v-icon>
<v-list-item-content>
{{ message.content }}
</v-list-item-content>
<v-list-item-action>
<v-list-item-subtitle>
{{ $date(message.createdAt).format("DD/MM/YYYY hh:mm A") }}
</v-list-item-subtitle>
<v-list-item-subtitle>
<v-btn
icon
v-if="message.userId === $store.state.user.id"
@click="deleteMessage(message)"
>
<v-icon> mdi-delete </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = message.content
edit.editing = true
edit.id = message.id
"
v-if="
message.userId === $store.state.user.id &&
edit.id !== message.id
"
>
<v-icon> mdi-pencil </v-icon>
</v-btn>
<v-btn
icon
@click="
edit.content = ''
edit.editing = false
edit.id = null
"
v-if="
message.userId === $store.state.user.id &&
edit.id === message.id
"
>
<v-icon> mdi-close </v-icon>
</v-btn>
<v-btn
icon
@click="
replying(message)
focusInput()
"
>
<v-icon> mdi-reply </v-icon>
</v-btn>
</v-list-item-subtitle>
</v-list-item-action>
</v-list-item>
</template>
</span>
</v-hover>
</div> </div>
</template> </template>