thelounge/client/components/Chat.vue

193 lines
4.9 KiB
Vue
Raw Normal View History

<template>
<div id="chat-container" class="window" :data-current-channel="channel.name">
2018-07-08 15:42:54 +02:00
<div
id="chat"
2018-07-09 12:44:12 +02:00
:data-id="channel.id"
:class="{
'hide-motd': !$store.state.settings.motd,
'colored-nicks': $store.state.settings.coloredNicks,
'show-seconds': $store.state.settings.showSeconds,
}"
>
<div
:id="'chan-' + channel.id"
:class="[channel.type, 'chan', 'active']"
:data-id="channel.id"
:data-type="channel.type"
:aria-label="channel.name"
role="tabpanel"
>
<div class="header">
<SidebarToggle />
<span class="title">{{ channel.name }}</span>
<div v-if="channel.editTopic === true" class="topic-container">
<input
:value="channel.topic"
class="topic-input"
placeholder="Set channel topic"
@keyup.enter="saveTopic"
@keyup.esc="channel.editTopic = false"
/>
<span aria-label="Save topic" class="save-topic" @click="saveTopic">
<span type="button" aria-label="Save topic"></span>
</span>
</div>
<span v-else :title="channel.topic" class="topic" @dblclick="editTopic"
2019-07-17 11:33:59 +02:00
><ParsedMessage
v-if="channel.topic"
:network="network"
:text="channel.topic"
/></span>
2019-07-17 11:33:59 +02:00
<button class="menu" aria-label="Open the context menu" />
<span
v-if="channel.type === 'channel'"
class="rt-tooltip tooltipped tooltipped-w"
aria-label="Toggle user list"
>
<button
class="rt"
aria-label="Toggle user list"
@click="$root.toggleUserlist"
/>
</span>
</div>
2019-07-17 11:33:59 +02:00
<div v-if="channel.type === 'special'" class="chat-content">
<div class="chat">
<div class="messages">
<div class="msg">
2018-12-17 11:29:49 +01:00
<Component
:is="specialComponent"
2018-07-19 19:44:24 +02:00
:network="network"
:channel="channel"
/>
</div>
</div>
</div>
2018-07-10 11:16:24 +02:00
</div>
2019-07-17 11:33:59 +02:00
<div v-else class="chat-content">
<div
2019-07-17 11:33:59 +02:00
:class="[
'scroll-down tooltipped tooltipped-w tooltipped-no-touch',
{'scroll-down-shown': !channel.scrolledToBottom},
]"
aria-label="Jump to recent messages"
@click="$refs.messageList.jumpToBottom()"
>
<div class="scroll-down-arrow" />
</div>
2019-07-17 11:33:59 +02:00
<MessageList ref="messageList" :network="network" :channel="channel" />
<ChatUserList v-if="channel.type === 'channel'" :channel="channel" />
</div>
</div>
</div>
2018-08-31 12:43:21 +02:00
<div
v-if="this.$store.state.currentUserVisibleError"
2018-10-16 12:21:16 +02:00
id="user-visible-error"
@click="hideUserVisibleError"
2019-07-17 11:33:59 +02:00
>
{{ this.$store.state.currentUserVisibleError }}
2019-07-17 11:33:59 +02:00
</div>
2018-09-03 09:58:33 +02:00
<span id="upload-progressbar" />
2019-07-17 11:33:59 +02:00
<ChatInput :network="network" :channel="channel" />
</div>
</template>
<script>
const socket = require("../js/socket");
2018-07-12 10:41:40 +02:00
import ParsedMessage from "./ParsedMessage.vue";
import MessageList from "./MessageList.vue";
2018-07-08 15:42:54 +02:00
import ChatInput from "./ChatInput.vue";
import ChatUserList from "./ChatUserList.vue";
import SidebarToggle from "./SidebarToggle.vue";
2018-07-10 11:16:24 +02:00
import ListBans from "./Special/ListBans.vue";
2019-04-14 13:44:44 +02:00
import ListInvites from "./Special/ListInvites.vue";
2018-07-10 11:37:48 +02:00
import ListChannels from "./Special/ListChannels.vue";
2018-07-11 09:54:32 +02:00
import ListIgnored from "./Special/ListIgnored.vue";
export default {
name: "Chat",
components: {
2018-07-12 10:41:40 +02:00
ParsedMessage,
MessageList,
2018-07-08 15:42:54 +02:00
ChatInput,
ChatUserList,
SidebarToggle,
},
props: {
network: Object,
channel: Object,
},
2018-07-10 11:16:24 +02:00
computed: {
specialComponent() {
2018-07-10 11:37:48 +02:00
switch (this.channel.special) {
2019-07-17 11:33:59 +02:00
case "list_bans":
return ListBans;
case "list_invites":
return ListInvites;
case "list_channels":
return ListChannels;
case "list_ignored":
return ListIgnored;
2018-07-10 11:16:24 +02:00
}
2018-12-17 11:29:49 +01:00
return undefined;
2018-07-10 11:16:24 +02:00
},
},
2019-10-17 18:56:44 +02:00
watch: {
channel(_, previousChannel) {
this.channelChanged(previousChannel);
},
},
mounted() {
this.channelChanged();
},
methods: {
2019-10-17 18:56:44 +02:00
channelChanged(previousChannel) {
// Triggered when active channel is set or changed
if (previousChannel) {
this.$root.switchOutOfChannel(previousChannel);
}
this.channel.highlight = 0;
this.channel.unread = 0;
this.$store.commit("activeWindow", null);
socket.emit("open", this.channel.id);
if (this.channel.usersOutdated) {
this.channel.usersOutdated = false;
socket.emit("names", {
target: this.channel.id,
});
}
this.$root.synchronizeNotifiedState();
},
hideUserVisibleError() {
this.$store.commit("currentUserVisibleError", null);
},
editTopic() {
if (this.channel.type === "channel") {
this.channel.editTopic = true;
this.$nextTick(() => {
document.querySelector(`#chan-${this.channel.id} .topic-input`).focus();
});
}
},
saveTopic() {
this.channel.editTopic = false;
const newTopic = document.querySelector(`#chan-${this.channel.id} .topic-input`).value;
if (this.channel.topic !== newTopic) {
const target = this.channel.id;
const text = `/raw TOPIC ${this.channel.name} :${newTopic}`;
socket.emit("input", {target, text});
}
},
},
};
</script>