logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe
commit: 63d29eab3f0e399e8a3b1bbfa35f1717715ffc63
parent: bf7b5a7105e6543411d83ba126dab6b00955c98c
Author: eal <eal@waifu.club>
Date:   Thu,  7 Dec 2017 17:08:20 +0000

Merge branch 'feature/chat' into 'develop'

Feature/chat

See merge request pleroma/pleroma-fe!182

Diffstat:

Mconfig/index.js8+++++++-
Mpackage.json1+
Asrc/components/chat/chat.js21+++++++++++++++++++++
Asrc/components/chat/chat.vue59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/components/nav_panel/nav_panel.js3+++
Msrc/components/nav_panel/nav_panel.vue5+++++
Msrc/i18n/messages.js4++++
Msrc/main.js14+++++++++++---
Msrc/modules/api.js22+++++++++++++++++++++-
Asrc/modules/chat.js33+++++++++++++++++++++++++++++++++
Msrc/modules/users.js4++++
Mstatic/config.json3++-
Myarn.lock4++++
13 files changed, 175 insertions(+), 6 deletions(-)

diff --git a/config/index.js b/config/index.js @@ -23,9 +23,15 @@ module.exports = { assetsPublicPath: '/', proxyTable: { '/api': { - target: 'https://social.heldscal.la/', + target: 'htts://localhost:4000/', changeOrigin: true, cookieDomainRewrite: 'localhost' + }, + '/socket': { + target: 'htts://localhost:4000/', + changeOrigin: true, + cookieDomainRewrite: 'localhost', + ws: true } }, // CSS Sourcemaps off by default because relative paths are "buggy" diff --git a/package.json b/package.json @@ -21,6 +21,7 @@ "localforage": "^1.5.0", "node-sass": "^3.10.1", "object-path": "^0.11.3", + "phoenix": "^1.3.0", "sanitize-html": "^1.13.0", "sass-loader": "^4.0.2", "vue": "^2.3.4", diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js @@ -0,0 +1,21 @@ +const chat = { + data () { + return { + currentMessage: '', + channel: null + } + }, + computed: { + messages () { + return this.$store.state.chat.messages + } + }, + methods: { + submit (message) { + this.$store.state.chat.channel.push('new_msg', {text: message}, 10000) + this.currentMessage = '' + } + } +} + +export default chat diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue @@ -0,0 +1,59 @@ +<template> + <div class="chat-panel panel panel-default"> + <div class="panel-heading timeline-heading base02-background base04"> + <div class="title"> + {{$t('chat.title')}} + </div> + </div> + <div class="panel-body base01-background"> + <div class="chat-window"> + <div class="chat-message" v-for="message in messages" :key="message.id"> + <span class="chat-avatar"> + <img :src="message.author.avatar" /> + {{message.author.username}}: + </span> + <span class="chat-text"> + {{message.text}} + </span> + </div> + </div> + <div class="chat-input"> + <form @submit.prevent="submit(currentMessage)"> + <input v-model="currentMessage" type="text" > + </form> + </div> + </div> + </div> +</template> + +<script src="./chat.js"></script> + + +<style lang="scss"> + .chat-window { + max-height: 80vh; + overflow-y: auto; + overflow-x: hidden; + } + .chat-message { + padding: 0.2em 0.5em + } + .chat-avatar { + img { + height: 32px; + width: 32px; + border-radius: 5px; + margin-right: 0.5em; + } + } + .chat-input { + display: flex; + form { + flex: auto; + input { + margin: 0.5em; + width: fill-available; + } + } + } +</style> diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js @@ -2,6 +2,9 @@ const NavPanel = { computed: { currentUser () { return this.$store.state.users.currentUser + }, + chat () { + return this.$store.state.chat.channel } } } diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue @@ -7,6 +7,11 @@ {{ $t("nav.timeline") }} </router-link> </li> + <li v-if='chat && currentUser'> + <router-link class="base00-background" to='/chat'> + {{ $t("nav.chat") }} + </router-link> + </li> <li v-if='currentUser'> <router-link class="base00-background" :to="{ name: 'mentions', params: { username: currentUser.screen_name } }"> {{ $t("nav.mentions") }} diff --git a/src/i18n/messages.js b/src/i18n/messages.js @@ -179,7 +179,11 @@ const fi = { } const en = { + chat: { + title: 'Chat' + }, nav: { + chat: 'Local Chat', timeline: 'Timeline', mentions: 'Mentions', public_tl: 'Public Timeline', diff --git a/src/main.js b/src/main.js @@ -12,11 +12,13 @@ import UserProfile from './components/user_profile/user_profile.vue' import Settings from './components/settings/settings.vue' import Registration from './components/registration/registration.vue' import UserSettings from './components/user_settings/user_settings.vue' +import Chat from './components/chat/chat.vue' import statusesModule from './modules/statuses.js' import usersModule from './modules/users.js' import apiModule from './modules/api.js' import configModule from './modules/config.js' +import chatModule from './modules/chat.js' import VueTimeago from 'vue-timeago' import VueI18n from 'vue-i18n' @@ -57,10 +59,12 @@ const store = new Vuex.Store({ statuses: statusesModule, users: usersModule, api: apiModule, - config: configModule + config: configModule, + chat: chatModule }, plugins: [createPersistedState(persistedStateOptions)], - strict: process.env.NODE_ENV !== 'production' + strict: false // Socket modifies itself, let's ignore this for now. + // strict: process.env.NODE_ENV !== 'production' }) const i18n = new VueI18n({ @@ -78,6 +82,9 @@ window.fetch('/static/config.json') store.dispatch('setOption', { name: 'background', value: background }) store.dispatch('setOption', { name: 'logo', value: logo }) store.dispatch('setOption', { name: 'registrationOpen', value: registrationOpen }) + if (data['chatDisabled']) { + store.dispatch('disableChat') + } const routes = [ { name: 'root', path: '/', redirect: data['defaultPath'] || '/main/all' }, @@ -90,7 +97,8 @@ window.fetch('/static/config.json') { name: 'mentions', path: '/:username/mentions', component: Mentions }, { name: 'settings', path: '/settings', component: Settings }, { name: 'registration', path: '/registration', component: Registration }, - { name: 'user-settings', path: '/user-settings', component: UserSettings } + { name: 'user-settings', path: '/user-settings', component: UserSettings }, + { name: 'chat', path: '/chat', component: Chat } ] const router = new VueRouter({ diff --git a/src/modules/api.js b/src/modules/api.js @@ -1,10 +1,13 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' import {isArray} from 'lodash' +import { Socket } from 'phoenix' const api = { state: { backendInteractor: backendInteractorService(), - fetchers: {} + fetchers: {}, + socket: null, + chatDisabled: false }, mutations: { setBackendInteractor (state, backendInteractor) { @@ -15,6 +18,12 @@ const api = { }, removeFetcher (state, {timeline}) { delete state.fetchers[timeline] + }, + setSocket (state, socket) { + state.socket = socket + }, + setChatDisabled (state, value) { + state.chatDisabled = value } }, actions: { @@ -37,6 +46,17 @@ const api = { const fetcher = store.state.fetchers[timeline] window.clearInterval(fetcher) store.commit('removeFetcher', {timeline}) + }, + initializeSocket (store, token) { + // Set up websocket connection + if (!store.state.chatDisabled) { + let socket = new Socket('/socket', {params: {token: token}}) + socket.connect() + store.dispatch('initializeChat', socket) + } + }, + disableChat (store) { + store.commit('setChatDisabled', true) } } } diff --git a/src/modules/chat.js b/src/modules/chat.js @@ -0,0 +1,33 @@ +const chat = { + state: { + messages: [], + channel: null + }, + mutations: { + setChannel (state, channel) { + state.channel = channel + }, + addMessage (state, message) { + state.messages.push(message) + state.messages = state.messages.slice(-19, 20) + }, + setMessages (state, messages) { + state.messages = messages.slice(-19, 20) + } + }, + actions: { + initializeChat (store, socket) { + const channel = socket.channel('chat:public') + channel.on('new_msg', (msg) => { + store.commit('addMessage', msg) + }) + channel.on('messages', ({messages}) => { + store.commit('setMessages', messages) + }) + channel.join() + store.commit('setChannel', channel) + } + } +} + +export default chat diff --git a/src/modules/users.js b/src/modules/users.js @@ -97,6 +97,10 @@ const users = { // Set our new backend interactor commit('setBackendInteractor', backendInteractorService(userCredentials)) + if (user.token) { + store.dispatch('initializeSocket', user.token) + } + // Start getting fresh tweets. store.dispatch('startFetching', 'friends') diff --git a/static/config.json b/static/config.json @@ -4,5 +4,6 @@ "background": "/static/bg.jpg", "logo": "/static/logo.png", "registrationOpen": false, - "defaultPath": "/main/all" + "defaultPath": "/main/all", + "chatDisabled": false } diff --git a/yarn.lock b/yarn.lock @@ -4226,6 +4226,10 @@ phantomjs-prebuilt@^2.1.3, phantomjs-prebuilt@^2.1.7: request-progress "~2.0.1" which "~1.2.10" +phoenix@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/phoenix/-/phoenix-1.3.0.tgz#1df2c27f986ee295e37c9983ec28ebac1d7f4a3e" + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"