Compare commits
5 Commits
edddf9afbf
...
adb7a1161a
Author | SHA1 | Date | |
---|---|---|---|
|
adb7a1161a | ||
|
3c069ed2f8 | ||
|
ae73326820 | ||
|
f40b6758de | ||
|
43e8cc7d3e |
@ -12,10 +12,10 @@ export default class Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async register(body, res: Response) {
|
static async register(body, res: Response) {
|
||||||
const { email, pwd, xoauth, xoauth2, host, port, tls } = body;
|
const { email, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls } = body;
|
||||||
getAddressId(email).then((addressId) => {
|
getAddressId(email).then((addressId) => {
|
||||||
registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls)
|
registerAccount(addressId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls)
|
||||||
.then((mailboxId) => {
|
.then((mailboxId) => {0
|
||||||
res.status(statusCodes.OK).json({ id: mailboxId });
|
res.status(statusCodes.OK).json({ id: mailboxId });
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { execQueryAsync, execQueryAsyncWithId } from "./db";
|
import { execQueryAsync, execQueryAsyncWithId } from "./db";
|
||||||
import { queryCcId, queryToId, queryFromId } from "./utils/addressQueries";
|
import { queryCcId, queryToId, queryFromId } from "./utils/addressQueries";
|
||||||
|
|
||||||
export async function registerAccount(userId, pwd, xoauth, xoauth2, host, port, tls) {
|
export async function registerAccount(userId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls) {
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO app_account
|
INSERT INTO app_account
|
||||||
(user_id, account_pwd, xoauth, xoauth2, host, port, tls) VALUES (?, ?, ?, ?, ?, ?, ?)
|
(user_id, account_pwd, xoauth, xoauth2, imap_host, smtp_host, imap_port, smtp_port, tls) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`;
|
`;
|
||||||
const values = [userId, pwd, xoauth, xoauth2, host, port, tls];
|
const values = [userId, pwd, xoauth, xoauth2, imapHost, smtpHost, imapPort, smtpPort, tls];
|
||||||
return await execQueryAsyncWithId(query, values);
|
return await execQueryAsyncWithId(query, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,10 @@ CREATE TABLE app_account (
|
|||||||
account_pwd BINARY(22),
|
account_pwd BINARY(22),
|
||||||
xoauth VARCHAR(116),
|
xoauth VARCHAR(116),
|
||||||
xoauth2 VARCHAR(116),
|
xoauth2 VARCHAR(116),
|
||||||
host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
imap_host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
||||||
port INT(5) NOT NULL DEFAULT 143,
|
imap_port INT(5) NOT NULL DEFAULT 993,
|
||||||
|
smtp_host VARCHAR(255) NOT NULL DEFAULT 'localhost',
|
||||||
|
smtp_port INT(5) NOT NULL DEFAULT 465,
|
||||||
tls BOOLEAN NOT NULL DEFAULT true,
|
tls BOOLEAN NOT NULL DEFAULT true,
|
||||||
PRIMARY KEY (account_id),
|
PRIMARY KEY (account_id),
|
||||||
FOREIGN KEY (user_id) REFERENCES address(address_id) ON DELETE CASCADE
|
FOREIGN KEY (user_id) REFERENCES address(address_id) ON DELETE CASCADE
|
||||||
|
@ -6,9 +6,11 @@ export async function getAllAccounts() {
|
|||||||
app_account.account_id AS id,
|
app_account.account_id AS id,
|
||||||
address.email AS user,
|
address.email AS user,
|
||||||
app_account.account_pwd AS password,
|
app_account.account_pwd AS password,
|
||||||
app_account.host AS host,
|
app_account.imap_host,
|
||||||
app_account.port AS port,
|
app_account.imap_port,
|
||||||
app_account.tls AS tls
|
app_account.smtp_host,
|
||||||
|
app_account.smtp_port,
|
||||||
|
app_account.tls
|
||||||
FROM app_account INNER JOIN address
|
FROM app_account INNER JOIN address
|
||||||
WHERE address.address_id = app_account.user_id
|
WHERE address.address_id = app_account.user_id
|
||||||
`;
|
`;
|
||||||
|
@ -14,9 +14,9 @@ export class ImapInstance {
|
|||||||
this.imap = new Imap({
|
this.imap = new Imap({
|
||||||
user: account.user,
|
user: account.user,
|
||||||
password: account.password,
|
password: account.password,
|
||||||
tlsOptions: { servername: account.host },
|
tlsOptions: { servername: account.imap_host },
|
||||||
host: account.host,
|
host: account.imap_host,
|
||||||
port: account.port,
|
port: account.imap_port,
|
||||||
tls: account.tls,
|
tls: account.tls,
|
||||||
});
|
});
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
@ -5,12 +5,11 @@ export class SmtpInstance {
|
|||||||
transporter: Transporter;
|
transporter: Transporter;
|
||||||
user: string;
|
user: string;
|
||||||
|
|
||||||
constructor(account: { user: string; password: string }) {
|
constructor(account: { user: string; password: string, smtp_host: string, smtp_port: number }) {
|
||||||
// todo store other data
|
|
||||||
this.user = account.user;
|
this.user = account.user;
|
||||||
this.transporter = nodemailer.createTransport({
|
this.transporter = nodemailer.createTransport({
|
||||||
host: "smtp.gmail.com",
|
host: account.smtp_host,
|
||||||
port: 465,
|
port: account.smtp_port,
|
||||||
secure: true,
|
secure: true,
|
||||||
auth: {
|
auth: {
|
||||||
user: account.user,
|
user: account.user,
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
"pwd": { "type": "string" },
|
"pwd": { "type": "string" },
|
||||||
"xoauth": { "type": "string" },
|
"xoauth": { "type": "string" },
|
||||||
"xoauth2": { "type": "string" },
|
"xoauth2": { "type": "string" },
|
||||||
"host": { "type": "string", "format": "hostname" },
|
"imapHost": { "type": "string", "format": "hostname" },
|
||||||
"port": { "type": "number", "maximum": 65535 },
|
"smtpHost": { "type": "string", "format": "hostname" },
|
||||||
|
"imapPort": { "type": "number", "maximum": 65535 },
|
||||||
|
"smtpPort": { "type": "number", "maximum": 65535 },
|
||||||
"tls": { "type": "boolean" }
|
"tls": { "type": "boolean" }
|
||||||
},
|
},
|
||||||
"required": ["email", "host", "port", "tls"],
|
"required": ["email", "imapHost", "smtpHost", "imapPort", "smtpPort", "tls"],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
@ -142,11 +142,11 @@ function mailChange() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<Input label="Plain password:" v-model="pwd" type="password" />
|
||||||
|
</div>
|
||||||
<!-- <fieldset>
|
<!-- <fieldset>
|
||||||
<legend>Authentification method</legend>
|
<legend>Authentification method</legend>
|
||||||
<div class="field">
|
|
||||||
<Input label="Plain password:" v-model="pwd" type="password" />
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<Input label="Xoauth:" v-model="xoauth" type="text" />
|
<Input label="Xoauth:" v-model="xoauth" type="text" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,26 +1,59 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Message } from "@/store/models/model";
|
import { Address, Message, Room } from "@/store/models/model";
|
||||||
import { ref, watch, defineProps, PropType } from "vue";
|
import { ref, Ref, watch, defineProps, PropType } from "vue";
|
||||||
import Content from "../structure/message/Content.vue";
|
import Content from "../structure/message/Content.vue";
|
||||||
import Modal from "./Modal.vue";
|
import Modal from "./Modal.vue";
|
||||||
|
import MemberList from "@/views/room/MemberList.vue";
|
||||||
|
import { removeDuplicates } from "@/utils/array";
|
||||||
|
import { decodeEmojis } from "@/utils/string";
|
||||||
|
|
||||||
const props = defineProps({ messageId: { type: Number, require: true }, message: Object as PropType<Message> });
|
const props = defineProps({
|
||||||
|
messageId: { type: Number, require: true },
|
||||||
|
message: Object as PropType<Message>,
|
||||||
|
room: Object as PropType<Room>,
|
||||||
|
});
|
||||||
|
|
||||||
const messageId = ref(-1);
|
const messageId = ref(-1);
|
||||||
|
const fromA = ref<Address[]>([]);
|
||||||
|
const toA = ref<Address[]>([]);
|
||||||
|
const ccA = ref<Address[]>([]);
|
||||||
|
|
||||||
|
const getAddr = (ids: string | undefined, addrs: Address[] | undefined, res: Ref<Address[]>) => {
|
||||||
|
res.value = [];
|
||||||
|
if (!ids || !addrs) return;
|
||||||
|
let idsClean = removeDuplicates(ids.split(","));
|
||||||
|
idsClean.forEach((id) => {
|
||||||
|
let addr = addrs.find((member) => member.id === parseInt(id));
|
||||||
|
if (addr) {
|
||||||
|
res.value.push(addr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.messageId,
|
() => props.messageId,
|
||||||
(newMessageId: number | undefined) => {
|
(newMessageId: number | undefined) => {
|
||||||
if (!newMessageId) return;
|
if (!newMessageId) return;
|
||||||
messageId.value = newMessageId;
|
messageId.value = newMessageId;
|
||||||
|
getAddr(props.message?.fromA, props.room?.members, fromA);
|
||||||
|
getAddr(props.message?.toA, props.room?.members, toA);
|
||||||
|
getAddr(props.message?.ccA, props.room?.members, ccA);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<Modal v-if="messageId != -1" @close-modal="() => $emit('close')">
|
<Modal v-if="messageId != -1" @close-modal="() => $emit('close')" id="modal">
|
||||||
|
<template v-slot:header>
|
||||||
|
<h2 id="header">
|
||||||
|
{{ decodeEmojis(props.message?.subject) ?? "No Object" }}
|
||||||
|
</h2>
|
||||||
|
</template>
|
||||||
<template v-slot:body>
|
<template v-slot:body>
|
||||||
<div>{{ props.message?.subject ?? "No Object" }}</div>
|
<MemberList type="from" :members="fromA" />
|
||||||
|
<MemberList type="to" :members="toA" />
|
||||||
|
<MemberList v-if="ccA.length > 0" type="cc" :members="ccA" />
|
||||||
<Content type="large" :content="props.message?.content" class="content" />
|
<Content type="large" :content="props.message?.content" class="content" />
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
@ -31,6 +64,11 @@ watch(
|
|||||||
.main {
|
.main {
|
||||||
min-width: 700px;
|
min-width: 700px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
/* todo define size automatically */
|
/* todo define size automatically */
|
||||||
.content {
|
.content {
|
||||||
width: 700px;
|
width: 700px;
|
||||||
|
@ -26,7 +26,9 @@ onUnmounted(() => {
|
|||||||
<div class="modal-wrapper">
|
<div class="modal-wrapper">
|
||||||
<div class="modal" v-on-click-outside="close">
|
<div class="modal" v-on-click-outside="close">
|
||||||
<header class="modal-header">
|
<header class="modal-header">
|
||||||
<h2>{{ props.title }}</h2>
|
<slot name="header">
|
||||||
|
<h2>{{ props.title }}</h2>
|
||||||
|
</slot>
|
||||||
<div class="close-button" @click="close"></div>
|
<div class="close-button" @click="close"></div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -190,19 +190,19 @@ const getClasses = (isActive, disabled = false) => {
|
|||||||
svg="align-center"
|
svg="align-center"
|
||||||
@click="editor.chain().focus().setTextAlign('center').run()"
|
@click="editor.chain().focus().setTextAlign('center').run()"
|
||||||
:classes="getClasses(editor.isActive({ textAlign: 'center' }))"
|
:classes="getClasses(editor.isActive({ textAlign: 'center' }))"
|
||||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'E'] }"
|
v-tooltip="{ text: 'Align Center', shortcut: ['Ctrl', 'Shift', 'E'] }"
|
||||||
/>
|
/>
|
||||||
<SvgLoader
|
<SvgLoader
|
||||||
svg="align-right"
|
svg="align-right"
|
||||||
@click="editor.chain().focus().setTextAlign('right').run()"
|
@click="editor.chain().focus().setTextAlign('right').run()"
|
||||||
:classes="getClasses(editor.isActive({ textAlign: 'right' }))"
|
:classes="getClasses(editor.isActive({ textAlign: 'right' }))"
|
||||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'R'] }"
|
v-tooltip="{ text: 'Align Right', shortcut: ['Ctrl', 'Shift', 'R'] }"
|
||||||
/>
|
/>
|
||||||
<SvgLoader
|
<SvgLoader
|
||||||
svg="align-justify"
|
svg="align-justify"
|
||||||
@click="editor.chain().focus().setTextAlign('justify').run()"
|
@click="editor.chain().focus().setTextAlign('justify').run()"
|
||||||
:classes="getClasses(editor.isActive({ textAlign: 'justify' }))"
|
:classes="getClasses(editor.isActive({ textAlign: 'justify' }))"
|
||||||
v-tooltip="{ text: 'Align Left', shortcut: ['Ctrl', 'Shift', 'J'] }"
|
v-tooltip="{ text: 'Justify', shortcut: ['Ctrl', 'Shift', 'J'] }"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps, withDefaults, ref } from "vue";
|
import { defineProps, withDefaults, ref } from "vue";
|
||||||
import { decodeEmojis } from "../../../utils/string";
|
import { decodeEmojis } from "../../../utils/string";
|
||||||
import { removeDuplicates } from "../../../utils/array";
|
|
||||||
import { Address, Message } from "@/store/models/model";
|
import { Address, Message } from "@/store/models/model";
|
||||||
import Content from "./Content.vue";
|
import Content from "./Content.vue";
|
||||||
import Options from "./Options.vue";
|
import Options from "./Options.vue";
|
||||||
import { isSeenFc } from "@/utils/flagsUtils";
|
import { isSeenFc } from "@/utils/flagsUtils";
|
||||||
import SvgLoader from "@/components/utils/SvgLoader.vue";
|
import SvgLoader from "@/components/utils/SvgLoader.vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import { displayAddresses } from "@/utils/address";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
msg: Message;
|
msg: Message;
|
||||||
@ -21,17 +21,6 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
|
|
||||||
const compact = ref(props.compact);
|
const compact = ref(props.compact);
|
||||||
|
|
||||||
const displayAddresses = (addressIds: string[] | undefined): string => {
|
|
||||||
if (!addressIds) return "";
|
|
||||||
addressIds = removeDuplicates(addressIds);
|
|
||||||
let res = "";
|
|
||||||
addressIds.forEach((addressId) => {
|
|
||||||
const address = props.members?.find((member) => member.id === parseInt(addressId));
|
|
||||||
if (address) res += address.email;
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
const classes = (): string => {
|
const classes = (): string => {
|
||||||
const flags = props.msg?.flags;
|
const flags = props.msg?.flags;
|
||||||
|
|
||||||
@ -45,6 +34,15 @@ const classes = (): string => {
|
|||||||
return "msg-basic";
|
return "msg-basic";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const style = (prop: string): string => {
|
||||||
|
// get color of the member that send the message
|
||||||
|
let member = props.members?.find((member) => member.id === parseInt(props.msg?.fromA?.split(",")[0]));
|
||||||
|
if (member?.color) {
|
||||||
|
return `${prop}: ${member.color} !important`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
<!-- to if to is more than me
|
<!-- to if to is more than me
|
||||||
@ -54,9 +52,9 @@ const router = useRouter();
|
|||||||
attachments -->
|
attachments -->
|
||||||
<template>
|
<template>
|
||||||
<div class="message" @dblclick="$emit('openMessageView', props.msg?.id)">
|
<div class="message" @dblclick="$emit('openMessageView', props.msg?.id)">
|
||||||
<div id="context">
|
<div id="context" :style="style('background-color')">
|
||||||
<div class="left" id="profile">
|
<div class="left" id="profile">
|
||||||
{{ displayAddresses(props.msg?.fromA?.split(",")) }} - {{ props.msg?.fromA }}
|
{{ displayAddresses(props.msg?.fromA?.split(","), props.members) }} - {{ props.msg?.fromA }}
|
||||||
</div>
|
</div>
|
||||||
<div class="middle">{{ decodeEmojis(props.msg?.subject) }}</div>
|
<div class="middle">{{ decodeEmojis(props.msg?.subject) }}</div>
|
||||||
<div class="right" id="date">
|
<div class="right" id="date">
|
||||||
@ -73,7 +71,7 @@ const router = useRouter();
|
|||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" :class="[classes()]">
|
<div class="content" :class="[classes()]" :style="style('border-color')">
|
||||||
<Content v-if="!compact" :content="props.msg?.content" />
|
<Content v-if="!compact" :content="props.msg?.content" />
|
||||||
<SvgLoader
|
<SvgLoader
|
||||||
v-if="compact"
|
v-if="compact"
|
||||||
@ -86,7 +84,6 @@ const router = useRouter();
|
|||||||
</div>
|
</div>
|
||||||
<div id="thread-link" v-if="props.msg?.thread" @click="router.push(`/${props.msg?.thread}`)">
|
<div id="thread-link" v-if="props.msg?.thread" @click="router.push(`/${props.msg?.thread}`)">
|
||||||
<SvgLoader svg="expand-left-fill" />
|
<SvgLoader svg="expand-left-fill" />
|
||||||
<!-- <SvgLoader svg="expand-left-fill" :loading="true" /> -->
|
|
||||||
<span>Go to the full conversation.</span>
|
<span>Go to the full conversation.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -133,8 +130,11 @@ const router = useRouter();
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-top: 6px;
|
padding: 6px;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
border: solid 4px var(--quaternary-background);
|
||||||
|
border-top: 0;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expand-contract {
|
.expand-contract {
|
||||||
|
@ -15,7 +15,7 @@ export interface Message {
|
|||||||
content: string;
|
content: string;
|
||||||
date: string;
|
date: string;
|
||||||
flags: string[];
|
flags: string[];
|
||||||
threads: number | null;
|
thread: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LoadingState {
|
export enum LoadingState {
|
||||||
@ -47,5 +47,6 @@ export interface Address {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
email: string;
|
email: string;
|
||||||
|
color: string | undefined;
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { decodeEmojis } from "@/utils/string";
|
|||||||
import { AxiosError, AxiosResponse } from "axios";
|
import { AxiosError, AxiosResponse } from "axios";
|
||||||
import { createStore } from "vuex";
|
import { createStore } from "vuex";
|
||||||
import { Room, Account, Address, RoomType, Message, LoadingState } from "./models/model";
|
import { Room, Account, Address, RoomType, Message, LoadingState } from "./models/model";
|
||||||
|
import { removeDuplicates } from "@/utils/array";
|
||||||
|
|
||||||
interface RoomFromBack {
|
interface RoomFromBack {
|
||||||
id: number;
|
id: number;
|
||||||
@ -154,6 +155,10 @@ const store = createStore<State>({
|
|||||||
if (!roomMessage) return;
|
if (!roomMessage) return;
|
||||||
payload.messages.forEach((message: any) => {
|
payload.messages.forEach((message: any) => {
|
||||||
message.flags = message.flags?.split(",") ?? [];
|
message.flags = message.flags?.split(",") ?? [];
|
||||||
|
// todo fix upstream
|
||||||
|
// message.fromA = message.fromA ? removeDuplicates(message.fromA.split(",").join(",")) : null;
|
||||||
|
// message.toA = message.toA ? removeDuplicates(message.toA.split(",").join(",")) : null;
|
||||||
|
// message.ccA = message.ccA ? removeDuplicates(message.ccA.split(",").join(",")) : null;
|
||||||
roomMessage?.messages.push(message);
|
roomMessage?.messages.push(message);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
13
front/src/utils/address.ts
Normal file
13
front/src/utils/address.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Address } from "@/store/models/model";
|
||||||
|
import { removeDuplicates } from "./array";
|
||||||
|
|
||||||
|
export const displayAddresses = (addressIds: string[] | undefined, members: Address[]): string => {
|
||||||
|
if (!addressIds) return "";
|
||||||
|
addressIds = removeDuplicates(addressIds);
|
||||||
|
let res = "";
|
||||||
|
addressIds.forEach((addressId) => {
|
||||||
|
const address = members?.find((member) => member.id === parseInt(addressId));
|
||||||
|
if (address) res += address.email;
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
@ -72,7 +72,12 @@ provide("room", room);
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Composer v-if="shouldDisplayComposer() || true" />
|
<Composer v-if="shouldDisplayComposer() || true" />
|
||||||
<MessageViewModal :message="message" :messageId="messageIdView" @close="() => openMessageView(-1)" />
|
<MessageViewModal
|
||||||
|
:room="room"
|
||||||
|
:message="message"
|
||||||
|
:messageId="messageIdView"
|
||||||
|
@close="() => openMessageView(-1)"
|
||||||
|
/>
|
||||||
<!-- todo -->
|
<!-- todo -->
|
||||||
<!-- <ConfirmationModal /> -->
|
<!-- <ConfirmationModal /> -->
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user