aboutsummaryrefslogtreecommitdiff
path: root/src/components/shout_panel
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/shout_panel')
-rw-r--r--src/components/shout_panel/shout_panel.js53
-rw-r--r--src/components/shout_panel/shout_panel.vue148
2 files changed, 201 insertions, 0 deletions
diff --git a/src/components/shout_panel/shout_panel.js b/src/components/shout_panel/shout_panel.js
new file mode 100644
index 00000000..a6168971
--- /dev/null
+++ b/src/components/shout_panel/shout_panel.js
@@ -0,0 +1,53 @@
+import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faBullhorn,
+ faTimes
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faBullhorn,
+ faTimes
+)
+
+const shoutPanel = {
+ props: [ 'floating' ],
+ data () {
+ return {
+ currentMessage: '',
+ channel: null,
+ collapsed: true
+ }
+ },
+ computed: {
+ messages () {
+ return this.$store.state.shout.messages
+ }
+ },
+ methods: {
+ submit (message) {
+ this.$store.state.shout.channel.push('new_msg', { text: message }, 10000)
+ this.currentMessage = ''
+ },
+ togglePanel () {
+ this.collapsed = !this.collapsed
+ },
+ userProfileLink (user) {
+ return generateProfileLink(user.id, user.username, this.$store.state.instance.restrictedNicknames)
+ }
+ },
+ watch: {
+ messages (newVal) {
+ const scrollEl = this.$el.querySelector('.chat-window')
+ if (!scrollEl) return
+ if (scrollEl.scrollTop + scrollEl.offsetHeight + 20 > scrollEl.scrollHeight) {
+ this.$nextTick(() => {
+ if (!scrollEl) return
+ scrollEl.scrollTop = scrollEl.scrollHeight - scrollEl.offsetHeight
+ })
+ }
+ }
+ }
+}
+
+export default shoutPanel
diff --git a/src/components/shout_panel/shout_panel.vue b/src/components/shout_panel/shout_panel.vue
new file mode 100644
index 00000000..f90baf80
--- /dev/null
+++ b/src/components/shout_panel/shout_panel.vue
@@ -0,0 +1,148 @@
+<template>
+ <div
+ v-if="!collapsed || !floating"
+ class="shout-panel"
+ >
+ <div class="panel panel-default">
+ <div
+ class="panel-heading timeline-heading"
+ :class="{ 'shout-heading': floating }"
+ @click.stop.prevent="togglePanel"
+ >
+ <div class="title">
+ {{ $t('shoutbox.title') }}
+ <FAIcon
+ v-if="floating"
+ icon="times"
+ class="close-icon"
+ />
+ </div>
+ </div>
+ <div class="shout-window">
+ <div
+ v-for="message in messages"
+ :key="message.id"
+ class="shout-message"
+ >
+ <span class="shout-avatar">
+ <img :src="message.author.avatar">
+ </span>
+ <div class="shout-content">
+ <router-link
+ class="shout-name"
+ :to="userProfileLink(message.author)"
+ >
+ {{ message.author.username }}
+ </router-link>
+ <br>
+ <span class="shout-text">
+ {{ message.text }}
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="shout-input">
+ <textarea
+ v-model="currentMessage"
+ class="shout-input-textarea"
+ rows="1"
+ @keyup.enter="submit(currentMessage)"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ v-else
+ class="shout-panel"
+ >
+ <div class="panel panel-default">
+ <div
+ class="panel-heading stub timeline-heading shout-heading"
+ @click.stop.prevent="togglePanel"
+ >
+ <div class="title">
+ <FAIcon
+ class="icon"
+ icon="bullhorn"
+ />
+ {{ $t('shoutbox.title') }}
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script src="./shout_panel.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.floating-shout {
+ position: fixed;
+ right: 0px;
+ bottom: 0px;
+ z-index: 1000;
+ max-width: 25em;
+}
+
+.shout-panel {
+ .shout-heading {
+ cursor: pointer;
+
+ .icon {
+ color: $fallback--text;
+ color: var(--text, $fallback--text);
+ margin-right: 0.5em;
+ }
+
+ .title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ }
+
+ .shout-window {
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-height: 20em;
+ }
+
+ .shout-window-container {
+ height: 100%;
+ }
+
+ .shout-message {
+ display: flex;
+ padding: 0.2em 0.5em
+ }
+
+ .shout-avatar {
+ img {
+ height: 24px;
+ width: 24px;
+ border-radius: $fallback--avatarRadius;
+ border-radius: var(--avatarRadius, $fallback--avatarRadius);
+ margin-right: 0.5em;
+ margin-top: 0.25em;
+ }
+ }
+
+ .shout-input {
+ display: flex;
+ textarea {
+ flex: 1;
+ margin: 0.6em;
+ min-height: 3.5em;
+ resize: none;
+ }
+ }
+
+ .shout-panel {
+ .title {
+ display: flex;
+ justify-content: space-between;
+ }
+ }
+}
+</style>