diff --git a/src/assets/logo.svg b/src/assets/logo.svg index 29a32fc..68d6a03 100644 --- a/src/assets/logo.svg +++ b/src/assets/logo.svg @@ -1,412 +1,41 @@ - + + viewBox="0 0 477 477" style="enable-background:new 0 0 477 477;" xml:space="preserve"> - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - diff --git a/src/components/app/MemberTemplate.vue b/src/components/app/MemberTemplate.vue index db4b17e..5b338fb 100644 --- a/src/components/app/MemberTemplate.vue +++ b/src/components/app/MemberTemplate.vue @@ -3,11 +3,12 @@ class="member" @click="openUserInformation()" @mouseover="hover = true" @mouseleave="hover = false" + @contextmenu.prevent="rightClickEvent" > @@ -47,7 +48,7 @@ export default { return this.$store.getters.user.status || 0 } const presences = this.$store.getters['members/presences']; - const userPresense = presences[this.user.uniqueID] + const userPresense = presences[this.user.uniqueID]; return userPresense || 0 } }, @@ -55,6 +56,11 @@ export default { openUserInformation() { this.$store.dispatch('setUserInformationPopout', this.user.uniqueID) }, + rightClickEvent(event) { + const x = event.clientX; + const y = event.clientY; + this.$store.dispatch('setServerMemberContext', {serverID: this.$store.getters['servers/selectedServerID'], uniqueID: this.user.uniqueID, x, y}); + } } } @@ -65,12 +71,10 @@ export default { .member { display: flex; padding: 3px; - margin: 10px; - margin-top: 3px; - margin-bottom: 3px; + margin: 3px 5px; align-items: center; align-content: center; - border-radius: 10px; + border-radius: 5px; transition: 0.3s; cursor: pointer; user-select: none; diff --git a/src/components/app/MembersList.vue b/src/components/app/MembersList.vue index 3314463..79cc880 100644 --- a/src/components/app/MembersList.vue +++ b/src/components/app/MembersList.vue @@ -6,9 +6,19 @@
+
Online ({{onlineMembers.length}})
+ +
Offline ({{offlineMembers.length}})
+ sm.server_id === selectedServerID); let getMember = filteredSM.map(sm => { sm.member = members[sm.uniqueID]; + + // attach presense + if (sm.uniqueID === this.$store.getters.user.uniqueID) { + sm.presense = this.$store.getters.user.status || 0 + } else { + sm.presense = presences[sm.uniqueID] || 0 + } return sm; }) const sort = getMember.sort((a, b) => { @@ -46,6 +64,12 @@ export default { }) return sort; + }, + onlineMembers() { + return this.members.filter(sm => sm.presense >= 1) + }, + offlineMembers() { + return this.members.filter(sm => sm.presense == 0) } } } @@ -78,5 +102,15 @@ export default { padding-top: 10px; overflow: auto; } +.tab { + background: rgba(0, 0, 0, 0.308); + padding: 5px; + border-radius: 5px; + margin: 5px; + user-select: none; + cursor: default; + color: rgb(200, 200, 200); + font-size: 15px; +} diff --git a/src/components/app/MessageTemplate.vue b/src/components/app/MessageTemplate.vue index fe98b28..7d5bb3f 100644 --- a/src/components/app/MessageTemplate.vue +++ b/src/components/app/MessageTemplate.vue @@ -66,8 +66,9 @@
has left the server. + has been kicked. + has been banned. {{ getDate }}
@@ -127,8 +136,8 @@ export default { }, methods: { openContextMenu(event) { - const element = event.target; - const {x, y} = element.getBoundingClientRect() + const x = event.clientX; + const y = event.clientY; this.$store.dispatch('setMessageContext', { x, y, @@ -277,16 +286,28 @@ export default { color: white; overflow: hidden; border-radius: 5px; + background: rgba(0, 0, 0, 0.356); } .presence-message .text { margin-left: 5px; + font-size: 15px; } -.presence-message.green { - background: rgba(0, 128, 0, 0.534); +.presence-message .username { + font-size: 15px; + font-weight: bold } -.presence-message.red { - background: rgba(128, 0, 0, 0.534); +.presence-message.join { + color: #29BF12; +} +.presence-message.leave { + color: rgb(150, 139, 139); +} +.presence-message.kick { + color: #FF9914; +} +.presence-message.ban { + color: #d92121; } .ownMessageLeft { @@ -294,7 +315,7 @@ export default { } .ownMessageLeft .triangle-inner { - border-left: 7px solid rgba(184, 184, 184, 0.219); + border-left: 8px solid rgba(184, 184, 184, 0.219); border-right: none !important; } .ownMessageLeft .avatar { @@ -312,7 +333,7 @@ export default { } .ownMessage .triangle-inner { - border-right: 7px solid rgba(184, 184, 184, 0.219); + border-right: 8px solid rgba(184, 184, 184, 0.219); } .ownMessage .content { background: rgba(184, 184, 184, 0.219); @@ -366,15 +387,15 @@ export default { display: flex; justify-content: bottom; flex-direction: column; - margin: auto 0 8.7px 0; + margin: auto 0 0 0; } -.triangle-inner { - width: 0; - height: 0; - border-top: 1px solid transparent; - border-bottom: 7px solid transparent; - border-right: 7px solid rgba(0, 0, 0, 0.301); +.triangle-inner { + width: 0; + height: 0; + border-top: 9px solid transparent; + border-bottom: 0px solid transparent; + border-right: 8px solid rgba(0, 0, 0, 0.301); } .content { @@ -384,10 +405,15 @@ export default { justify-content: center; flex-direction: column; border-radius: 10px; + border-bottom-left-radius: 0; color: rgb(231, 231, 231); margin: auto 0; overflow: hidden; } +.ownMessageLeft .content { + border-bottom-left-radius: 10px; + border-bottom-right-radius: 0; +} .image-content { margin-top: 10px; padding: 5px; @@ -414,16 +440,17 @@ export default { font-size: 14px; margin: auto 0; transition: 0.1s; - cursor: default; + cursor: pointer; } .username:hover { color: rgb(199, 199, 199); text-decoration: underline; } .date { - color: rgb(161, 161, 161); + color: rgb(177, 177, 177); font-size: 10px; margin: auto auto auto 5px; + font-weight: normal; } .content-message { word-wrap: break-word; diff --git a/src/components/app/Popouts/Popouts.vue b/src/components/app/Popouts/Popouts.vue index edf64e6..ed5b537 100644 --- a/src/components/app/Popouts/Popouts.vue +++ b/src/components/app/Popouts/Popouts.vue @@ -13,6 +13,7 @@ + @@ -21,7 +22,12 @@ //popouts const userInformationPopout = () => import('./Popouts/userInformationPopout.vue'); + + // context menus const messageContextMenu = () => import('./Popouts/messageContextMenu'); + const ServerMemberContext = () => import('./Popouts/ServerMemberContext'); + + const AddServer = () => import('./Popouts/AddServer.vue'); const Settings = () => import('./Popouts/Settings.vue'); const TakeSurveyPopout = () => import('./Popouts/TakeSurveyPopout.vue'); @@ -48,7 +54,8 @@ export default { ServerInvite: ServerInvitePopout, ServerSettings, GenericPopout, - messageContextMenu + messageContextMenu, + ServerMemberContext }, data() { return { diff --git a/src/components/app/Popouts/Popouts/ServerMemberContext.vue b/src/components/app/Popouts/Popouts/ServerMemberContext.vue new file mode 100644 index 0000000..d9ed8c1 --- /dev/null +++ b/src/components/app/Popouts/Popouts/ServerMemberContext.vue @@ -0,0 +1,132 @@ + + + + + + + diff --git a/src/components/app/Popouts/Popouts/ServerSettingsPanels/ManageBans.vue b/src/components/app/Popouts/Popouts/ServerSettingsPanels/ManageBans.vue new file mode 100644 index 0000000..032443a --- /dev/null +++ b/src/components/app/Popouts/Popouts/ServerSettingsPanels/ManageBans.vue @@ -0,0 +1,135 @@ + + + + + + + + diff --git a/src/components/app/Popouts/Popouts/ServerSettingsPanels/ServerSettings.vue b/src/components/app/Popouts/Popouts/ServerSettingsPanels/ServerSettings.vue index b7db7ce..d5f6fb9 100644 --- a/src/components/app/Popouts/Popouts/ServerSettingsPanels/ServerSettings.vue +++ b/src/components/app/Popouts/Popouts/ServerSettingsPanels/ServerSettings.vue @@ -13,8 +13,9 @@ - - + + + @@ -30,9 +31,10 @@ import { mapState } from "vuex"; import General from './General.vue' import DeleteServer from './DeleteServer.vue' import ManageChannels from './ManageChannels.vue' +import ManageBans from './ManageBans.vue' import ServerVisibility from './ServerVisibility.vue' export default { - components: { General, DeleteServer, ManageChannels, ServerVisibility}, + components: { General, DeleteServer, ManageChannels, ServerVisibility, ManageBans}, data() { return { index: 0, @@ -40,6 +42,7 @@ export default { {title: "General", icon: "info"}, {title: "Manage Channels", icon: "storage"}, // {title: "Manage Invites", icon: "local_post_office"}, + {title: "Banned Members", icon: "lock"}, {title: "Server Visibility", icon: "visibility"}, {title: "Delete Server", icon: "warning", critical: true}, ] @@ -98,6 +101,7 @@ export default { height: 100%; display: flex; flex-direction: column; + overflow: hidden; } .tabs { display: flex; diff --git a/src/components/app/Popouts/Popouts/messageContextMenu.vue b/src/components/app/Popouts/Popouts/messageContextMenu.vue index fe562aa..4321e83 100644 --- a/src/components/app/Popouts/Popouts/messageContextMenu.vue +++ b/src/components/app/Popouts/Popouts/messageContextMenu.vue @@ -115,20 +115,16 @@ export default { } .item { - padding: 3px; + padding: 5px; margin: 2px; border-radius: 5px; transition: 0.3s; font-size: 13px; cursor: pointer; &:hover { - background: rgb(56, 56, 56); + background: rgb(46, 46, 46); } &.warn { - &:hover { - background: rgba(255, 90, 90, 0.338); - } - background: rgba(255, 90, 90, 0.1); color: rgb(255, 59, 59); } } diff --git a/src/components/app/Popouts/Popouts/userInformationPopout.vue b/src/components/app/Popouts/Popouts/userInformationPopout.vue index cc0c971..f021e4c 100644 --- a/src/components/app/Popouts/Popouts/userInformationPopout.vue +++ b/src/components/app/Popouts/Popouts/userInformationPopout.vue @@ -179,7 +179,7 @@ export default { left: 0; right: 0; bottom: 0; - z-index: 999; + z-index: 9999999; display: flex; justify-content: center; align-items: center; diff --git a/src/components/app/relationships/OnlineFriends.vue b/src/components/app/relationships/OnlineFriends.vue index f9617eb..a63b983 100644 --- a/src/components/app/relationships/OnlineFriends.vue +++ b/src/components/app/relationships/OnlineFriends.vue @@ -49,11 +49,11 @@ export default { const result = Object.keys(allFriend).map(function(key) { const friend = allFriend[key]; friend.recipient = members[friend.uniqueID]; - const findNotification = notifications.find( e => { + const findNotification = notifications.find( e => { return e.sender.uniqueID === friend.recipient.uniqueID && !channels[e.channelID].server_id - }) + if ( findNotification ){ friend.channelID = findNotification.channelID; } diff --git a/src/services/ServerService.js b/src/services/ServerService.js index 907c4b6..f8cc296 100644 --- a/src/services/ServerService.js +++ b/src/services/ServerService.js @@ -4,21 +4,10 @@ export default { post ( data ) { return wrapper(instance().post('/servers', data)); }, - updateServer (serverID, data) { - return wrapper(instance().patch(`/servers/${serverID}`, data)); - }, getChannels(serverID) { return wrapper(instance().get(`/servers/${serverID}/channels`)); }, - createChannel(serverID, name) { - return wrapper(instance().put(`/servers/${serverID}/channels`, {name})); - }, - updateChannel (serverID, channelID, data) { - return wrapper(instance().patch(`/servers/${serverID}/channels/${channelID}`, data)); - }, - deleteChannel (serverID, channelID) { - return wrapper(instance().delete(`/servers/${serverID}/channels/${channelID}`)); - }, + postInvite (serverID) { return wrapper (instance().post(`/servers/${serverID}/invite`)) }, @@ -38,4 +27,30 @@ export default { return wrapper (instance().delete(`/servers/${serverID}`)) }, + // Admin commands + updateServer (serverID, data) { + return wrapper(instance().patch(`/servers/${serverID}`, data)); + }, + createChannel(serverID, name) { + return wrapper(instance().put(`/servers/${serverID}/channels`, {name})); + }, + + updateChannel (serverID, channelID, data) { + return wrapper(instance().patch(`/servers/${serverID}/channels/${channelID}`, data)); + }, + deleteChannel (serverID, channelID) { + return wrapper(instance().delete(`/servers/${serverID}/channels/${channelID}`)); + }, + kickMember (serverID, uniqueID) { + return wrapper(instance().delete(`/servers/${serverID}/members/${uniqueID}`)); + }, + banMember (serverID, uniqueID) { + return wrapper(instance().put(`/servers/${serverID}/bans/${uniqueID}`)); + }, + unBanMember (serverID, uniqueID) { + return wrapper(instance().delete(`/servers/${serverID}/bans/${uniqueID}`)); + }, + memberBans (serverID,) { + return wrapper(instance().get(`/servers/${serverID}/bans`)); + }, } \ No newline at end of file diff --git a/src/store/modules/messageModule.js b/src/store/modules/messageModule.js index 832c3bf..81fc4cb 100644 --- a/src/store/modules/messageModule.js +++ b/src/store/modules/messageModule.js @@ -114,6 +114,14 @@ const actions = { } }) }, + deleteAllMessages(context, channelIDArr) { + const messages = Object.assign({}, context.state.messages); + for (let index = 0; index < channelIDArr.length; index++) { + const channelID = channelIDArr[index]; + delete messages[channelID] + } + context.commit('setAllMessages', messages) + }, updateMessage(context, {channelID, messageID, message}) { const messages = context.state.messages[channelID]; messages.find((obj, index) => { @@ -164,6 +172,9 @@ async function getMessages(context, channelID, isServerChannel) { const mutations = { + setAllMessages(state, messages) { + state.messages = messages; + }, setBottomUnloadStatus(state, {channelID, status}) { Vue.set(state.bottomUnloaded, channelID, status) }, diff --git a/src/store/modules/popoutsModule/popoutsModule.js b/src/store/modules/popoutsModule/popoutsModule.js index c12ce8d..497e656 100644 --- a/src/store/modules/popoutsModule/popoutsModule.js +++ b/src/store/modules/popoutsModule/popoutsModule.js @@ -36,6 +36,12 @@ const state = { uniqueID: null, x: null, y: null + }, + serverMemberContext: { + serverID: null, + uniqueID: null, + x: null, + y: null } @@ -74,10 +80,16 @@ const actions = { }, setMessageContext(context, {messageID, x, y, channelID, message, uniqueID}) { context.commit('setMessageContext', {messageID, x, y, channelID, message, uniqueID}); + }, + setServerMemberContext(context, {uniqueID, x, y, serverID}) { + context.commit('setServerMemberContext', {uniqueID, x, y, serverID}); } } const mutations = { + setServerMemberContext(state, data) { + Vue.set(state, 'serverMemberContext', data); + }, setMessageContext(state, data) { Vue.set(state, 'messageContextMenu', data); }, diff --git a/src/store/modules/socketIOModule.js b/src/store/modules/socketIOModule.js index af156e7..e8991a6 100644 --- a/src/store/modules/socketIOModule.js +++ b/src/store/modules/socketIOModule.js @@ -3,6 +3,7 @@ import {bus} from '../../main' import {router} from './../../router' import Vue from 'vue'; import DesktopNotification from '@/utils/ElectronJS/DesktopNotification' +import isElectron from '@/utils/ElectronJS/DesktopNotification' const state = { @@ -175,6 +176,8 @@ const actions = { // send desktop notification const disableDesktopNotification = context.rootGetters['settingsModule/settings'].notification.disableDesktopNotification; if (disableDesktopNotification === true) return + + if (!isElectron || disableDesktopNotification === undefined) return; const channel = context.getters.channels[data.message.channelID]; if (channel && channel.server_id) { const server = context.getters['servers/servers'][channel.server_id] @@ -267,10 +270,23 @@ const actions = { }, ['socket_server:leave'](context, {server_id}) { + // check if server channel selected + const serverChannelIDs = context.rootState.servers.channelsIDs[server_id]; + + const selectedChannelID = context.rootState.channelModule.selectedChannelID; + const serverChannelID = context.rootState.channelModule.serverChannelID; + + if (serverChannelIDs.includes(selectedChannelID)) { + context.dispatch('selectedChannelID', null) + } + if (serverChannelIDs.includes(serverChannelID)) { + context.dispatch('setServerChannelID', null) + } context.dispatch('servers/removePresences', server_id); context.dispatch('servers/removeServer', server_id) context.dispatch('servers/removeNotifications', server_id) context.dispatch('servers/removeAllServerChannels', server_id) + context.dispatch('deleteAllMessages', serverChannelIDs) }, ['socket_server:memberAdd'](context, {serverMember, presence}) { // member_add let sm = Object.assign({}, serverMember); diff --git a/src/utils/changelog.js b/src/utils/changelog.js index 3ab590d..7a692e2 100644 --- a/src/utils/changelog.js +++ b/src/utils/changelog.js @@ -14,12 +14,36 @@ const config = [ + { + version: 7.3, + title: "Kick and ban!", + shortTitle: "", + date: "29/09/2019", + headColor: "rgba(25, 130, 255, 0.77)", + new: [ + 'You can now kick/back members of a server by right clicking on their names in the server members list.', + 'Slightly changed message bubble design.' + ], + fix: [ + "Fixed a bug where Join and Leave messages would not get notified when reloading client.", + ], + }, + { + version: 7.2, + title: "Online, offline category in server member list", + shortTitle: "", + date: "21/09/2019", + new: [ + "Online and offline is now a category in the server members list.", + "Moved add server to the top of the servers list with new design.", + "Added Explore button to the top of the servers list." + ], + }, { version: 7.1, title: "Small improvements, bug fixes", shortTitle: "", date: "19/09/2019", - headColor: "rgba(25, 130, 255, 0.77)", new: [ "When joining a server, the tabs should change to servers and default channel should open up.", "Swapped the changelog and the explore tab." diff --git a/src/utils/clickOutside.js b/src/utils/clickOutside.js index 50a7dd1..a6c150c 100644 --- a/src/utils/clickOutside.js +++ b/src/utils/clickOutside.js @@ -3,6 +3,7 @@ import Vue from 'vue' // to close popout menus when clicking outside. Vue.directive('click-outside', { bind: function (el, binding, vnode) { + el.clickOutsideEvent = function (event) { // here I check that click was outside the el and his childrens if (!(el == event.target || el.contains(event.target))) { diff --git a/src/views/App.vue b/src/views/App.vue index eea47de..0cb1ace 100644 --- a/src/views/App.vue +++ b/src/views/App.vue @@ -160,9 +160,9 @@ export default { } // check if changelog is updated const seenVersion = localStorage.getItem("changelog-version-seen"); - if (!seenVersion || seenVersion < changelog[0].version) { - this.currentTab = 0; - localStorage.setItem("currentTab", 0); + if (seenVersion && seenVersion < changelog[0].version) { + localStorage.setItem("currentTab", 3); + this.currentTab = 3; } localStorage.setItem("changelog-version-seen", changelog[0].version); bus.$on("title:change", title => {