2018-07-08 15:42:54 +02:00
|
|
|
<template>
|
2019-07-17 11:33:59 +02:00
|
|
|
<form id="form" method="post" action="" @submit.prevent="onSubmit">
|
2020-03-19 20:20:45 +01:00
|
|
|
<div class="toolbar-container" :class="{opened: showToolbar}">
|
|
|
|
<div class="toolbar">
|
|
|
|
<button
|
|
|
|
class="format format-b"
|
|
|
|
type="button"
|
|
|
|
aria-label="Bold"
|
|
|
|
@click="applyFormatting('bold')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-u"
|
|
|
|
type="button"
|
|
|
|
aria-label="Underline"
|
|
|
|
@click="applyFormatting('underline')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-i"
|
|
|
|
type="button"
|
|
|
|
aria-label="Italic"
|
|
|
|
@click="applyFormatting('italic')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-s"
|
|
|
|
type="button"
|
|
|
|
aria-label="Strikethrough"
|
|
|
|
@click="applyFormatting('strikeThrough')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-m"
|
|
|
|
type="button"
|
|
|
|
aria-label="Monospace"
|
|
|
|
@click="applyFormatting('monospace')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-c"
|
|
|
|
type="button"
|
|
|
|
aria-label="Color"
|
|
|
|
@click="applyFormatting('color')"
|
|
|
|
></button>
|
|
|
|
<button
|
|
|
|
class="format format-o"
|
|
|
|
type="button"
|
|
|
|
aria-label="Clear formatting"
|
|
|
|
@click="applyFormatting('removeFormat')"
|
|
|
|
></button>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-12-04 07:58:23 +01:00
|
|
|
<span id="upload-progressbar" />
|
2018-07-08 15:42:54 +02:00
|
|
|
<span id="nick">{{ network.nick }}</span>
|
2020-03-19 20:20:45 +01:00
|
|
|
<WysiwygInput
|
|
|
|
ref="wysiwyg"
|
2018-07-08 15:42:54 +02:00
|
|
|
:placeholder="getInputPlaceholder(channel)"
|
2020-03-19 20:20:45 +01:00
|
|
|
@submit="onSubmit"
|
2019-02-25 06:38:13 +01:00
|
|
|
/>
|
2020-03-19 20:20:45 +01:00
|
|
|
<span
|
|
|
|
id="format-tooltip"
|
|
|
|
class="tooltipped tooltipped-w tooltipped-no-touch"
|
|
|
|
aria-label="Text formatting"
|
|
|
|
>
|
|
|
|
<button
|
|
|
|
id="format"
|
|
|
|
type="button"
|
|
|
|
class="chat-input-button"
|
|
|
|
aria-label="Text formatting"
|
|
|
|
@click="toggleToolbar"
|
|
|
|
/>
|
|
|
|
</span>
|
2018-09-03 09:58:33 +02:00
|
|
|
<span
|
2019-11-12 11:40:17 +01:00
|
|
|
v-if="$store.state.serverConfiguration.fileUpload"
|
2018-09-03 09:58:33 +02:00
|
|
|
id="upload-tooltip"
|
|
|
|
class="tooltipped tooltipped-w tooltipped-no-touch"
|
2019-02-18 08:19:44 +01:00
|
|
|
aria-label="Upload file"
|
2019-02-25 06:38:13 +01:00
|
|
|
@click="openFileUpload"
|
|
|
|
>
|
2019-10-21 17:52:46 +02:00
|
|
|
<input
|
|
|
|
id="upload-input"
|
|
|
|
ref="uploadInput"
|
|
|
|
type="file"
|
2020-08-28 03:57:12 +02:00
|
|
|
aria-labelledby="upload"
|
2020-03-19 20:20:45 +01:00
|
|
|
class="chat-input-button"
|
2019-10-21 17:52:46 +02:00
|
|
|
multiple
|
|
|
|
@change="onUploadInputChange"
|
|
|
|
/>
|
2018-09-03 09:58:33 +02:00
|
|
|
<button
|
|
|
|
id="upload"
|
|
|
|
type="button"
|
2020-03-19 20:20:45 +01:00
|
|
|
class="chat-input-button"
|
2018-09-12 21:44:49 +02:00
|
|
|
aria-label="Upload file"
|
2019-02-26 21:23:41 +01:00
|
|
|
:disabled="!$store.state.isConnected"
|
2019-02-25 06:38:13 +01:00
|
|
|
/>
|
2018-09-03 09:58:33 +02:00
|
|
|
</span>
|
2018-07-08 15:42:54 +02:00
|
|
|
<span
|
|
|
|
id="submit-tooltip"
|
|
|
|
class="tooltipped tooltipped-w tooltipped-no-touch"
|
2019-02-25 06:38:13 +01:00
|
|
|
aria-label="Send message"
|
|
|
|
>
|
2018-07-08 15:42:54 +02:00
|
|
|
<button
|
|
|
|
id="submit"
|
|
|
|
type="submit"
|
2020-03-19 20:20:45 +01:00
|
|
|
class="chat-input-button"
|
2018-09-12 21:54:20 +02:00
|
|
|
aria-label="Send message"
|
2019-02-26 21:23:41 +01:00
|
|
|
:disabled="!$store.state.isConnected"
|
2019-02-25 06:38:13 +01:00
|
|
|
/>
|
2018-07-08 15:42:54 +02:00
|
|
|
</span>
|
|
|
|
</form>
|
|
|
|
</template>
|
|
|
|
|
2020-03-19 20:20:45 +01:00
|
|
|
<style>
|
|
|
|
.toolbar button.format-b::before {
|
|
|
|
content: "\f032"; /* https://fontawesome.io/icon/bold/ */
|
|
|
|
}
|
|
|
|
.toolbar button.format-u::before {
|
|
|
|
content: "\f0cd"; /* https://fontawesome.io/icon/underline/ */
|
|
|
|
}
|
|
|
|
.toolbar button.format-i::before {
|
|
|
|
content: "\f033"; /* https://fontawesome.io/icon/italic/ */
|
|
|
|
}
|
|
|
|
.toolbar button.format-s::before {
|
|
|
|
content: "\f0cc"; /* https://fontawesome.io/icon/strikethrough/ */
|
|
|
|
}
|
|
|
|
.toolbar button.format-m::before {
|
|
|
|
content: "\f121"; /* https://fontawesome.io/icon/code/ */
|
|
|
|
}
|
|
|
|
.toolbar button.format-c::before {
|
|
|
|
content: "\f53f"; /* https://fontawesome.com/icons/palette?style=solid */
|
|
|
|
}
|
|
|
|
.toolbar button.format-o::before {
|
|
|
|
content: "\f87d"; /* https://fontawesome.com/icons/remove-format?style=solid */
|
|
|
|
}
|
|
|
|
#form #format::before {
|
|
|
|
content: "\f031"; /* https://fontawesome.io/icons/font/ */
|
|
|
|
}
|
|
|
|
|
|
|
|
#form .toolbar-container {
|
|
|
|
position: absolute;
|
|
|
|
top: -70px;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
#form .toolbar-container.opened {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
#form .toolbar-container .toolbar {
|
|
|
|
display: flex;
|
|
|
|
background: var(--body-bg-color);
|
|
|
|
color: var(--button-color);
|
|
|
|
padding: 0 6px;
|
|
|
|
border-radius: 5px;
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.2s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#form .toolbar-container.opened .toolbar {
|
|
|
|
pointer-events: all;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#form .toolbar-container .toolbar button {
|
|
|
|
padding: 10px 9px;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
2018-07-08 15:42:54 +02:00
|
|
|
<script>
|
2020-03-19 20:20:45 +01:00
|
|
|
// import autocompletion from "../js/autocompletion"; TODO
|
|
|
|
// import commands from "../js/commands/index"; TODO
|
2019-11-16 18:24:03 +01:00
|
|
|
import socket from "../js/socket";
|
|
|
|
import upload from "../js/upload";
|
2020-03-16 18:58:40 +01:00
|
|
|
import eventbus from "../js/eventbus";
|
2020-03-19 20:20:45 +01:00
|
|
|
import WysiwygInput from "./WysiwygInput.vue";
|
2018-07-08 17:17:20 +02:00
|
|
|
|
2019-11-15 19:53:38 +01:00
|
|
|
let autocompletionRef = null;
|
|
|
|
|
2018-07-08 15:42:54 +02:00
|
|
|
export default {
|
|
|
|
name: "ChatInput",
|
2020-03-19 20:20:45 +01:00
|
|
|
components: {
|
|
|
|
WysiwygInput,
|
|
|
|
},
|
2018-07-08 15:42:54 +02:00
|
|
|
props: {
|
|
|
|
network: Object,
|
|
|
|
channel: Object,
|
|
|
|
},
|
2020-03-19 20:20:45 +01:00
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
showToolbar: false,
|
|
|
|
};
|
|
|
|
},
|
2018-07-13 12:24:05 +02:00
|
|
|
watch: {
|
2019-11-24 14:44:03 +01:00
|
|
|
"channel.id"() {
|
|
|
|
if (autocompletionRef) {
|
|
|
|
autocompletionRef.hide();
|
|
|
|
}
|
2020-03-19 20:20:45 +01:00
|
|
|
|
|
|
|
this.closeToolbar();
|
2019-11-24 14:44:03 +01:00
|
|
|
},
|
2018-07-13 12:43:11 +02:00
|
|
|
"channel.pendingMessage"() {
|
2020-03-19 20:20:45 +01:00
|
|
|
this.closeToolbar();
|
2018-07-13 12:24:05 +02:00
|
|
|
},
|
|
|
|
},
|
2018-07-08 16:57:02 +02:00
|
|
|
mounted() {
|
2020-03-16 18:58:40 +01:00
|
|
|
eventbus.on("escapekey", this.blurInput);
|
2020-01-24 10:35:04 +01:00
|
|
|
|
2020-03-19 20:20:45 +01:00
|
|
|
/* TODO
|
2019-11-03 19:05:19 +01:00
|
|
|
if (this.$store.state.settings.autocomplete) {
|
2019-11-15 19:53:38 +01:00
|
|
|
autocompletionRef = autocompletion(this.$refs.input);
|
2018-07-08 16:57:02 +02:00
|
|
|
}
|
2020-03-19 20:20:45 +01:00
|
|
|
*/
|
2018-07-09 20:51:27 +02:00
|
|
|
|
2020-03-19 20:20:45 +01:00
|
|
|
/* TODO
|
2018-07-09 20:51:27 +02:00
|
|
|
const inputTrap = Mousetrap(this.$refs.input);
|
|
|
|
|
2018-09-09 14:23:12 +02:00
|
|
|
inputTrap.bind(["up", "down"], (e, key) => {
|
2019-11-02 20:40:59 +01:00
|
|
|
if (
|
|
|
|
this.$store.state.isAutoCompleting ||
|
|
|
|
e.target.selectionStart !== e.target.selectionEnd
|
|
|
|
) {
|
2018-09-09 14:23:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-02-17 08:59:11 +01:00
|
|
|
const {channel} = this;
|
|
|
|
|
|
|
|
if (channel.inputHistoryPosition === 0) {
|
|
|
|
channel.inputHistory[channel.inputHistoryPosition] = channel.pendingMessage;
|
2018-09-09 14:23:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (key === "up") {
|
2019-02-17 08:59:11 +01:00
|
|
|
if (channel.inputHistoryPosition < channel.inputHistory.length - 1) {
|
|
|
|
channel.inputHistoryPosition++;
|
2018-09-09 14:23:12 +02:00
|
|
|
}
|
2019-02-17 08:59:11 +01:00
|
|
|
} else if (channel.inputHistoryPosition > 0) {
|
|
|
|
channel.inputHistoryPosition--;
|
2018-09-09 14:23:12 +02:00
|
|
|
}
|
|
|
|
|
2019-02-17 08:59:11 +01:00
|
|
|
channel.pendingMessage = channel.inputHistory[channel.inputHistoryPosition];
|
|
|
|
this.$refs.input.value = channel.pendingMessage;
|
2018-09-09 14:23:12 +02:00
|
|
|
this.setInputSize();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
2020-03-19 20:20:45 +01:00
|
|
|
*/
|
2018-09-09 14:23:12 +02:00
|
|
|
|
2019-11-12 11:40:17 +01:00
|
|
|
if (this.$store.state.serverConfiguration.fileUpload) {
|
2019-10-21 17:52:46 +02:00
|
|
|
upload.mounted();
|
2018-09-03 09:58:33 +02:00
|
|
|
}
|
2018-07-08 16:57:02 +02:00
|
|
|
},
|
|
|
|
destroyed() {
|
2020-03-16 18:58:40 +01:00
|
|
|
eventbus.off("escapekey", this.blurInput);
|
2020-01-24 10:35:04 +01:00
|
|
|
|
2019-11-15 19:53:38 +01:00
|
|
|
if (autocompletionRef) {
|
|
|
|
autocompletionRef.destroy();
|
|
|
|
autocompletionRef = null;
|
|
|
|
}
|
|
|
|
|
2019-03-03 19:10:35 +01:00
|
|
|
upload.abort();
|
2018-07-08 16:57:02 +02:00
|
|
|
},
|
2018-07-08 15:42:54 +02:00
|
|
|
methods: {
|
2018-08-29 09:34:21 +02:00
|
|
|
setPendingMessage(e) {
|
|
|
|
this.channel.pendingMessage = e.target.value;
|
2018-09-09 14:23:12 +02:00
|
|
|
this.channel.inputHistoryPosition = 0;
|
2018-08-29 09:34:21 +02:00
|
|
|
this.setInputSize();
|
|
|
|
},
|
2018-07-08 15:42:54 +02:00
|
|
|
getInputPlaceholder(channel) {
|
|
|
|
if (channel.type === "channel" || channel.type === "query") {
|
|
|
|
return `Write to ${channel.name}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
},
|
2020-03-19 20:20:45 +01:00
|
|
|
onSubmit(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
if (!this.$store.state.isConnected) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const target = this.channel.id;
|
|
|
|
// const content = this.$refs.wysiwyg.getHtmlContent(); TODO: use this for input history
|
|
|
|
const lines = this.$refs.wysiwyg.getIrcLines();
|
|
|
|
|
|
|
|
this.$refs.wysiwyg.clear();
|
|
|
|
this.$refs.wysiwyg.focus();
|
|
|
|
|
|
|
|
const message = lines.join("\n");
|
|
|
|
socket.emit("input", {target, text: message});
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2018-07-08 17:17:20 +02:00
|
|
|
onSubmit() {
|
|
|
|
// Triggering click event opens the virtual keyboard on mobile
|
|
|
|
// This can only be called from another interactive event (e.g. button click)
|
2018-08-29 09:34:21 +02:00
|
|
|
this.$refs.input.click();
|
|
|
|
this.$refs.input.focus();
|
2018-07-08 17:17:20 +02:00
|
|
|
|
2019-02-27 15:15:34 +01:00
|
|
|
if (!this.$store.state.isConnected) {
|
2018-08-15 11:00:54 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-08 17:17:20 +02:00
|
|
|
const target = this.channel.id;
|
2018-07-08 20:21:24 +02:00
|
|
|
const text = this.channel.pendingMessage;
|
2018-07-08 17:17:20 +02:00
|
|
|
|
|
|
|
if (text.length === 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-11-15 19:53:38 +01:00
|
|
|
if (autocompletionRef) {
|
|
|
|
autocompletionRef.hide();
|
|
|
|
}
|
|
|
|
|
2018-09-09 14:23:12 +02:00
|
|
|
this.channel.inputHistoryPosition = 0;
|
2018-07-08 20:21:24 +02:00
|
|
|
this.channel.pendingMessage = "";
|
2018-08-29 09:34:21 +02:00
|
|
|
this.$refs.input.value = "";
|
|
|
|
this.setInputSize();
|
2018-07-08 17:17:20 +02:00
|
|
|
|
2018-09-09 14:23:12 +02:00
|
|
|
// Store new message in history if last message isn't already equal
|
|
|
|
if (this.channel.inputHistory[1] !== text) {
|
|
|
|
this.channel.inputHistory.splice(1, 0, text);
|
|
|
|
}
|
|
|
|
|
2018-09-12 22:35:55 +02:00
|
|
|
// Limit input history to a 100 entries
|
|
|
|
if (this.channel.inputHistory.length > 100) {
|
|
|
|
this.channel.inputHistory.pop();
|
|
|
|
}
|
|
|
|
|
2018-07-10 09:49:23 +02:00
|
|
|
if (text[0] === "/") {
|
2018-07-08 17:17:20 +02:00
|
|
|
const args = text.substr(1).split(" ");
|
|
|
|
const cmd = args.shift().toLowerCase();
|
|
|
|
|
2019-07-17 11:33:59 +02:00
|
|
|
if (
|
|
|
|
Object.prototype.hasOwnProperty.call(commands, cmd) &&
|
|
|
|
commands[cmd].input(args)
|
|
|
|
) {
|
2018-07-08 17:17:20 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
socket.emit("input", {target, text});
|
|
|
|
},
|
2020-03-19 20:20:45 +01:00
|
|
|
*/
|
2019-10-21 17:52:46 +02:00
|
|
|
onUploadInputChange() {
|
|
|
|
const files = Array.from(this.$refs.uploadInput.files);
|
|
|
|
upload.triggerUpload(files);
|
|
|
|
this.$refs.uploadInput.value = ""; // Reset <input> element so you can upload the same file
|
|
|
|
},
|
2018-09-03 09:58:33 +02:00
|
|
|
openFileUpload() {
|
|
|
|
this.$refs.uploadInput.click();
|
|
|
|
},
|
2020-01-24 10:35:04 +01:00
|
|
|
blurInput() {
|
2020-03-19 20:20:45 +01:00
|
|
|
this.$refs.wysiwyg.blur();
|
|
|
|
},
|
|
|
|
closeToolbar() {
|
|
|
|
this.showToolbar = false;
|
|
|
|
},
|
|
|
|
toggleToolbar() {
|
|
|
|
this.showToolbar = !this.showToolbar;
|
|
|
|
this.$refs.wysiwyg.focus();
|
|
|
|
},
|
|
|
|
applyFormatting(command) {
|
|
|
|
this.$refs.wysiwyg.runCommand(command);
|
|
|
|
this.closeToolbar();
|
|
|
|
this.$refs.wysiwyg.focus();
|
|
|
|
return false;
|
2020-01-24 10:35:04 +01:00
|
|
|
},
|
2018-07-08 15:42:54 +02:00
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|