mirror of
https://github.com/danbulant/Nertivia-Client
synced 2026-06-24 09:01:43 +00:00
New design, a lot of changes.
This commit is contained in:
parent
41db687eaa
commit
154d6147a9
51 changed files with 1599 additions and 1731 deletions
5
package-lock.json
generated
5
package-lock.json
generated
|
|
@ -10296,6 +10296,11 @@
|
||||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"simple-markdown": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-markdown/-/simple-markdown-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-02HKXvM9J7pJWf74fuWthcgof5jF81Yndt+XcXtWnEtpp8QaX9dUAJpdAA6KWrB/rSGzrOi0PRAVy9/0bJiIZw=="
|
||||||
|
},
|
||||||
"simple-swizzle": {
|
"simple-swizzle": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"markdown-it-chat-formatter": "^0.1.1",
|
"markdown-it-chat-formatter": "^0.1.1",
|
||||||
"match-sorter": "^2.3.0",
|
"match-sorter": "^2.3.0",
|
||||||
"particles.js": "^2.0.0",
|
"particles.js": "^2.0.0",
|
||||||
|
"simple-markdown": "^0.6.1",
|
||||||
"socket.io": "^2.2.0",
|
"socket.io": "^2.2.0",
|
||||||
"socket.io-client": "^2.2.0",
|
"socket.io-client": "^2.2.0",
|
||||||
"twemoji": "^11.3.0",
|
"twemoji": "^11.3.0",
|
||||||
|
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="change-log">
|
|
||||||
<div class="inner">
|
|
||||||
<div
|
|
||||||
class="close-button"
|
|
||||||
@click="close"
|
|
||||||
>
|
|
||||||
<i class="material-icons">
|
|
||||||
close
|
|
||||||
</i>
|
|
||||||
</div>
|
|
||||||
<div class="change-title">
|
|
||||||
Change Log <div class="changelog-icon">
|
|
||||||
<i class="material-icons ">update</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="change-list">
|
|
||||||
<div
|
|
||||||
v-for="(change, index) in changelog"
|
|
||||||
:key="index"
|
|
||||||
class="change"
|
|
||||||
>
|
|
||||||
<div class="date">
|
|
||||||
{{ change.date }}
|
|
||||||
</div>
|
|
||||||
<div class="changes-title">
|
|
||||||
{{ change.title }}
|
|
||||||
</div>
|
|
||||||
<div class="information">
|
|
||||||
<div v-if="change.new">
|
|
||||||
<strong>What's new?</strong><br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wnew, index) in change.new"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
{{ wnew }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="change.fix">
|
|
||||||
<strong>Issues fixed</strong><br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wfix, index) in change.fix"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
{{ wfix }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="change.next">
|
|
||||||
<strong>Up next</strong><br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wnext, index) in change.next"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
{{ wnext }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="change.msg">
|
|
||||||
{{ change.msg }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {bus} from './../main.js'
|
|
||||||
import changelog from '@/utils/changelog.js'
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
changelog
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
close() {
|
|
||||||
bus.$emit('closeChangeLog')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.change-log{
|
|
||||||
position: absolute;
|
|
||||||
background: rgba(0, 0, 0, 0.342);
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
display: flex;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.inner{
|
|
||||||
background-color: rgba(0, 0, 0, 0.664);
|
|
||||||
margin: auto;
|
|
||||||
width: 600px;
|
|
||||||
height: 700px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button{
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-right: 10px;
|
|
||||||
user-select: none;
|
|
||||||
cursor: default;
|
|
||||||
color: grey;
|
|
||||||
transition: .3s;
|
|
||||||
}
|
|
||||||
.close-button:hover{
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button .material-icons {
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-title{
|
|
||||||
color: white;
|
|
||||||
font-size: 30px;
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 10px;
|
|
||||||
user-select: none;
|
|
||||||
display: flex;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
.changelog-icon{
|
|
||||||
margin-top: 2px;
|
|
||||||
margin-left: 10px
|
|
||||||
}
|
|
||||||
.changelog-icon .material-icons {
|
|
||||||
font-size: 40px;
|
|
||||||
}
|
|
||||||
.change-list {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
border-top: 1px solid white;
|
|
||||||
}
|
|
||||||
.change{
|
|
||||||
margin: 5px;
|
|
||||||
min-height: 100px;
|
|
||||||
border-bottom: solid 1px white;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
}
|
|
||||||
.change:last-child{
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.date{
|
|
||||||
text-align: right;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-right: 10px;
|
|
||||||
color: grey;
|
|
||||||
}
|
|
||||||
.changes-title {
|
|
||||||
font-size: 25px;
|
|
||||||
padding-left: 15px;
|
|
||||||
color: rgba(255, 255, 255, 0.795);
|
|
||||||
}
|
|
||||||
.information {
|
|
||||||
margin: 10px;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-height: 700px) {
|
|
||||||
.inner {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ export default {
|
||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 9999999999999999;
|
z-index: 9999999999999999;
|
||||||
height: 39px;
|
height: 25px;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
@ -66,8 +66,7 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 60px;
|
width: 30px;
|
||||||
border-radius: 2px;
|
|
||||||
color: white;
|
color: white;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -82,9 +81,9 @@ export default {
|
||||||
background: rgba(255, 0, 0, 0.595);
|
background: rgba(255, 0, 0, 0.595);
|
||||||
}
|
}
|
||||||
.frame-buttons .minimize:hover {
|
.frame-buttons .minimize:hover {
|
||||||
background: rgba(255, 81, 0, 0.595);
|
background: rgba(46, 46, 46, 0.595);
|
||||||
}
|
}
|
||||||
.frame-buttons .res-max:hover {
|
.frame-buttons .res-max:hover {
|
||||||
background: rgba(0, 162, 255, 0.595);
|
background: rgba(46, 46, 46, 0.595);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,88 +1,78 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="left-panel">
|
<div class="left-panel">
|
||||||
<MyMiniInformation />
|
<navigation />
|
||||||
<div class="tabs">
|
<div class="content">
|
||||||
<div :class="{selector: true, right: currentTab === 1}" />
|
<div class="tabs">
|
||||||
<div
|
<div :class="{selector: true, right: currentTab === 1}" />
|
||||||
class="tab"
|
<div
|
||||||
:class="{notifyAnimation: friendRequestExists}"
|
class="tab"
|
||||||
@click="currentTab = 0"
|
:class="{notifyAnimation: friendRequestExists}"
|
||||||
>
|
@click="currentTab = 0"
|
||||||
Friends
|
>Friends</div>
|
||||||
|
<div class="tab" :class="{notifyAnimation: DMNotification}" @click="currentTab = 1">Recents</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="currentTab === 0" class="list">
|
||||||
class="tab"
|
<pending-friends />
|
||||||
:class="{notifyAnimation: DMNotification}"
|
<online-friends />
|
||||||
@click="currentTab = 1"
|
<offline-friends />
|
||||||
>
|
|
||||||
Recents
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="list">
|
||||||
|
<recent-friends />
|
||||||
|
</div>
|
||||||
|
<MyMiniInformation />
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-if="currentTab === 0"
|
|
||||||
class="list"
|
|
||||||
>
|
|
||||||
<pending-friends />
|
|
||||||
<online-friends />
|
|
||||||
<offline-friends />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="list"
|
|
||||||
>
|
|
||||||
<recent-friends />
|
|
||||||
</div>
|
|
||||||
<AddFriendPanel />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import MyMiniInformation from "../../components/app/MyMiniInformation.vue";
|
||||||
import MyMiniInformation from '../../components/app/MyMiniInformation.vue'
|
import PendingFriends from "./relationships/PendingFriends.vue";
|
||||||
import PendingFriends from './relationships/PendingFriends.vue'
|
import OnlineFriends from "./relationships/OnlineFriends.vue";
|
||||||
import AddFriendPanel from './relationships/AddFriendPanel.vue'
|
import OfflineFriends from "./relationships/OfflineFriends.vue";
|
||||||
import OnlineFriends from './relationships/OnlineFriends.vue'
|
import RecentFriends from "./relationships/RecentFriends.vue";
|
||||||
import OfflineFriends from './relationships/OfflineFriends.vue'
|
import Navigation from "@/components/app/Navigation";
|
||||||
import RecentFriends from './relationships/RecentFriends.vue'
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MyMiniInformation,
|
MyMiniInformation,
|
||||||
PendingFriends,
|
PendingFriends,
|
||||||
AddFriendPanel,
|
|
||||||
OnlineFriends,
|
OnlineFriends,
|
||||||
OfflineFriends,
|
OfflineFriends,
|
||||||
RecentFriends
|
RecentFriends,
|
||||||
|
Navigation
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentTab: 0
|
currentTab: 0
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentTab(tab) {
|
currentTab(tab) {
|
||||||
localStorage.setItem('friendsListTab', tab)
|
localStorage.setItem("friendsListTab", tab);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const tab = localStorage.getItem('friendsListTab');
|
const tab = localStorage.getItem("friendsListTab");
|
||||||
if (tab) {
|
if (tab) {
|
||||||
this.currentTab = parseInt(tab)
|
this.currentTab = parseInt(tab);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
DMNotification() {
|
DMNotification() {
|
||||||
const notifications = this.$store.getters.notifications;
|
const notifications = this.$store.getters.notifications;
|
||||||
const channels = this.$store.getters.channels
|
const channels = this.$store.getters.channels;
|
||||||
const notification = notifications.find(e => {
|
const notification = notifications.find(e => {
|
||||||
return channels[e.channelID] && !channels[e.channelID].server_id && e.channelID !== this.$store.getters.selectedChannelID
|
return (
|
||||||
})
|
channels[e.channelID] &&
|
||||||
|
!channels[e.channelID].server_id &&
|
||||||
|
e.channelID !== this.$store.getters.selectedChannelID
|
||||||
|
);
|
||||||
|
});
|
||||||
// unopened dm
|
// unopened dm
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
return notifications.find(e => {
|
return notifications.find(e => {
|
||||||
return !channels[e.channelID]
|
return !channels[e.channelID];
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
return notification;
|
return notification;
|
||||||
},
|
},
|
||||||
|
|
@ -93,106 +83,112 @@ export default {
|
||||||
});
|
});
|
||||||
return result.find(friend => friend.status === 1);
|
return result.find(friend => friend.status === 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.left-panel {
|
.left-panel {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.671);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
width: 300px;
|
width: 300px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.list{
|
.content {
|
||||||
margin: 2px;
|
display: flex;
|
||||||
margin-left: 5px;
|
flex-direction: column;
|
||||||
margin-right: 5px;
|
flex-shrink: 0;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs{
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
color: white;
|
color: white;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-top: 10px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.tab{
|
.tab {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
padding: 10px;
|
height: 50px;
|
||||||
background: rgba(0, 0, 0, 0.171);
|
background: rgba(0, 0, 0, 0.171);
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.tab:hover{
|
.tab:hover {
|
||||||
background: rgba(255, 255, 255, 0.096);
|
background: rgba(255, 255, 255, 0.096);
|
||||||
}
|
}
|
||||||
.selector {
|
.selector {
|
||||||
background: rgba(255, 255, 255, 0.322);
|
background: rgba(255, 255, 255, 0.322);
|
||||||
width: 148px;
|
width: 118px;
|
||||||
height: 39px;
|
height: 50px;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 1px;
|
left: 1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
.right{
|
.right {
|
||||||
transform: translateX(150px);
|
transform: translateX(120px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------- SCROLL BAR -------*/
|
/* ------- SCROLL BAR -------*/
|
||||||
/* width */
|
/* width */
|
||||||
.list::-webkit-scrollbar {
|
.list::-webkit-scrollbar {
|
||||||
width: 3px;
|
width: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Track */
|
/* Track */
|
||||||
.list::-webkit-scrollbar-track {
|
.list::-webkit-scrollbar-track {
|
||||||
background: #8080806b;
|
background: #8080806b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle */
|
/* Handle */
|
||||||
.list::-webkit-scrollbar-thumb {
|
.list::-webkit-scrollbar-thumb {
|
||||||
background: #f5f5f559;
|
background: #f5f5f559;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle on hover */
|
/* Handle on hover */
|
||||||
.list::-webkit-scrollbar-thumb:hover {
|
.list::-webkit-scrollbar-thumb:hover {
|
||||||
background: #f5f5f59e;
|
background: #f5f5f59e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notifyAnimation{
|
.notifyAnimation {
|
||||||
animation: notifyAnime;
|
animation: notifyAnime;
|
||||||
animation-duration: 1s;
|
animation-duration: 1s;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
@keyframes notifyAnime {
|
@keyframes notifyAnime {
|
||||||
0%{
|
0% {
|
||||||
background: rgba(121, 3, 3, 0.541);
|
background: rgba(121, 3, 3, 0.541);
|
||||||
}
|
}
|
||||||
40%{
|
40% {
|
||||||
background: rgba(255, 0, 0, 0.568);
|
background: rgba(255, 0, 0, 0.568);
|
||||||
}
|
}
|
||||||
60%{
|
60% {
|
||||||
background: rgba(255, 0, 0, 0.568);
|
background: rgba(255, 0, 0, 0.568);
|
||||||
}
|
}
|
||||||
100%{
|
100% {
|
||||||
background: rgba(121, 3, 3, 0.541);
|
background: rgba(121, 3, 3, 0.541);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,18 +71,18 @@ export default {
|
||||||
.member {
|
.member {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
margin: 3px 5px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member:hover {
|
.member:hover {
|
||||||
background: rgba(0, 0, 0, 0.301);
|
background: rgba(0, 0, 0, 0.301);
|
||||||
}
|
}
|
||||||
|
|
||||||
.information {
|
.information {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export default {
|
||||||
color: white;
|
color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: rgba(0, 0, 0, 0.671);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
@ -105,8 +105,6 @@ export default {
|
||||||
.tab {
|
.tab {
|
||||||
background: rgba(0, 0, 0, 0.308);
|
background: rgba(0, 0, 0, 0.308);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
color: rgb(200, 200, 200);
|
color: rgb(200, 200, 200);
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ export default {
|
||||||
.right-panel {
|
.right-panel {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.507);
|
background-color: rgba(0, 0, 0, 0.650);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="container" @mouseover="hover = true" @mouseleave="hover = false">
|
<div class="container" @mouseover="hover = true" @mouseleave="hover = false">
|
||||||
<div
|
<div
|
||||||
v-if="!type || type === 0"
|
v-if="!type || type === 0"
|
||||||
:class="{message: true, ownMessage: user.uniqueID === $props.uniqueID, halloween: user.uniqueID === $props.uniqueID, ownMessageLeft: user.uniqueID === $props.uniqueID && (apperance && apperance.own_message_right === true)} "
|
:class="{message: true, ownMessage: user.uniqueID === $props.uniqueID, ownMessageLeft: user.uniqueID === $props.uniqueID && (apperance && apperance.own_message_right === true)} "
|
||||||
>
|
>
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<profile-picture
|
<profile-picture
|
||||||
|
|
@ -18,80 +18,71 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="content" @dblclick="contentDoubleClickEvent">
|
<div class="content" @dblclick="contentDoubleClickEvent">
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="username halloween-color"
|
<div
|
||||||
|
class="username"
|
||||||
@click="openUserInformation"
|
@click="openUserInformation"
|
||||||
>
|
>{{ this.$props.username }}</div>
|
||||||
{{ this.$props.username }}
|
<div class="date">{{ getDate }}</div>
|
||||||
</div>
|
|
||||||
<div class="date">
|
|
||||||
{{ getDate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-message"
|
<div class="content-message" v-html="formatMessage" />
|
||||||
v-html="formatMessage"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="file-content"
|
<div class="file-content" v-if="getFile">
|
||||||
v-if="getFile"
|
|
||||||
>
|
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="material-icons">insert_drive_file</i>
|
<i class="material-icons">insert_drive_file</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="information">
|
<div class="information">
|
||||||
<div class="info"> {{ getFile.fileName }}</div>
|
<div class="info">{{ getFile.fileName }}</div>
|
||||||
<a
|
<a :href="getFile.url" target="_blank">
|
||||||
:href="getFile.url"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class="download-button">Download</div>
|
<div class="download-button">Download</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="image-content" ref="image" v-if="getImage">
|
<div class="image-content" ref="image" v-if="getImage">
|
||||||
<img
|
<img :src="getImage" @click="imageClicked" />
|
||||||
:src="getImage"
|
|
||||||
@click="imageClicked"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<message-embed-template v-if="embed && Object.keys(embed).length" :embed="embed"/>
|
<message-embed-template v-if="embed && Object.keys(embed).length" :embed="embed" />
|
||||||
</div>
|
</div>
|
||||||
<div class="other-information">
|
<div class="other-information">
|
||||||
<div class="drop-down-button" ref="drop-down-button" @click="openContextMenu"><i class="material-icons">more_vert</i></div>
|
<div class="drop-down-button" ref="drop-down-button" @click="openContextMenu">
|
||||||
<div class="sending-status" v-if="timeEdited && (status === undefined || status === 1)" :title="`Edited ${getEditedDate}`"><i class="material-icons">edit</i></div>
|
<i class="material-icons">more_vert</i>
|
||||||
<div class="sending-status" v-else-if="status === 0"><i class="material-icons">hourglass_full</i></div>
|
</div>
|
||||||
<div class="sending-status" v-else-if="status === 1"><i class="material-icons">done</i></div>
|
<div
|
||||||
<div class="sending-status" v-else-if="status === 2"><i class="material-icons">close</i> Failed</div>
|
class="sending-status"
|
||||||
|
v-if="timeEdited && (status === undefined || status === 1)"
|
||||||
|
:title="`Edited ${getEditedDate}`"
|
||||||
|
>
|
||||||
|
<i class="material-icons">edit</i>
|
||||||
|
</div>
|
||||||
|
<div class="sending-status" v-else-if="status === 0">
|
||||||
|
<i class="material-icons">hourglass_full</i>
|
||||||
|
</div>
|
||||||
|
<div class="sending-status" v-else-if="status === 1">
|
||||||
|
<i class="material-icons">done</i>
|
||||||
|
</div>
|
||||||
|
<div class="sending-status" v-else-if="status === 2">
|
||||||
|
<i class="material-icons">close</i> Failed
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="type && (type === 1 || type === 2 || type === 3 || type === 4)"
|
v-if="type && (type === 1 || type === 2 || type === 3 || type === 4)"
|
||||||
class="presence-message"
|
class="presence-message"
|
||||||
:class="{join: type === 1, leave: type === 2, kick: type === 3, ban: type === 4}"
|
:class="{join: type === 1, leave: type === 2, kick: type === 3, ban: type === 4}"
|
||||||
>
|
>
|
||||||
<span>
|
<div class="presense-contain">
|
||||||
<span class="username"
|
<span>
|
||||||
@click="openUserInformation"
|
<span class="username" @click="openUserInformation">{{ this.$props.username }}</span>
|
||||||
>{{ this.$props.username }}</span>
|
<span v-if="type === 1" class="text">has joined the server!</span>
|
||||||
<span
|
<span v-if="type === 2" class="text">has left the server.</span>
|
||||||
v-if="type === 1"
|
<span v-if="type === 3" class="text">has been kicked.</span>
|
||||||
class="text"
|
<span v-if="type === 4" class="text">has been banned.</span>
|
||||||
>has joined the server!</span>
|
<span class="date">{{ getDate }}</span>
|
||||||
<span
|
</span>
|
||||||
v-if="type === 2"
|
</div>
|
||||||
class="text"
|
<div class="drop-down-button" ref="drop-down-button" @click="openContextMenu">
|
||||||
>has left the server.</span>
|
<i class="material-icons">more_vert</i>
|
||||||
<span
|
</div>
|
||||||
v-if="type === 3"
|
|
||||||
class="text"
|
|
||||||
>has been kicked.</span>
|
|
||||||
<span
|
|
||||||
v-if="type === 4"
|
|
||||||
class="text"
|
|
||||||
>has been banned.</span>
|
|
||||||
<span class="date">{{ getDate }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -104,10 +95,10 @@ import messageFormatter from "@/utils/messageFormatter.js";
|
||||||
import config from "@/config.js";
|
import config from "@/config.js";
|
||||||
import friendlyDate from "@/utils/date";
|
import friendlyDate from "@/utils/date";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import windowProperties from '@/utils/windowProperties';
|
import windowProperties from "@/utils/windowProperties";
|
||||||
|
|
||||||
import { mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
import messagesService from '../../services/messagesService';
|
import messagesService from "../../services/messagesService";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: [
|
||||||
|
|
@ -132,20 +123,19 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hover: false
|
hover: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openContextMenu(event) {
|
openContextMenu(event) {
|
||||||
const x = event.clientX;
|
const x = event.clientX;
|
||||||
const y = event.clientY;
|
const y = event.clientY;
|
||||||
this.$store.dispatch('setMessageContext', {
|
this.$store.dispatch("setMessageContext", {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
channelID: this.channelID,
|
channelID: this.channelID,
|
||||||
messageID: this.messageID,
|
messageID: this.messageID,
|
||||||
message: this.message,
|
message: this.message,
|
||||||
uniqueID: this.uniqueID
|
uniqueID: this.uniqueID
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openUserInformation() {
|
openUserInformation() {
|
||||||
|
|
@ -157,27 +147,35 @@ export default {
|
||||||
editMessage() {
|
editMessage() {
|
||||||
if (this.uniqueID !== this.user.uniqueID) return;
|
if (this.uniqueID !== this.user.uniqueID) return;
|
||||||
this.dropDownVisable = false;
|
this.dropDownVisable = false;
|
||||||
this.$store.dispatch("setEditMessage", {channelID: this.channelID, messageID: this.messageID, message: this.message});
|
this.$store.dispatch("setEditMessage", {
|
||||||
|
channelID: this.channelID,
|
||||||
|
messageID: this.messageID,
|
||||||
|
message: this.message
|
||||||
|
});
|
||||||
},
|
},
|
||||||
contentDoubleClickEvent(event){
|
contentDoubleClickEvent(event) {
|
||||||
if (event.target.classList.contains("content") || event.target.closest('.user-info')) this.editMessage();
|
if (
|
||||||
|
event.target.classList.contains("content") ||
|
||||||
|
event.target.closest(".user-info")
|
||||||
|
)
|
||||||
|
this.editMessage();
|
||||||
},
|
},
|
||||||
clamp(num, min, max) {
|
clamp(num, min, max) {
|
||||||
return num <= min ? min : num >= max ? max : num;
|
return num <= min ? min : num >= max ? max : num;
|
||||||
},
|
},
|
||||||
calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
|
calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
|
||||||
let ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
|
let ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
|
||||||
return { width: srcWidth*ratio, height: srcHeight*ratio };
|
return { width: srcWidth * ratio, height: srcHeight * ratio };
|
||||||
},
|
},
|
||||||
imageSize() {
|
imageSize() {
|
||||||
const files = this.$props.files;
|
const files = this.$props.files;
|
||||||
if (!files || files.length === 0 || !files[0].dimensions)
|
if (!files || files.length === 0 || !files[0].dimensions)
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
||||||
const messageLog = document.querySelector('.message-logs');
|
const messageLog = document.querySelector(".message-logs");
|
||||||
const w = messageLog.offsetWidth;
|
const w = messageLog.offsetWidth;
|
||||||
const h = messageLog.offsetHeight;
|
const h = messageLog.offsetHeight;
|
||||||
|
|
||||||
let minWidth = w / 4;
|
let minWidth = w / 4;
|
||||||
let minHeight = h / 4;
|
let minHeight = h / 4;
|
||||||
if (w <= 800) {
|
if (w <= 800) {
|
||||||
|
|
@ -185,34 +183,39 @@ export default {
|
||||||
minHeight = h / 1.7;
|
minHeight = h / 1.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dimensions = this.$props.files[0].dimensions;
|
||||||
const dimensions = this.$props.files[0].dimensions
|
|
||||||
const srcWidth = dimensions.width;
|
const srcWidth = dimensions.width;
|
||||||
const srcHeight = dimensions.height;
|
const srcHeight = dimensions.height;
|
||||||
|
|
||||||
const newDimentions = this.calculateAspectRatioFit(srcWidth, srcHeight, minWidth, minHeight);
|
const newDimentions = this.calculateAspectRatioFit(
|
||||||
|
srcWidth,
|
||||||
|
srcHeight,
|
||||||
|
minWidth,
|
||||||
|
minHeight
|
||||||
|
);
|
||||||
|
|
||||||
const imageTag = this.$refs['image'];
|
const imageTag = this.$refs["image"];
|
||||||
|
|
||||||
imageTag.firstChild.style.width = "100%"
|
imageTag.firstChild.style.width = "100%";
|
||||||
imageTag.firstChild.style.height = "100%"
|
imageTag.firstChild.style.height = "100%";
|
||||||
|
|
||||||
imageTag.style.width = this.clamp(newDimentions.width, 0, srcWidth) + "px"
|
imageTag.style.width =
|
||||||
imageTag.style.height = this.clamp(newDimentions.height, 0, srcHeight) + "px"
|
this.clamp(newDimentions.width, 0, srcWidth) + "px";
|
||||||
|
imageTag.style.height =
|
||||||
|
this.clamp(newDimentions.height, 0, srcHeight) + "px";
|
||||||
},
|
},
|
||||||
onResize(dimentions) {
|
onResize(dimentions) {
|
||||||
this.imageSize();
|
this.imageSize();
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
getWindowWidth(dimentions) {
|
getWindowWidth(dimentions) {
|
||||||
this.onResize(dimentions)
|
this.onResize(dimentions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const files = this.files;
|
const files = this.files;
|
||||||
if (!files || files.length === 0 || !files[0].dimensions)
|
if (!files || files.length === 0 || !files[0].dimensions) return undefined;
|
||||||
return undefined;
|
|
||||||
this.imageSize();
|
this.imageSize();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -254,33 +257,40 @@ export default {
|
||||||
return this.$store.getters.user;
|
return this.$store.getters.user;
|
||||||
},
|
},
|
||||||
getWindowWidth() {
|
getWindowWidth() {
|
||||||
return {width: windowProperties.resizeWidth, height: windowProperties.resizeHeight};
|
return {
|
||||||
},
|
width: windowProperties.resizeWidth,
|
||||||
|
height: windowProperties.resizeHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drop-down-button{
|
.drop-down-button {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container:hover .drop-down-button {
|
||||||
|
|
||||||
.container:hover .drop-down-button{
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.presence-message {
|
.presence-message {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
display: flex;
|
||||||
|
color: white;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.presense-contain {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: table;
|
display: table;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
@ -289,24 +299,25 @@ export default {
|
||||||
background: rgba(0, 0, 0, 0.356);
|
background: rgba(0, 0, 0, 0.356);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.presence-message .text {
|
.presence-message .text {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
.presence-message .username {
|
.presence-message .username {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: bold
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.presence-message.join {
|
.presence-message.join .text {
|
||||||
color: #29BF12;
|
color: #29bf12;
|
||||||
}
|
}
|
||||||
.presence-message.leave {
|
.presence-message.leave .text {
|
||||||
color: rgb(150, 139, 139);
|
color: rgb(150, 139, 139);
|
||||||
}
|
}
|
||||||
.presence-message.kick {
|
.presence-message.kick .text {
|
||||||
color: #FF9914;
|
color: #ff9914;
|
||||||
}
|
}
|
||||||
.presence-message.ban {
|
.presence-message.ban .text {
|
||||||
color: #d92121;
|
color: #d92121;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,6 +329,8 @@ export default {
|
||||||
border-left: 8px solid rgba(184, 184, 184, 0.219);
|
border-left: 8px solid rgba(184, 184, 184, 0.219);
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.ownMessageLeft .avatar {
|
.ownMessageLeft .avatar {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
|
@ -338,12 +351,8 @@ export default {
|
||||||
.ownMessage .content {
|
.ownMessage .content {
|
||||||
background: rgba(184, 184, 184, 0.219);
|
background: rgba(184, 184, 184, 0.219);
|
||||||
}
|
}
|
||||||
.ownMessage.halloween .content {
|
|
||||||
background: rgba(255, 135, 31, 0.43);
|
|
||||||
}
|
|
||||||
.ownMessage.halloween .triangle-inner {
|
|
||||||
background: rgba(255, 135, 31, 0.43);
|
|
||||||
}
|
|
||||||
.ownMessage .date {
|
.ownMessage .date {
|
||||||
color: rgb(209, 209, 209);
|
color: rgb(209, 209, 209);
|
||||||
}
|
}
|
||||||
|
|
@ -397,11 +406,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.triangle-inner {
|
.triangle-inner {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-top: 9px solid transparent;
|
border-top: 9px solid transparent;
|
||||||
border-bottom: 0px solid transparent;
|
border-bottom: 0px solid transparent;
|
||||||
border-right: 8px solid rgba(0, 0, 0, 0.301);
|
border-right: 8px solid rgba(0, 0, 0, 0.301);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
|
@ -433,7 +442,6 @@ export default {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.image-content:hover img {
|
.image-content:hover img {
|
||||||
filter: brightness(70%);
|
filter: brightness(70%);
|
||||||
|
|
@ -453,9 +461,6 @@ export default {
|
||||||
color: rgb(199, 199, 199);
|
color: rgb(199, 199, 199);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.username.halloween-color {
|
|
||||||
color: orange
|
|
||||||
}
|
|
||||||
.date {
|
.date {
|
||||||
color: rgb(177, 177, 177);
|
color: rgb(177, 177, 177);
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
|
@ -489,8 +494,6 @@ export default {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.message .other-information div .material-icons {
|
.message .other-information div .material-icons {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
color: rgb(306, 306, 306);
|
color: rgb(306, 306, 306);
|
||||||
|
|
@ -505,14 +508,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 468px) {
|
@media (max-width: 468px) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.code-inline {
|
||||||
.code-inline{
|
|
||||||
background: rgba(0, 0, 0, 0.322);
|
background: rgba(0, 0, 0, 0.322);
|
||||||
}
|
}
|
||||||
.msg-link {
|
.msg-link {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="my-mini-information"
|
class="my-mini-information"
|
||||||
:style="{backgroundColor: getStatusColor}"
|
|
||||||
@mouseover="hover = true" @mouseleave="hover = false"
|
@mouseover="hover = true" @mouseleave="hover = false"
|
||||||
|
|
||||||
>
|
>
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<profile-picture
|
<profile-picture
|
||||||
:url="`${avatar}${hover ? '' : '?type=png'}`"
|
:url="`${avatar}${hover ? '' : '?type=png'}`"
|
||||||
:admin="user.admin"
|
:admin="user.admin"
|
||||||
size="50px"
|
size="35px"
|
||||||
:hover="true"
|
:hover="true"
|
||||||
@click.native="openUserInformation"
|
@click.native="openUserInformation"
|
||||||
/>
|
/>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
class="current-status"
|
class="current-status"
|
||||||
:src="getStatus"
|
:src="getStatus"
|
||||||
>
|
>
|
||||||
<i class="material-icons expand-status-icon">expand_more</i>
|
<i class="material-icons expand-status-icon">expand_less</i>
|
||||||
<transition name="show-status-list">
|
<transition name="show-status-list">
|
||||||
<statusList
|
<statusList
|
||||||
v-if="status.isPoppedOut"
|
v-if="status.isPoppedOut"
|
||||||
|
|
@ -49,12 +49,6 @@
|
||||||
<i class="material-icons">error</i>
|
<i class="material-icons">error</i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="setting-icon"
|
|
||||||
@click="openSettings"
|
|
||||||
>
|
|
||||||
<i class="material-icons">settings</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -123,12 +117,7 @@ export default {
|
||||||
this.$store.dispatch("changeStatus", result.data.set);
|
this.$store.dispatch("changeStatus", result.data.set);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openSettings() {
|
|
||||||
this.$store.dispatch("setPopoutVisibility", {
|
|
||||||
name: "settings",
|
|
||||||
visibility: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -139,8 +128,9 @@ export default {
|
||||||
.profile-pic-outer{
|
.profile-pic-outer{
|
||||||
z-index:9999;
|
z-index:9999;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.survay-button {
|
.survay-button {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
@ -160,6 +150,7 @@ export default {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
color: cyan;
|
color: cyan;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-status-list-enter-active,
|
.show-status-list-enter-active,
|
||||||
|
|
@ -169,7 +160,7 @@ export default {
|
||||||
.show-status-list-enter,
|
.show-status-list-enter,
|
||||||
.show-status-list-leave-to {
|
.show-status-list-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-5px);
|
transform: translateY(20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
|
|
@ -181,19 +172,19 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-mini-information {
|
.my-mini-information {
|
||||||
border-radius: 10px;
|
position: relative;
|
||||||
margin: 5px;
|
background: rgba(0, 0, 0, 0.3);;
|
||||||
height: 80px;
|
height: 50px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 10px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.information {
|
.information {
|
||||||
color: white;
|
color: white;
|
||||||
margin-top: -7px;
|
margin-top: -4px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
@ -205,9 +196,9 @@ export default {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: default;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.setting-icon:hover {
|
.setting-icon:hover {
|
||||||
background: rgba(0, 0, 0, 0.294);
|
background: rgba(0, 0, 0, 0.294);
|
||||||
|
|
@ -221,10 +212,11 @@ export default {
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-top: -2px;
|
margin-top: -10px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status:hover {
|
.status:hover {
|
||||||
|
|
@ -251,14 +243,15 @@ export default {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
color: rgb(199, 199, 199);
|
color: rgb(199, 199, 199);
|
||||||
font-size: 13px;
|
font-size: 11px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
margin-top: 5px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
373
src/components/app/Navigation.vue
Normal file
373
src/components/app/Navigation.vue
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
<template>
|
||||||
|
<div class="navigation" ref="navigation">
|
||||||
|
<div
|
||||||
|
class="tool-tip"
|
||||||
|
ref="toolTip"
|
||||||
|
:style="{top: toolTipTopPosition + 'px'}"
|
||||||
|
v-if="toolTipShown"
|
||||||
|
>{{toolTipLocalName || servers[toolTipServerID].name}}</div>
|
||||||
|
<div class="container" @mouseleave="mouseLeaveEvent">
|
||||||
|
<div class="scrollable">
|
||||||
|
<div class="navigation-items">
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
:class="{selected: currentTab == 0}"
|
||||||
|
@click="switchTab(0)"
|
||||||
|
@mouseenter="localToolTipEvent('Explore', $event)"
|
||||||
|
>explore</div>
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
:class="{selected: currentTab == 1, notifyAnimation: DMNotification || friendRequestExists}"
|
||||||
|
@click="switchTab(1)"
|
||||||
|
@mouseenter="localToolTipEvent('Direct Message', $event)"
|
||||||
|
>chat</div>
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
:class="{selected: currentTab == 2, notifyAnimation: serverNotification}"
|
||||||
|
@click="switchTab(2)"
|
||||||
|
@mouseenter="localToolTipEvent('Servers', $event)"
|
||||||
|
>forum</div>
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
:class="{selected: currentTab == 3}"
|
||||||
|
@click="switchTab(3)"
|
||||||
|
@mouseenter="localToolTipEvent('Changelog', $event)"
|
||||||
|
>list_alt</div>
|
||||||
|
</div>
|
||||||
|
<div class="seperater" />
|
||||||
|
<div class="server-items" v-if="currentTab === 2">
|
||||||
|
<server-template
|
||||||
|
v-for="(data, index) in serversArr"
|
||||||
|
:serverData="data"
|
||||||
|
@click.native="openServer(data.server_id)"
|
||||||
|
:key="index.server_id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="seperater" />
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
v-if="currentTab === 1"
|
||||||
|
@click="addFriend"
|
||||||
|
@mouseenter="localToolTipEvent('Add Friend', $event)"
|
||||||
|
>person_add</div>
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
v-if="currentTab === 2"
|
||||||
|
@click="addServer"
|
||||||
|
@mouseenter="localToolTipEvent('Add Server', $event)"
|
||||||
|
>add</div>
|
||||||
|
<div
|
||||||
|
class="item material-icons"
|
||||||
|
@click="openSettings"
|
||||||
|
@mouseenter="localToolTipEvent('Settings', $event)"
|
||||||
|
>settings</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { bus } from "@/main.js";
|
||||||
|
import config from "@/config.js";
|
||||||
|
import ServerTemplate from "@/components/app/ServerTemplate/ServerTemplate";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { ServerTemplate },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
avatarDomain: config.domain + "/avatars",
|
||||||
|
toolTipShown: false,
|
||||||
|
toolTipTopPosition: 0,
|
||||||
|
toolTipServerID: null,
|
||||||
|
toolTipLocalName: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
dismissNotification(channelID) {
|
||||||
|
const notifications = this.$store.getters.notifications.find(function(e) {
|
||||||
|
return e.channelID === channelID;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (notifications && notifications.count >= 1 && document.hasFocus()) {
|
||||||
|
this.$socket.emit("notification:dismiss", { channelID });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openServer(serverID) {
|
||||||
|
const server = this.servers[serverID];
|
||||||
|
const lastSelectedChannel = JSON.parse(
|
||||||
|
localStorage.getItem("selectedChannels") || "{}"
|
||||||
|
)[serverID];
|
||||||
|
const defaultChannelID = server.default_channel_id;
|
||||||
|
const channels = this.$store.getters.channels;
|
||||||
|
const channel = channels[lastSelectedChannel || defaultChannelID];
|
||||||
|
|
||||||
|
this.dismissNotification(channel.channelID);
|
||||||
|
this.$store.dispatch("servers/setSelectedServerID", serverID);
|
||||||
|
this.$store.dispatch("openChannel", channel);
|
||||||
|
},
|
||||||
|
switchChannel(isServer) {
|
||||||
|
const serverChannelID = this.$store.state.channelModule.serverChannelID;
|
||||||
|
const DMChannelID = this.$store.state.channelModule.DMChannelID;
|
||||||
|
|
||||||
|
if (isServer) {
|
||||||
|
this.$store.dispatch("selectedChannelID", serverChannelID);
|
||||||
|
const channel = this.$store.state.channelModule.channels[
|
||||||
|
serverChannelID
|
||||||
|
];
|
||||||
|
this.$store.dispatch("setChannelName", channel ? channel.name : "");
|
||||||
|
this.dismissNotification(serverChannelID);
|
||||||
|
} else {
|
||||||
|
const channel = this.$store.state.channelModule.channels[DMChannelID];
|
||||||
|
this.$store.dispatch(
|
||||||
|
"setChannelName",
|
||||||
|
channel ? channel.recipients[0].username : ""
|
||||||
|
);
|
||||||
|
this.$store.dispatch("selectedChannelID", DMChannelID);
|
||||||
|
this.dismissNotification(DMChannelID);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
switchTab(index) {
|
||||||
|
localStorage.setItem("currentTab", index);
|
||||||
|
this.$store.dispatch("setCurrentTab", index);
|
||||||
|
if (index == 1) {
|
||||||
|
//1: direct message tab.
|
||||||
|
this.switchChannel(false);
|
||||||
|
} else if (index === 2) {
|
||||||
|
//2: server tab
|
||||||
|
this.switchChannel(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openSettings() {
|
||||||
|
this.$store.dispatch("setPopoutVisibility", {
|
||||||
|
name: "settings",
|
||||||
|
visibility: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
localToolTipEvent(name, event) {
|
||||||
|
const rect = event.target.getBoundingClientRect();
|
||||||
|
this.toolTipLocalName = name;
|
||||||
|
this.toolTipTopPosition = rect.top - this.getTopHeight() + 16;
|
||||||
|
this.toolTipShown = true;
|
||||||
|
},
|
||||||
|
serverToolTipEvent({ serverID, top }) {
|
||||||
|
this.toolTipLocalName = null;
|
||||||
|
this.toolTipServerID = serverID;
|
||||||
|
this.toolTipTopPosition = top - this.getTopHeight() + 16;
|
||||||
|
this.toolTipShown = true;
|
||||||
|
},
|
||||||
|
mouseLeaveEvent() {
|
||||||
|
this.toolTipShown = false;
|
||||||
|
this.toolTipServerID = null;
|
||||||
|
this.toolTipLocalName = null;
|
||||||
|
},
|
||||||
|
getTopHeight() {
|
||||||
|
return window.innerHeight - this.$refs["navigation"].offsetHeight;
|
||||||
|
},
|
||||||
|
addServer() {
|
||||||
|
this.$store.dispatch("setPopoutVisibility", {
|
||||||
|
name: "addServer",
|
||||||
|
visibility: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addFriend() {
|
||||||
|
this.$store.dispatch('setAllPopout', {
|
||||||
|
show: true,
|
||||||
|
type: "ADD_FRIEND",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentTab() {
|
||||||
|
return this.$store.getters.currentTab;
|
||||||
|
},
|
||||||
|
servers() {
|
||||||
|
return this.$store.getters["servers/servers"];
|
||||||
|
},
|
||||||
|
serversArr() {
|
||||||
|
const data = this.servers;
|
||||||
|
return Object.keys(data)
|
||||||
|
.map(key => {
|
||||||
|
return data[key];
|
||||||
|
})
|
||||||
|
.slice()
|
||||||
|
.reverse();
|
||||||
|
},
|
||||||
|
selectedServerID() {
|
||||||
|
return this.$store.getters["servers/selectedServerID"];
|
||||||
|
},
|
||||||
|
serverNotification() {
|
||||||
|
const notifications = this.$store.getters.notifications;
|
||||||
|
const channels = this.$store.getters.channels;
|
||||||
|
const notification = notifications.find(e => {
|
||||||
|
return (
|
||||||
|
channels[e.channelID] &&
|
||||||
|
channels[e.channelID].server_id &&
|
||||||
|
e.channelID !== this.$store.getters.selectedChannelID
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return notification;
|
||||||
|
},
|
||||||
|
DMNotification() {
|
||||||
|
const notifications = this.$store.getters.notifications;
|
||||||
|
const channels = this.$store.getters.channels;
|
||||||
|
const notification = notifications.find(e => {
|
||||||
|
return (
|
||||||
|
channels[e.channelID] &&
|
||||||
|
!channels[e.channelID].server_id &&
|
||||||
|
e.channelID !== this.$store.getters.selectedChannelID
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// unopened dm
|
||||||
|
if (!notification) {
|
||||||
|
return notifications.find(e => {
|
||||||
|
return !channels[e.channelID];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return notification;
|
||||||
|
},
|
||||||
|
friendRequestExists() {
|
||||||
|
const allFriend = this.$store.getters.user.friends;
|
||||||
|
const result = Object.keys(allFriend).map(function(key) {
|
||||||
|
return allFriend[key];
|
||||||
|
});
|
||||||
|
return result.find(friend => friend.status === 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
bus.$on("server-tool-tip", this.serverToolTipEvent);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
bus.$off("server-tool-tip", this.serverToolTipEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.navigation {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 60px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
.navigation-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
align-self: flex-start;
|
||||||
|
align-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.scrollable {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
height: 100%;
|
||||||
|
align-self: center;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: white;
|
||||||
|
font-size: 30px;
|
||||||
|
align-self: center;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: 0.2s;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
&.selected {
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seperater {
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-self: center;
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notifyAnimation:before {
|
||||||
|
content: "!";
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
font-size: 15px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 115651;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
animation: notifyAnime;
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 23, 23, 0.753);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
@keyframes notifyAnime {
|
||||||
|
0% {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-tip {
|
||||||
|
color: white;
|
||||||
|
position: absolute;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
padding: 5px;
|
||||||
|
max-width: 150px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
left: 60px;
|
||||||
|
z-index: 99999;
|
||||||
|
user-select: none;
|
||||||
|
cursor: default;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
<GenericPopout key="gp" v-if="popouts.genericMessage"/>
|
<GenericPopout key="gp" v-if="popouts.genericMessage"/>
|
||||||
<message-context-menu key="mcm" v-if="popouts.messageContextMenu.messageID"/>
|
<message-context-menu key="mcm" v-if="popouts.messageContextMenu.messageID"/>
|
||||||
<server-member-context key="smc" v-if="popouts.serverMemberContext.uniqueID"/>
|
<server-member-context key="smc" v-if="popouts.serverMemberContext.uniqueID"/>
|
||||||
|
<server-context key="sc" v-if="popouts.allPopout.type === 'SERVER' && popouts.allPopout.show"/>
|
||||||
|
<add-friend key="af" v-if="popouts.allPopout.type === 'ADD_FRIEND' && popouts.allPopout.show"/>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -26,9 +28,11 @@
|
||||||
// context menus
|
// context menus
|
||||||
const messageContextMenu = () => import('./Popouts/messageContextMenu');
|
const messageContextMenu = () => import('./Popouts/messageContextMenu');
|
||||||
const ServerMemberContext = () => import('./Popouts/ServerMemberContext');
|
const ServerMemberContext = () => import('./Popouts/ServerMemberContext');
|
||||||
|
const ServerContext = () => import('./Popouts/ServerContextMenu.vue');
|
||||||
|
|
||||||
|
|
||||||
const AddServer = () => import('./Popouts/AddServer.vue');
|
const AddServer = () => import('./Popouts/AddServer.vue');
|
||||||
|
const AddFriend = () => import('./Popouts/AddFriend');
|
||||||
const Settings = () => import('./Popouts/Settings.vue');
|
const Settings = () => import('./Popouts/Settings.vue');
|
||||||
const TakeSurveyPopout = () => import('./Popouts/TakeSurveyPopout.vue');
|
const TakeSurveyPopout = () => import('./Popouts/TakeSurveyPopout.vue');
|
||||||
const uploadDialog = () => import('./Popouts/uploadDialog.vue');
|
const uploadDialog = () => import('./Popouts/uploadDialog.vue');
|
||||||
|
|
@ -55,7 +59,10 @@ export default {
|
||||||
ServerSettings,
|
ServerSettings,
|
||||||
GenericPopout,
|
GenericPopout,
|
||||||
messageContextMenu,
|
messageContextMenu,
|
||||||
ServerMemberContext
|
ServerMemberContext,
|
||||||
|
ServerContext,
|
||||||
|
AddFriend
|
||||||
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
174
src/components/app/Popouts/Popouts/AddFriend.vue
Normal file
174
src/components/app/Popouts/Popouts/AddFriend.vue
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
<template>
|
||||||
|
<div class="dark-background" @mousedown="backgroundClick">
|
||||||
|
<div class="add-friend">
|
||||||
|
<div class="header">
|
||||||
|
<div class="icon material-icons">person_add</div>
|
||||||
|
<div class="name">Add Friend</div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="container">
|
||||||
|
<div class="description">Add friends by using their username and tag.</div>
|
||||||
|
<input class="tag" v-model="input" type="text" placeholder="pancake@time" />
|
||||||
|
<input class="button" @click="addButton" type="button" :value="requestSent ? 'Adding...' :'Add Friend'" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alerts" :class="{success, error}" v-if="error || success">{{error || success || ""}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RelationshipService from '@/services/RelationshipService.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
input: "",
|
||||||
|
requestSent: false,
|
||||||
|
error: null,
|
||||||
|
success: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {
|
||||||
|
closeMenu() {
|
||||||
|
this.$store.dispatch("setAllPopout", {
|
||||||
|
show: false,
|
||||||
|
type: "ADD_FRIEND"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
backgroundClick(e) {
|
||||||
|
if (e.target.classList.contains("dark-background")) {
|
||||||
|
this.closeMenu();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async addButton(e) {
|
||||||
|
if (this.requestSent) return;
|
||||||
|
this.error = null;
|
||||||
|
this.success = null;
|
||||||
|
this.requestSent = true;
|
||||||
|
|
||||||
|
const split = this.input.trim().split("@");
|
||||||
|
// validation
|
||||||
|
if ( split.length <2 || split.length >2 || split[1] === "" || split[1].length !== 4){
|
||||||
|
this.requestSent = false;
|
||||||
|
this.error = "Invalid username or tag.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const username = split[0];
|
||||||
|
const tag = split[1];
|
||||||
|
|
||||||
|
const {ok, error, result} = await RelationshipService.post({username, tag})
|
||||||
|
this.requestSent = false;
|
||||||
|
if ( ok ) {
|
||||||
|
this.success = result.data.message
|
||||||
|
} else {
|
||||||
|
if (error.response === undefined) {
|
||||||
|
this.error = "Can't connect to server.";
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.error = error.response.data.errors[0].msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.dark-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.541);
|
||||||
|
z-index: 111111;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-friend {
|
||||||
|
height: 300px;
|
||||||
|
width: 400px;
|
||||||
|
background: rgba(24, 24, 24, 0.9);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: rgba(41, 41, 41, 0.801);
|
||||||
|
color: white;
|
||||||
|
height: 50px;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: auto;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
color: white;
|
||||||
|
background: transparent;
|
||||||
|
border: solid 1px #afafaf;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
align-self: center;
|
||||||
|
color: white;
|
||||||
|
width: initial;
|
||||||
|
background: #1998ff;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: #157fd6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerts {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 30px;
|
||||||
|
color: white;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
&.success {
|
||||||
|
background: #008a00;
|
||||||
|
}
|
||||||
|
&.error {
|
||||||
|
background: #8a0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
102
src/components/app/Popouts/Popouts/ServerContextMenu.vue
Normal file
102
src/components/app/Popouts/Popouts/ServerContextMenu.vue
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
<template>
|
||||||
|
<div class="drop-down-menu" v-click-outside="outsideClick">
|
||||||
|
<div class="item" @click="createInvite" >Manage Invites</div>
|
||||||
|
<div class="item" v-if="checkServerCreator" @click="showSettings" >Server Settings</div>
|
||||||
|
<div class="item warn" v-if="!checkServerCreator" @click="leaveServer">Leave Server</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import messagesService from '@/services/messagesService';
|
||||||
|
import ServerService from '../../../../services/ServerService';
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeMenu() {
|
||||||
|
this.$store.dispatch('setAllPopout', {
|
||||||
|
show: false,
|
||||||
|
type: null,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
outsideClick(event) {
|
||||||
|
if (event.target.classList.contains('options-button')) return;
|
||||||
|
this.closeMenu();
|
||||||
|
},
|
||||||
|
setPosition() {
|
||||||
|
const y = this.contextDetails.y;
|
||||||
|
const x = this.contextDetails.x;
|
||||||
|
|
||||||
|
this.$el.style.top = y + "px";
|
||||||
|
this.$el.style.left = x + "px";
|
||||||
|
},
|
||||||
|
showSettings() {
|
||||||
|
this.closeMenu()
|
||||||
|
this.$store.dispatch('setServerSettings', {serverID: this.contextDetails.serverID})
|
||||||
|
},
|
||||||
|
createInvite(serverID) {
|
||||||
|
this.closeMenu()
|
||||||
|
this.$store.dispatch("setPopoutVisibility", {
|
||||||
|
name: "showServerInviteMenu",
|
||||||
|
visibility: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async leaveServer() {
|
||||||
|
this.closeMenu()
|
||||||
|
const {ok, error, result} = await ServerService.leaveServer(this.contextDetails.serverID);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setPosition();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
contextDetails() {
|
||||||
|
this.setPosition();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
contextDetails() {
|
||||||
|
return this.$store.getters.popouts.allPopout
|
||||||
|
},
|
||||||
|
user() {
|
||||||
|
return this.$store.getters.user;
|
||||||
|
},
|
||||||
|
checkServerCreator() {
|
||||||
|
return this.contextDetails.creatorUniqueID === this.user.uniqueID
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.drop-down-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
z-index: 99999;
|
||||||
|
user-select: none;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 10px;
|
||||||
|
transition: 0.3s;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(46, 46, 46, 0.651);
|
||||||
|
}
|
||||||
|
&.warn {
|
||||||
|
color: rgb(255, 59, 59);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -39,7 +39,6 @@ import config from "@/config.js";
|
||||||
import { bus } from "@/main";
|
import { bus } from "@/main";
|
||||||
import Spinner from "@/components/Spinner.vue";
|
import Spinner from "@/components/Spinner.vue";
|
||||||
import ServerService from "@/services/ServerService";
|
import ServerService from "@/services/ServerService";
|
||||||
import { mapState } from "vuex";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {Spinner},
|
components: {Spinner},
|
||||||
|
|
@ -84,9 +83,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
serverID() {
|
||||||
serverID: state => state.popoutsModule.serverIDContextMenu
|
return this.$store.getters.popouts.allPopout.serverID
|
||||||
})
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -106,23 +106,21 @@ export default {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
background: rgba(31, 31, 31, 0.995);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
padding: 5px;
|
padding: 10px;
|
||||||
margin: 2px;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgb(46, 46, 46);
|
background: rgba(46, 46, 46, 0.651);
|
||||||
}
|
}
|
||||||
&.warn {
|
&.warn {
|
||||||
color: rgb(255, 59, 59);
|
color: rgb(255, 59, 59);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@
|
||||||
<div class="my-profile-panel">
|
<div class="my-profile-panel">
|
||||||
|
|
||||||
<div class="switches">
|
<div class="switches">
|
||||||
|
<div class="checkbox"
|
||||||
|
@click="toggleNotificationSounds">
|
||||||
|
<div class="checkbox-box" :class="{selected: !notificationSettings.disableNotificationSound}" />
|
||||||
|
<div class="checkbox-name">
|
||||||
|
Notification Sounds
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="checkbox"
|
<div class="checkbox"
|
||||||
@click="toggleNotification()">
|
@click="toggleNotification()">
|
||||||
<div class="checkbox-box" :class="{selected: !notificationSettings.disableDesktopNotification}" />
|
<div class="checkbox-box" :class="{selected: !notificationSettings.disableDesktopNotification}" />
|
||||||
|
|
@ -23,7 +30,8 @@ import SettingsService from '@/services/settingsService.js';
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isElectron: window && window.process && window.process.type
|
isElectron: window && window.process && window.process.type,
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -39,7 +47,7 @@ export default {
|
||||||
const setting = this.notificationSettings['disableDesktopNotification'];
|
const setting = this.notificationSettings['disableDesktopNotification'];
|
||||||
if (setting && setting === true && !this.isElectron) {
|
if (setting && setting === true && !this.isElectron) {
|
||||||
if (Notification.permission === "denied") {
|
if (Notification.permission === "denied") {
|
||||||
alert("Notifications blocked. Please enable them in your browser.");
|
alert("Notifications permission is blocked. Allow notifications from this website in your browsers permission settings.");
|
||||||
}
|
}
|
||||||
Notification.requestPermission().then(function(result) {
|
Notification.requestPermission().then(function(result) {
|
||||||
if (result === 'denied' || result === 'default') return;
|
if (result === 'denied' || result === 'default') return;
|
||||||
|
|
@ -49,6 +57,12 @@ export default {
|
||||||
}
|
}
|
||||||
this.toggleSetting('disableDesktopNotification');
|
this.toggleSetting('disableDesktopNotification');
|
||||||
},
|
},
|
||||||
|
toggleNotificationSounds(){
|
||||||
|
console.log("test")
|
||||||
|
const setting = this.notificationSettings['disableNotificationSound'];
|
||||||
|
console.log(!!!setting)
|
||||||
|
this.$store.dispatch('settingsModule/updateNotification', {disableNotificationSound: !setting})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.isElectron && this.notificationSettings.disableDesktopNotification === undefined) {
|
if (!this.isElectron && this.notificationSettings.disableDesktopNotification === undefined) {
|
||||||
|
|
@ -69,18 +83,19 @@ export default {
|
||||||
|
|
||||||
.switches {
|
.switches {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
.checkbox-box {
|
.checkbox-box {
|
||||||
background: rgba(88, 88, 88, 0.74);
|
background: rgba(88, 88, 88, 0.74);
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin: auto;
|
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
|
||||||
|
|
@ -106,23 +106,20 @@ export default {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
background: rgba(31, 31, 31, 0.895);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
padding: 5px;
|
padding: 10px;
|
||||||
margin: 2px;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgb(46, 46, 46);
|
background: rgba(46, 46, 46, 0.651);
|
||||||
}
|
}
|
||||||
&.warn {
|
&.warn {
|
||||||
color: rgb(255, 59, 59);
|
color: rgb(255, 59, 59);
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
openChat() {
|
openChat() {
|
||||||
bus.$emit('changeTab', 1)
|
this.$store.dispatch('setCurrentTab', 1)
|
||||||
this.$store.dispatch("openChat", {
|
this.$store.dispatch("openChat", {
|
||||||
uniqueID: this.uniqueID,
|
uniqueID: this.uniqueID,
|
||||||
channelName: this.user.username
|
channelName: this.user.username
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="left-panel">
|
<div class="left-panel">
|
||||||
<MyMiniInformation />
|
<navigation />
|
||||||
<div class="actions">
|
<div class="right">
|
||||||
<div class="action" @click="openAddServer">
|
<div class="server-banner" v-if="selectedServerID">
|
||||||
<div class="material-icons">add</div>
|
<div class="banner-image"></div>
|
||||||
<div class="text">Add Server</div>
|
<div class="sub-banner" >
|
||||||
|
<div class="text" :title="servers[selectedServerID].name">{{servers[selectedServerID].name}}</div>
|
||||||
|
<div class="options-button material-icons" @click="openServerContext">more_vert</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="action" @click="openExploreTab">
|
<div class="channels-list">
|
||||||
<div class="material-icons">explore</div>
|
<channels-list v-if="selectedServerID" :server-i-d="selectedServerID" />
|
||||||
<div class="text">Explore</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<MyMiniInformation />
|
||||||
<div class="list">
|
|
||||||
<server
|
|
||||||
v-for="(data, index) in servers"
|
|
||||||
:key="index.server_id"
|
|
||||||
:server-data="data"
|
|
||||||
:open-channel="selectedServerID && selectedServerID === data.server_id"
|
|
||||||
@click.native="toggleChannel(data.server_id, $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -26,12 +20,16 @@
|
||||||
<script>
|
<script>
|
||||||
import MyMiniInformation from "@/components/app/MyMiniInformation.vue";
|
import MyMiniInformation from "@/components/app/MyMiniInformation.vue";
|
||||||
import Server from "@/components/app/ServerTemplate/ServerTemplate.vue";
|
import Server from "@/components/app/ServerTemplate/ServerTemplate.vue";
|
||||||
import {bus} from '@/main'
|
import ChannelsList from "@/components/app/ServerTemplate/ChannelsList.vue";
|
||||||
|
import Navigation from "@/components/app/Navigation.vue";
|
||||||
|
import { bus } from "@/main";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MyMiniInformation,
|
MyMiniInformation,
|
||||||
Server
|
ChannelsList,
|
||||||
|
Server,
|
||||||
|
Navigation
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -45,98 +43,147 @@ export default {
|
||||||
visibility: true
|
visibility: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
toggleChannel(serverID, event) {
|
clickServer(serverID, event) {
|
||||||
if (!event.target.closest('.small-view') || event.target.closest('.options-context-button') || event.target.closest('.options-context-menu')) return;
|
this.openedServer = serverID;
|
||||||
if (this.openedServer === serverID) {
|
this.$store.dispatch("servers/setSelectedServerID", serverID);
|
||||||
this.openedServer = null;
|
|
||||||
this.$store.dispatch('servers/setSelectedServerID', null)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
this.openedServer = serverID;
|
|
||||||
this.$store.dispatch('servers/setSelectedServerID', serverID)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
openExploreTab() {
|
openExploreTab() {
|
||||||
bus.$emit('changeTab', 0)
|
this.$store.dispatch('setCurrentTab', 0)
|
||||||
|
},
|
||||||
|
openServerContext(event) {
|
||||||
|
const rect = event.target.getBoundingClientRect();
|
||||||
|
if (this.checkServerContextOpened) {
|
||||||
|
this.$store.dispatch('setAllPopout', {
|
||||||
|
show: false,
|
||||||
|
type: null
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$store.dispatch('setAllPopout', {
|
||||||
|
show: true,
|
||||||
|
type: 'SERVER',
|
||||||
|
serverID: this.servers[this.selectedServerID].server_id,
|
||||||
|
creatorUniqueID: this.servers[this.selectedServerID].creator.uniqueID,
|
||||||
|
x: rect.left - 30,
|
||||||
|
y: rect.top + 35,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
servers() {
|
servers() {
|
||||||
const data = this.$store.getters['servers/servers'];
|
return this.$store.getters["servers/servers"];
|
||||||
return Object.keys(data).map(key => {
|
},
|
||||||
return data[key];
|
serversArr() {
|
||||||
}).slice().reverse()
|
const data = this.servers;
|
||||||
|
return Object.keys(data)
|
||||||
|
.map(key => {
|
||||||
|
return data[key];
|
||||||
|
})
|
||||||
|
.slice()
|
||||||
|
.reverse();
|
||||||
},
|
},
|
||||||
selectedServerID() {
|
selectedServerID() {
|
||||||
return this.$store.getters['servers/selectedServerID'];
|
return this.$store.getters["servers/selectedServerID"];
|
||||||
},
|
},
|
||||||
|
checkServerContextOpened() {
|
||||||
|
const contextDetail = this.$store.getters.popouts.allPopout;
|
||||||
|
return contextDetail.show && contextDetail.type === "SERVER";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss" >
|
<style scoped lang="scss" >
|
||||||
.left-panel {
|
.left-panel {
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.671);
|
|
||||||
width: 300px;
|
width: 300px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.list {
|
|
||||||
margin: 2px;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
flex: 1;
|
|
||||||
overflow: auto;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------- SCROLL BAR -------*/
|
.channels-list {
|
||||||
/* width */
|
|
||||||
.list::-webkit-scrollbar {
|
|
||||||
width: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Track */
|
|
||||||
.list::-webkit-scrollbar-track {
|
|
||||||
background: #8080806b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
.list::-webkit-scrollbar-thumb {
|
|
||||||
background: #f5f5f559;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle on hover */
|
|
||||||
.list::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: #f5f5f59e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.left {
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
background: rgba(29, 29, 29, 0.37);
|
||||||
|
width: 70px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-banner {
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: rgb(32, 32, 32);
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
.banner-image {
|
||||||
|
position: absolute;
|
||||||
|
background-image: url("../../assets/background.jpg");
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.sub-banner {
|
||||||
|
display: flex;
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(0, 0, 0, 0.507);
|
||||||
|
align-self: flex-end;
|
||||||
|
height: 35px;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 10px;
|
||||||
|
position: relative;
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
|
z-index: 2;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
.action {
|
overflow: hidden;
|
||||||
display: flex;
|
cursor: default;
|
||||||
padding: 5px;
|
.text {
|
||||||
margin: 2px;
|
overflow: hidden;
|
||||||
align-items: center;
|
white-space: nowrap;
|
||||||
align-content: center;
|
text-overflow: ellipsis;
|
||||||
cursor: pointer;
|
width: 100%;
|
||||||
color: rgb(223, 223, 223);
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.2s;
|
|
||||||
.material-icons {
|
|
||||||
color: white;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.24);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.options-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 35px;
|
||||||
|
width: 35px;
|
||||||
|
transition: 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
font-size: 20px;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.322);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -54,22 +54,26 @@ export default {
|
||||||
.channel {
|
.channel {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 5px;
|
|
||||||
margin-top: 3px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
.channel:hover {
|
.channel:hover {
|
||||||
background: rgba(139, 139, 139, 0.288);
|
background: rgba(0, 0, 0, 0.192);
|
||||||
}
|
}
|
||||||
.selected {
|
.channel.selected {
|
||||||
background: rgba(139, 139, 139, 0.288);
|
background: rgba(0, 0, 0, 0.288);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.channel-name {
|
.channel-name {
|
||||||
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openChannel(channel) {
|
openChannel(channel) {
|
||||||
|
// add to local storage
|
||||||
|
const selectedChannels = JSON.parse(localStorage.getItem('selectedChannels') || '{}')
|
||||||
|
selectedChannels[this.serverID] = channel.channelID;
|
||||||
|
localStorage.setItem('selectedChannels', JSON.stringify(selectedChannels));
|
||||||
|
|
||||||
const notificationExists = this.$store.getters.notifications.find(n => n.channelID === channel.channelID)
|
const notificationExists = this.$store.getters.notifications.find(n => n.channelID === channel.channelID)
|
||||||
|
|
||||||
if (notificationExists && document.hasFocus()) {
|
if (notificationExists && document.hasFocus()) {
|
||||||
|
|
@ -79,11 +84,21 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.channel-list {
|
.channels-list {
|
||||||
background: rgba(0, 0, 0, 0.288);
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------- SCROLL BAR -------*/
|
||||||
|
/* width */
|
||||||
|
.channels-list::-webkit-scrollbar {
|
||||||
|
width: 3px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,243 +1,126 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{server: true, 'add-server': mode === 'ADD_SERVER'}">
|
<div class="server" :class="{selected: selectedServerID === serverData.server_id, notifyAnimation: notification }" @contextmenu.prevent="contextEvent" @mouseenter="hoverEvent" @mouseover="hover = true" @mouseleave="hover = false">
|
||||||
<div :class="{'small-view': true, notifyAnimation: notification}">
|
<profile-picture size="45px" :url="`${avatarDomain}/${serverData.avatar}${hover ? '' : '?type=png'}`" />
|
||||||
<profile-picture
|
|
||||||
v-if="!mode"
|
|
||||||
size="50px"
|
|
||||||
:url="`${avatarDomain}/${serverData.avatar}`"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
v-if="mode === 'ADD_SERVER'"
|
|
||||||
class="add-icon"
|
|
||||||
>
|
|
||||||
<i class="material-icons">add</i>
|
|
||||||
</div>
|
|
||||||
<div class="server-name">
|
|
||||||
{{ mode === 'ADD_SERVER'? 'Create / Join Server' : serverData.name }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="mode !== 'ADD_SERVER'"
|
|
||||||
ref="contextMenuButton"
|
|
||||||
class="options-context-button"
|
|
||||||
@click="showContextMenu = !showContextMenu"
|
|
||||||
>
|
|
||||||
<i class="material-icons">more_vert</i>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="showContextMenu"
|
|
||||||
v-click-outside="closeContextMenu"
|
|
||||||
class="options-context-menu"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-button"
|
|
||||||
@click="createInvite(serverData.server_id)"
|
|
||||||
>
|
|
||||||
Manage Invites
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="serverData.creator.uniqueID !== user.uniqueID"
|
|
||||||
class="menu-button warn"
|
|
||||||
@click="leaveServer(serverData.server_id)"
|
|
||||||
>
|
|
||||||
Leave Server
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="serverData.creator.uniqueID === user.uniqueID"
|
|
||||||
class="menu-button"
|
|
||||||
@click="showSettings()"
|
|
||||||
>
|
|
||||||
Server Settings
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ref="container">
|
|
||||||
<channels-list
|
|
||||||
v-if="openChannel"
|
|
||||||
:server-i-d="serverData.server_id"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {bus} from "../../../main.js"
|
||||||
import config from "@/config.js";
|
import config from "@/config.js";
|
||||||
import ChannelsList from "@/components/app/ServerTemplate/ChannelsList.vue";
|
|
||||||
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
import ProfilePicture from "@/components/ProfilePictureTemplate.vue";
|
||||||
import ServerService from "@/services/ServerService";
|
import ServerService from "@/services/ServerService";
|
||||||
import smoothReflow from "vue-smooth-reflow";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ProfilePicture, ChannelsList },
|
components: { ProfilePicture },
|
||||||
mixins: [smoothReflow],
|
props: ["serverData"],
|
||||||
props: ["serverData", "openChannel", "mode"],
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showContextMenu: false,
|
avatarDomain: config.domain + "/avatars",
|
||||||
showChannels: false,
|
hover: false
|
||||||
avatarDomain: config.domain + "/avatars"
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user() {
|
user() {
|
||||||
return this.$store.getters.user;
|
return this.$store.getters.user;
|
||||||
},
|
},
|
||||||
|
selectedServerID() {
|
||||||
|
return this.$store.getters["servers/selectedServerID"];
|
||||||
|
},
|
||||||
notification() {
|
notification() {
|
||||||
const notifications = this.$store.getters.notifications;
|
const notifications = this.$store.getters.notifications;
|
||||||
const channels = this.$store.getters.channels
|
const channels = this.$store.getters.channels;
|
||||||
const notification = notifications.find(e => {
|
const notification = notifications.find(e => {
|
||||||
return channels[e.channelID] && channels[e.channelID].server_id && this.serverData && channels[e.channelID].server_id === this.serverData.server_id
|
return (
|
||||||
})
|
channels[e.channelID] &&
|
||||||
|
channels[e.channelID].server_id &&
|
||||||
|
this.serverData &&
|
||||||
|
channels[e.channelID].server_id === this.serverData.server_id
|
||||||
|
);
|
||||||
|
});
|
||||||
return notification;
|
return notification;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.$smoothReflow({
|
|
||||||
el: this.$refs.container
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
showSettings() {
|
hoverEvent(event) {
|
||||||
this.showContextMenu = false;
|
const rect = event.target.getBoundingClientRect();
|
||||||
this.$store.dispatch('setServerSettings', {serverID: this.serverData.server_id})
|
//let centerX = targetNode.offsetLeft + targetNode.offsetWidth / 2;
|
||||||
|
//let centerY = targetNode.offsetTop + targetNode.offsetHeight / 2;
|
||||||
|
bus.$emit('server-tool-tip', {serverID: this.serverData.server_id, top: rect.top})
|
||||||
},
|
},
|
||||||
createInvite(serverID) {
|
contextEvent(event) {
|
||||||
this.showContextMenu = false;
|
this.$store.dispatch('setAllPopout', {
|
||||||
this.$store.dispatch("setServerIDContextMenu", serverID);
|
show: true,
|
||||||
this.$store.dispatch("setPopoutVisibility", {
|
type: 'SERVER',
|
||||||
name: "showServerInviteMenu",
|
serverID: this.serverData.server_id,
|
||||||
visibility: true
|
creatorUniqueID: this.serverData.creator.uniqueID,
|
||||||
});
|
x: event.clientX,
|
||||||
},
|
y: event.clientY
|
||||||
closeContextMenu(event) {
|
})
|
||||||
if (
|
|
||||||
event.target.closest(".options-context-button") ===
|
|
||||||
this.$refs.contextMenuButton
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
this.showContextMenu = false;
|
|
||||||
},
|
|
||||||
async leaveServer(serverID) {
|
|
||||||
this.showContextMenu = false;
|
|
||||||
const {ok, error, result} = await ServerService.leaveServer(serverID);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
.server {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-self: center;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
transition: 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
&.selected {
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.notifyAnimation:before{
|
.notifyAnimation:before {
|
||||||
content: '';
|
content: "!";
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 15px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: 115651;
|
||||||
top: 0;
|
top: 5px;
|
||||||
left: 0;
|
right: 5px;
|
||||||
right: 0;
|
width: 20px;
|
||||||
bottom: 0;
|
height: 20px;
|
||||||
animation: notifyAnime;
|
animation: notifyAnime;
|
||||||
animation-duration: 1s;
|
animation-duration: 1s;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
border-radius: 5px;
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 23, 23, 0.753);
|
||||||
}
|
}
|
||||||
@keyframes notifyAnime {
|
@keyframes notifyAnime {
|
||||||
0%{
|
0% {
|
||||||
background: rgba(255, 0, 0, 0.198);
|
opacity: 1;
|
||||||
}
|
}
|
||||||
40%{
|
40% {
|
||||||
background: rgba(255, 0, 0, 0.411);
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
60%{
|
60% {
|
||||||
background: rgba(255, 0, 0, 0.411);
|
opacity: 1;
|
||||||
}
|
}
|
||||||
100%{
|
100% {
|
||||||
background: rgba(255, 0, 0, 0.198);
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.server {
|
|
||||||
color: white;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background-color: rgba(0, 0, 0, 0.137);
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.288);
|
|
||||||
}
|
|
||||||
.material-icons {
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
.add-server:hover .material-icons {
|
|
||||||
color: rgba(20, 255, 39, 0.726);
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-view {
|
|
||||||
padding-right: 0;
|
|
||||||
display: flex;
|
|
||||||
transition: 0.3s;
|
|
||||||
position: relative;
|
|
||||||
align-items: center;
|
|
||||||
padding: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.server-name {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
margin-left: 5px;
|
|
||||||
flex: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.add-icon {
|
|
||||||
height: 56px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 5px;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-icon .material-icons {
|
|
||||||
font-size: 40px;
|
|
||||||
}
|
|
||||||
.options-context-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 5px;
|
|
||||||
color: rgba(255, 255, 255, 0.623);
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
.options-context-button .material-icons:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.options-context-menu {
|
|
||||||
position: absolute;
|
|
||||||
background: rgba(0, 0, 0, 0.692);
|
|
||||||
border-radius: 10px;
|
|
||||||
z-index: 9999;
|
|
||||||
padding: 5px;
|
|
||||||
right: 40px;
|
|
||||||
top: 20px;
|
|
||||||
}
|
|
||||||
.menu-button {
|
|
||||||
padding: 5px;
|
|
||||||
margin: 2px;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
.menu-button:hover {
|
|
||||||
background: rgb(47, 47, 47);
|
|
||||||
}
|
|
||||||
|
|
||||||
.warn {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,10 @@ export default {
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.left-panel {
|
.left-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(39, 39, 39, 0.97);
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,80 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="explore-tab">
|
<div class="explore-tab">
|
||||||
|
|
||||||
<transition name="slidein">
|
<transition name="slidein">
|
||||||
<div class="left-panel"
|
<div
|
||||||
|
class="left-panel"
|
||||||
v-show="$mq === 'mobile' && showLeftPanel || ($mq !== 'mobile')"
|
v-show="$mq === 'mobile' && showLeftPanel || ($mq !== 'mobile')"
|
||||||
v-click-outside="hideLeftPanel">
|
v-click-outside="hideLeftPanel"
|
||||||
<div class="header">
|
>
|
||||||
<div class="icon">
|
<navigation />
|
||||||
<i class="material-icons">explore</i>
|
<div class="content">
|
||||||
</div>
|
<div class="header">
|
||||||
<div class="details">
|
<div class="icon">
|
||||||
<div class="title">Explore</div>
|
<i class="material-icons">explore</i>
|
||||||
<div class="description">Find new servers, Emojis and more!</div>
|
</div>
|
||||||
</div>
|
<div class="details">
|
||||||
</div>
|
<div class="title">Explore</div>
|
||||||
<div class="items">
|
<div class="description">Find new servers, Emojis and more!</div>
|
||||||
<div class="item halloween"
|
</div>
|
||||||
v-for="(tab, index) in tabs"
|
|
||||||
:key="index"
|
|
||||||
:class="{selected: selectedTab === index}"
|
|
||||||
@click="selectedTab = index">
|
|
||||||
<i class="material-icons">{{tab.icon}}</i>
|
|
||||||
{{tab.name}}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="items">
|
||||||
|
<div
|
||||||
|
class="item"
|
||||||
|
v-for="(tab, index) in tabs"
|
||||||
|
:key="index"
|
||||||
|
:class="{selected: selectedTab === index}"
|
||||||
|
@click="selectedTab = index"
|
||||||
|
>
|
||||||
|
<i class="material-icons">{{tab.icon}}</i>
|
||||||
|
{{tab.name}}
|
||||||
|
</div>
|
||||||
|
<div class="card self-promo" v-if="nertiviaServerHide !== true && !nertiviaServer">
|
||||||
|
<div class="material-icons close-btn" @click="hideSelfPromo">close</div>
|
||||||
|
<div class="logo" />
|
||||||
|
<div class="title">Join the official Nertivia server</div>
|
||||||
|
<div class="button" @click="joinNertiviaServer">Join</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card halloween" v-if="halloween">
|
<div class="card donate-paypal" v-if="donateHide !== true">
|
||||||
<div class="pumpkin">🎃</div>
|
<div class="material-icons close-btn" @click="hideDonatePaypal">close</div>
|
||||||
<div class="title">Happy Halloween!</div>
|
<div class="material-icons heart">favorite</div>
|
||||||
</div>
|
<div
|
||||||
|
class="title"
|
||||||
<div class="card self-promo" v-if="nertiviaServerHide !== true && !nertiviaServer">
|
>Support Nertivia by donating any amount of money. You will get a supporter badge and more features in the future.</div>
|
||||||
<div class="material-icons close-btn" @click="hideSelfPromo">close</div>
|
<div class="button" @click="donateButton">Donate</div>
|
||||||
<div class="logo"/>
|
</div>
|
||||||
<div class="title">Join the official Nertivia server</div>
|
|
||||||
<div class="button" @click="joinNertiviaServer">Join</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card donate-paypal" v-if="donateHide !== true">
|
|
||||||
<div class="material-icons close-btn" @click="hideDonatePaypal">close</div>
|
|
||||||
<div class="material-icons heart">favorite</div>
|
|
||||||
<div class="title">Support Nertivia by donating any amount of money. You will get a supporter badge and more features in the future.</div>
|
|
||||||
<div class="button" @click="donateButton">Donate With PayPal</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="right-panel">
|
<div class="right-panel">
|
||||||
<div class="header"> <div class="material-icons left-menu-show-button" @click="showLeftPanel = !showLeftPanel">view_list</div> <i class="material-icons">{{tabs[selectedTab].icon}}</i>{{tabs[selectedTab].name}}</div>
|
<div class="header">
|
||||||
|
<div
|
||||||
|
class="material-icons left-menu-show-button"
|
||||||
|
@click="showLeftPanel = !showLeftPanel"
|
||||||
|
>view_list</div>
|
||||||
|
<i class="material-icons">{{tabs[selectedTab].icon}}</i>
|
||||||
|
{{tabs[selectedTab].name}}
|
||||||
|
</div>
|
||||||
<div class="coming-soon" v-if="selectedTab > 0">
|
<div class="coming-soon" v-if="selectedTab > 0">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="material-icons">explore</i>
|
<i class="material-icons">explore</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="text">Coming soon!</div>
|
<div class="text">Coming soon!</div>
|
||||||
</div>
|
</div>
|
||||||
<component :is="tabs[selectedTab].component" />
|
<component :is="tabs[selectedTab].component" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { bus } from "@/main";
|
import { bus } from "@/main";
|
||||||
import Servers from './Explore/servers'
|
import Servers from "./Explore/servers";
|
||||||
import ServerService from '@/services/ServerService'
|
import ServerService from "@/services/ServerService";
|
||||||
|
import Navigation from '@/components/app/Navigation';
|
||||||
export default {
|
export default {
|
||||||
components: { Servers },
|
components: { Servers, Navigation },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showLeftPanel: false,
|
showLeftPanel: false,
|
||||||
|
|
@ -80,11 +86,10 @@ export default {
|
||||||
{ icon: "brush", name: "Themes", component: "" },
|
{ icon: "brush", name: "Themes", component: "" },
|
||||||
{ icon: "message", name: "Message Styles", component: "" }
|
{ icon: "message", name: "Message Styles", component: "" }
|
||||||
],
|
],
|
||||||
nertiviaServerID: '6572915451527958528',
|
nertiviaServerID: "6572915451527958528",
|
||||||
nertiviaServerHide: localStorage.getItem('exploreTabNertiviaServerPromoHide') === 'true',
|
nertiviaServerHide:
|
||||||
donateHide: localStorage.getItem('exploreTabDonateHide') === 'true',
|
localStorage.getItem("exploreTabNertiviaServerPromoHide") === "true",
|
||||||
halloween: new Date().getDate() === 31
|
donateHide: localStorage.getItem("exploreTabDonateHide") === "true",
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -97,27 +102,29 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideSelfPromo() {
|
hideSelfPromo() {
|
||||||
localStorage.setItem('exploreTabNertiviaServerPromoHide', true)
|
localStorage.setItem("exploreTabNertiviaServerPromoHide", true);
|
||||||
this.nertiviaServerHide = true;
|
this.nertiviaServerHide = true;
|
||||||
},
|
},
|
||||||
hideDonatePaypal() {
|
hideDonatePaypal() {
|
||||||
localStorage.setItem('exploreTabDonateHide', true)
|
localStorage.setItem("exploreTabDonateHide", true);
|
||||||
this.donateHide = true;
|
this.donateHide = true;
|
||||||
},
|
},
|
||||||
async joinNertiviaServer() {
|
async joinNertiviaServer() {
|
||||||
const {ok, error, result} = await ServerService.joinServerById(this.nertiviaServerID, {
|
const { ok, error, result } = await ServerService.joinServerById(
|
||||||
socketID: this.$socket.id
|
this.nertiviaServerID,
|
||||||
});
|
{
|
||||||
|
socketID: this.$socket.id
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
donateButton() {
|
donateButton() {
|
||||||
window.open('https://www.patreon.com/nertivia', '_blank');
|
window.open("https://www.patreon.com/nertivia", "_blank");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {},
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
nertiviaServer() {
|
nertiviaServer() {
|
||||||
return this.$store.getters['servers/servers'][this.nertiviaServerID]
|
return this.$store.getters["servers/servers"][this.nertiviaServerID];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -125,26 +132,32 @@ export default {
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
.explore-tab {
|
.explore-tab {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: rgba(0, 0, 0, 0.459);
|
|
||||||
color: white;
|
color: white;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.left-panel {
|
.left-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
background: rgba(0, 0, 0, 0.274);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
width: 300px;
|
width: 300px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.items {
|
.items {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 3px;
|
||||||
|
}
|
||||||
.item {
|
.item {
|
||||||
.material-icons {
|
.material-icons {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
|
@ -152,22 +165,16 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(0, 0, 0, 0.199);
|
|
||||||
margin: 5px;
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.452);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
&.selected {
|
&.selected {
|
||||||
background: rgba(0, 0, 0, 0.452);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.item.halloween.selected {
|
|
||||||
background: rgba(255, 166, 0, 0.692);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -182,19 +189,19 @@ export default {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 100px;
|
width: 70px;
|
||||||
position: relative;
|
position: relative;
|
||||||
.material-icons {
|
.material-icons {
|
||||||
font-size: 70px;
|
font-size: 50px;
|
||||||
}
|
}
|
||||||
&::after{
|
&::after {
|
||||||
content: 'BETA';
|
content: "BETA";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: #ff3333;
|
background: #ff3333;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 10px;
|
font-size: 9px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
bottom: 15px;
|
bottom: 20px;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,28 +235,28 @@ export default {
|
||||||
.title {
|
.title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.button {
|
.button {
|
||||||
background-color: rgba(0, 0, 0, 0.200);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
font-size: 20px;
|
font-size: 15px;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
color: rgba(255, 255, 255, 0.924);
|
color: rgba(255, 255, 255, 0.924);
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.300);
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.close-btn {
|
.close-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
&.self-promo{
|
&.self-promo {
|
||||||
.logo {
|
.logo {
|
||||||
background-image: url('../../../assets/logo.png');
|
background-image: url("../../../assets/logo.png");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
|
|
@ -269,15 +276,6 @@ export default {
|
||||||
font-size: 60px;
|
font-size: 60px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
&.halloween {
|
|
||||||
.pumpkin {
|
|
||||||
font-size: 50px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
background: orange;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.coming-soon {
|
.coming-soon {
|
||||||
|
|
@ -295,13 +293,16 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-panel {
|
.right-panel {
|
||||||
|
background: rgba(0, 0, 0, 0.65);
|
||||||
.header {
|
.header {
|
||||||
background: rgba(0, 0, 0, 0.448);
|
background: rgba(0, 0, 0, 0.448);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
.material-icons {margin-right: 5px;}
|
.material-icons {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +313,6 @@ export default {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.left-menu-show-button {
|
.left-menu-show-button {
|
||||||
border-right: solid 1px rgb(158, 158, 158);
|
border-right: solid 1px rgb(158, 158, 158);
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
|
|
@ -320,14 +320,13 @@ export default {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.slidein-enter-active,
|
.slidein-enter-active,
|
||||||
.slidein-leave-active {
|
.slidein-leave-active {
|
||||||
transition: 0.5s;
|
transition: 0.5s;
|
||||||
}
|
}
|
||||||
.slidein-enter, .slidein-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
.slidein-enter, .slidein-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||||
/* margin-left: -300px; */
|
/* margin-left: -300px; */
|
||||||
transform: translateX(-300px)
|
transform: translateX(-300px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
|
|
@ -336,11 +335,10 @@ export default {
|
||||||
}
|
}
|
||||||
.left-panel {
|
.left-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(39, 39, 39, 0.97);
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: calc(100% - 44px);
|
height: calc(100% - 44px);
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="title">Filter:</div>
|
<div class="title">Filter:</div>
|
||||||
<div class="filter-item">
|
<div class="filter-item">
|
||||||
<div
|
<div
|
||||||
class="item halloween"
|
class="item"
|
||||||
v-for="(filter, index) in filters"
|
v-for="(filter, index) in filters"
|
||||||
:class="{selected: filterSelected === index}"
|
:class="{selected: filterSelected === index}"
|
||||||
:key="filter.name"
|
:key="filter.name"
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<div class="title">Sort By:</div>
|
<div class="title">Sort By:</div>
|
||||||
<div class="filter-item">
|
<div class="filter-item">
|
||||||
<div
|
<div
|
||||||
class="item halloween"
|
class="item"
|
||||||
v-for="(sortBy, index) in sortBys"
|
v-for="(sortBy, index) in sortBys"
|
||||||
:class="{selected: sortSelected === index}"
|
:class="{selected: sortSelected === index}"
|
||||||
:key="sortBy.name"
|
:key="sortBy.name"
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-area">
|
<div class="search-area" v-if="false">
|
||||||
<input type="text" :placeholder="`Search for ${name}`" />
|
<input type="text" :placeholder="`Search for ${name}`" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -136,9 +136,6 @@ input {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.item.halloween.selected {
|
|
||||||
color: orange;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
|
<div class="background-dark"></div>
|
||||||
<profile-picture
|
<profile-picture
|
||||||
size="90px"
|
size="90px"
|
||||||
:url="`${avatarDomain}/${server.server.avatar}`"
|
:url="`${avatarDomain}/${server.server.avatar}`"
|
||||||
|
|
@ -8,7 +9,7 @@
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<div class="name-container">
|
<div class="name-container">
|
||||||
<span class="inner-name">{{server.server.name}}</span>
|
<span class="inner-name">{{server.server.name}}</span>
|
||||||
<span class="material-icons halloween-icons" v-if="server.verified">check</span>
|
<span class="material-icons" v-if="server.verified">check</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -16,7 +17,7 @@
|
||||||
<div class="description">{{server.description}}</div>
|
<div class="description">{{server.description}}</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<div class="member-count"><div class="material-icons">account_box</div>{{server.total_members}}</div>
|
<div class="member-count"><div class="material-icons">account_box</div>{{server.total_members}}</div>
|
||||||
<div class="button halloween-button" :class="{selected: joined}" @click="joinButton">
|
<div class="button" :class="{selected: joined}" @click="joinButton">
|
||||||
<span v-if="joined">Joined</span>
|
<span v-if="joined">Joined</span>
|
||||||
<spinner v-else-if="joinClicked" :size="30"/>
|
<spinner v-else-if="joinClicked" :size="30"/>
|
||||||
<span v-else-if="!joinClicked">Join Server</span>
|
<span v-else-if="!joinClicked">Join Server</span>
|
||||||
|
|
@ -70,6 +71,7 @@ export default {
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.item {
|
.item {
|
||||||
|
position: relative;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
background: rgba(0, 0, 0, 0.479);
|
background: rgba(0, 0, 0, 0.479);
|
||||||
|
|
@ -94,6 +96,18 @@ export default {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
.background-dark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
background-image: url('../../../../assets/background.jpg');
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
.avatar {
|
.avatar {
|
||||||
background: rgb(26, 133, 255);
|
background: rgb(26, 133, 255);
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
|
@ -110,6 +124,7 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
z-index: 999;
|
||||||
.name-container {
|
.name-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
@ -123,18 +138,16 @@ export default {
|
||||||
color: #66e0ff;
|
color: #66e0ff;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
.halloween-icons {
|
|
||||||
color: orange;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.bottom {
|
.bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: rgba(0, 0, 0, 0.194);
|
background: rgba(0, 0, 0, 0.541);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -146,6 +159,7 @@ export default {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -187,15 +201,7 @@ export default {
|
||||||
background: grey;
|
background: grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.halloween-button {
|
|
||||||
background: rgba(255, 166, 0, 0.8);
|
|
||||||
&:hover {
|
|
||||||
background: rgb(255, 166, 0);
|
|
||||||
}
|
|
||||||
&.selected {
|
|
||||||
background: grey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,62 +1,42 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="news">
|
<div class="news">
|
||||||
<div class="change-log">
|
<navigation />
|
||||||
<span class="news-title">Changes in this release</span>
|
<div class="changelog">
|
||||||
|
<div class="change-log">
|
||||||
|
<span class="news-title">Changes in this release</span>
|
||||||
|
|
||||||
<div
|
<div v-for="(change, index) in changelog" :key="index" class="change">
|
||||||
v-for="(change, index) in changelog"
|
|
||||||
:key="index"
|
|
||||||
class="change"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="heading"
|
|
||||||
:style="change.headColor ? `background-color: ${change.headColor}` : ``"
|
|
||||||
>
|
|
||||||
<div class="date">
|
|
||||||
{{ change.date }}
|
|
||||||
</div>
|
|
||||||
<div class="changes-title">
|
|
||||||
{{ change.title }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="information">
|
|
||||||
<div v-if="change.new">
|
|
||||||
<strong>What's new?</strong>
|
|
||||||
<br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wnew, index) in change.new"
|
|
||||||
:key="index"
|
|
||||||
v-html="wnew"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="change.fix">
|
|
||||||
<strong>Issues fixed</strong>
|
|
||||||
<br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wfix, index) in change.fix"
|
|
||||||
:key="index"
|
|
||||||
v-html="wfix"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-if="change.next">
|
|
||||||
<strong>Up next</strong>
|
|
||||||
<br>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(wnext, index) in change.next"
|
|
||||||
:key="index"
|
|
||||||
v-html="wnext"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="change.msg"
|
class="heading"
|
||||||
v-html="change.msg"
|
:style="change.headColor ? `background-color: ${change.headColor}` : ``"
|
||||||
/>
|
>
|
||||||
|
<div class="date">{{ change.date }}</div>
|
||||||
|
<div class="changes-title">{{ change.title }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="information">
|
||||||
|
<div v-if="change.new">
|
||||||
|
<strong>What's new?</strong>
|
||||||
|
<br />
|
||||||
|
<ul>
|
||||||
|
<li v-for="(wnew, index) in change.new" :key="index" v-html="wnew" />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div v-if="change.fix">
|
||||||
|
<strong>Issues fixed</strong>
|
||||||
|
<br />
|
||||||
|
<ul>
|
||||||
|
<li v-for="(wfix, index) in change.fix" :key="index" v-html="wfix" />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div v-if="change.next">
|
||||||
|
<strong>Up next</strong>
|
||||||
|
<br />
|
||||||
|
<ul>
|
||||||
|
<li v-for="(wnext, index) in change.next" :key="index" v-html="wnext" />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div v-if="change.msg" v-html="change.msg" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -65,12 +45,13 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Spinner from "@/components/Spinner.vue";
|
import Spinner from "@/components/Spinner.vue";
|
||||||
|
import Navigation from "@/components/app/Navigation";
|
||||||
import changelog from "@/utils/changelog.js";
|
import changelog from "@/utils/changelog.js";
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: { Navigation },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
changelog: changelog
|
changelog
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -84,16 +65,19 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: white;
|
color: white;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: rgba(0, 0, 0, 0.486);
|
background: #0000005d;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.news-title {
|
.news-title {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: 20px;
|
margin-left: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 21px;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
border-bottom: solid 1px white;
|
|
||||||
}
|
}
|
||||||
.todo-list {
|
.todo-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -102,29 +86,35 @@ export default {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
.change {
|
.change {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
border-bottom: solid 1px white;
|
|
||||||
}
|
}
|
||||||
.heading{
|
.heading {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: rgba(0, 0, 0, 0.555);
|
background: rgba(0, 0, 0, 0.555);
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
border-radius: 10px;
|
|
||||||
}
|
}
|
||||||
.information {
|
.information {
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
margin: 10px;
|
||||||
}
|
}
|
||||||
.heading.latest {
|
.heading.latest {
|
||||||
background: rgba(38, 139, 255, 0.87);
|
background: rgba(38, 139, 255, 0.87);
|
||||||
}
|
}
|
||||||
.change-log {
|
.change-log {
|
||||||
background: rgba(0, 0, 0, 0.137);
|
background: rgba(0, 0, 0, 0.561);
|
||||||
padding: 20px;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
.changelog {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
}
|
||||||
.plan-list {
|
.plan-list {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
@ -142,5 +132,4 @@ export default {
|
||||||
margin-top: -5px;
|
margin-top: -5px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -103,21 +103,21 @@ export default {
|
||||||
@media (max-width: 949px) {
|
@media (max-width: 949px) {
|
||||||
.members-panel {
|
.members-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(39, 39, 39, 0.97);
|
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.left-panel {
|
.left-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(39, 39, 39, 0.97);
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="add-friend-panel">
|
|
||||||
<div
|
|
||||||
class="panel-title"
|
|
||||||
@click="expanded = !expanded"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<i
|
|
||||||
v-if="!expanded"
|
|
||||||
class="material-icons"
|
|
||||||
>
|
|
||||||
person_add
|
|
||||||
</i>
|
|
||||||
<span>{{ expanded ? "Hide" : "Add friend" }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<transition
|
|
||||||
name="slide"
|
|
||||||
appear
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="expanded"
|
|
||||||
class="add-friend"
|
|
||||||
>
|
|
||||||
<div class="title">
|
|
||||||
Add friend
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
Type in your friends username and tag. eg: someone@jt4g
|
|
||||||
</div>
|
|
||||||
<div class="infoC">
|
|
||||||
Creators tag: Fishie@azK0
|
|
||||||
</div>
|
|
||||||
<form
|
|
||||||
action="#"
|
|
||||||
@submit.prevent="addFriend"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-model="input"
|
|
||||||
type="text"
|
|
||||||
placeholder="username@tag"
|
|
||||||
>
|
|
||||||
<loadingButton
|
|
||||||
:loading="currentButtonMessage == 1"
|
|
||||||
:message="buttonMessages[currentButtonMessage]"
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
<div :class="{message: true, warning: errorMessage.isError}">
|
|
||||||
{{ errorMessage.message }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import RelationshipService from '@/services/RelationshipService.js'
|
|
||||||
import loadingButton from './../../Button.vue'
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
loadingButton
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
expanded: false,
|
|
||||||
buttonMessages: [
|
|
||||||
"Add Friend",
|
|
||||||
"Adding..."
|
|
||||||
],
|
|
||||||
currentButtonMessage: 0,
|
|
||||||
input: "",
|
|
||||||
errorMessage:{
|
|
||||||
message: "",
|
|
||||||
isError: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async addFriend() {
|
|
||||||
this.$set(this.errorMessage, 'message', "")
|
|
||||||
|
|
||||||
this.currentButtonMessage = 1;
|
|
||||||
const split = this.input.trim().split("@");
|
|
||||||
|
|
||||||
// validation
|
|
||||||
if ( split.length <2 || split.length >2 || split[1] === "" || split[1].length !== 4){
|
|
||||||
this.$set(this.errorMessage, 'message', "Invalid username or tag.")
|
|
||||||
this.$set(this.errorMessage, 'isError', true)
|
|
||||||
this.currentButtonMessage = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const username = split[0];
|
|
||||||
const tag = split[1];
|
|
||||||
|
|
||||||
const {ok, error, result} = await RelationshipService.post({username, tag})
|
|
||||||
this.currentButtonMessage = 0;
|
|
||||||
if ( ok ) {
|
|
||||||
this.$set(this.errorMessage, 'message', result.data.message)
|
|
||||||
this.$set(this.errorMessage, 'isError', false)
|
|
||||||
} else {
|
|
||||||
if (error.response === undefined) {
|
|
||||||
this.$set(this.errorMessage, 'message', "Can't connect to server.")
|
|
||||||
this.$set(this.errorMessage, 'isError', true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$set(this.errorMessage, 'message', error.response.data.errors[0].msg)
|
|
||||||
this.$set(this.errorMessage, 'isError', true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.slide-enter-active, .slide-leave-active {
|
|
||||||
transition: .3s;
|
|
||||||
}
|
|
||||||
.slide-enter, .slide-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
|
||||||
margin-bottom: -250px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-friend-panel{
|
|
||||||
width: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.123);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-friend{
|
|
||||||
background: rgba(0, 0, 0, 0);
|
|
||||||
flex: 1;
|
|
||||||
height: 230px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
color: white;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
.title{
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
font-size: 20px;
|
|
||||||
color: white;
|
|
||||||
user-select: none;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.info{
|
|
||||||
text-align: center;
|
|
||||||
color: rgb(182, 182, 182);
|
|
||||||
font-size: 15px;
|
|
||||||
user-select: none;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.infoC{
|
|
||||||
text-align: center;
|
|
||||||
color: rgb(255, 79, 79);
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
form {
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message{
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 2px;
|
|
||||||
font-size: 15px;
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
.warning {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
.panel-title{
|
|
||||||
background: rgba(0, 0, 0, 0.274);
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
display: flex;
|
|
||||||
transition: 0.3s;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.panel-title:hover{
|
|
||||||
background: rgba(0, 0, 0, 0.445);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-title .material-icons{
|
|
||||||
vertical-align: top;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
.panel-title span{
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
.panel-title div{
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="{friend: true, notifyAnimation: (notifications && notifications > 0) }"
|
class="friend"
|
||||||
:style="{background: status.status !== 0 ? status.bgColor : ''}"
|
:style="{background: status.status !== 0 ? status.bgColor : ''}"
|
||||||
|
:class="{selected: uniqueIDSelected, notifyAnimation: (notifications && notifications > 0) }"
|
||||||
@click="openChat"
|
@click="openChat"
|
||||||
@mouseover="hover = true"
|
@mouseover="hover = true"
|
||||||
@mouseleave="hover = false"
|
@mouseleave="hover = false"
|
||||||
|
|
@ -80,6 +81,9 @@ export default {
|
||||||
statusColor: statuses[parseInt(status)].color,
|
statusColor: statuses[parseInt(status)].color,
|
||||||
bgColor: statuses[parseInt(status)].bgColor
|
bgColor: statuses[parseInt(status)].bgColor
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
uniqueIDSelected() {
|
||||||
|
return this.$store.getters.selectedUserUniqueID === this.recipient.uniqueID
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -108,20 +112,18 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.username{
|
.username{
|
||||||
width: 201px;
|
width: 150px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
.friend {
|
.friend {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: rgba(0, 0, 0, 0.100);
|
|
||||||
margin: 5px;
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
padding-right: 0;
|
padding-left: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -151,9 +153,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.friend:hover {
|
.friend:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.246);
|
background: rgba(0, 0, 0, 0.3) !important;
|
||||||
|
}
|
||||||
|
.friend.selected {
|
||||||
|
background: rgba(0, 0, 0, 0.4) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-picture{
|
.profile-picture{
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,12 @@ export default {
|
||||||
|
|
||||||
.friends{
|
.friends{
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
margin: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab{
|
.tab{
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab:hover{
|
.tab:hover{
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,11 @@ export default {
|
||||||
|
|
||||||
.friends{
|
.friends{
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
margin: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab{
|
.tab{
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab:hover{
|
.tab:hover{
|
||||||
|
|
|
||||||
|
|
@ -84,14 +84,12 @@ export default {
|
||||||
|
|
||||||
.recents{
|
.recents{
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
margin: 5px;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab{
|
.tab{
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
}
|
||||||
.tab:hover{
|
.tab:hover{
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export default {
|
||||||
.tab{
|
.tab{
|
||||||
display: flex;
|
display: flex;
|
||||||
color: white;
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.tab-name {
|
.tab-name {
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,16 @@ export default {
|
||||||
|
|
||||||
.status-popout{
|
.status-popout{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(26, 26, 26, 0.863);
|
bottom: 55px;
|
||||||
border-radius: 10px;
|
left: 30px;
|
||||||
padding: 5px;
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
width: 180px;
|
width: 180px;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
.status-list {
|
.status-list {
|
||||||
padding: 5px;
|
padding: 10px;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
border-radius: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
|
|
@ -86,7 +85,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-list:hover {
|
.status-list:hover {
|
||||||
background: rgba(0, 0, 0, 0.349);
|
background: rgba(46, 46, 46, 0.651);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-icon{
|
.status-icon{
|
||||||
|
|
|
||||||
|
|
@ -32,16 +32,22 @@ export const store = new Vuex.Store({
|
||||||
members: membersModule
|
members: membersModule
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
|
currentTab: 0,
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
currentTab(state) {
|
||||||
},
|
return state.currentTab;
|
||||||
mutations: {
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
setCurrentTab({commit}, currentTab) {
|
||||||
}
|
localStorage.setItem("currentTab", currentTab);
|
||||||
|
commit('SET_CURRENT_TAB', currentTab)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
SET_CURRENT_TAB(state, currentTab) {
|
||||||
|
state.currentTab = currentTab;
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -4,6 +4,7 @@ import Vue from "vue";
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
selectedChannelID: null,
|
selectedChannelID: null,
|
||||||
|
selectedUserUniqueID: null,
|
||||||
DMChannelID: null,
|
DMChannelID: null,
|
||||||
serverChannelID: null,
|
serverChannelID: null,
|
||||||
channelName: null,
|
channelName: null,
|
||||||
|
|
@ -14,6 +15,9 @@ const getters = {
|
||||||
selectedChannelID(state) {
|
selectedChannelID(state) {
|
||||||
return state.selectedChannelID;
|
return state.selectedChannelID;
|
||||||
},
|
},
|
||||||
|
selectedUserUniqueID(state) {
|
||||||
|
return state.selectedUserUniqueID;
|
||||||
|
},
|
||||||
channels(state) {
|
channels(state) {
|
||||||
return state.channels;
|
return state.channels;
|
||||||
},
|
},
|
||||||
|
|
@ -43,6 +47,9 @@ const actions = {
|
||||||
selectedChannelID(context, channelID) {
|
selectedChannelID(context, channelID) {
|
||||||
context.commit("selectedChannelID", channelID);
|
context.commit("selectedChannelID", channelID);
|
||||||
},
|
},
|
||||||
|
selectedUserUniqueID(context, uniqueID) {
|
||||||
|
context.commit("selectedUserUniqueID", uniqueID);
|
||||||
|
},
|
||||||
setChannelName(context, name) {
|
setChannelName(context, name) {
|
||||||
context.commit("setChannelName", name);
|
context.commit("setChannelName", name);
|
||||||
},
|
},
|
||||||
|
|
@ -74,6 +81,9 @@ const mutations = {
|
||||||
selectedChannelID(state, channelID) {
|
selectedChannelID(state, channelID) {
|
||||||
state.selectedChannelID = channelID;
|
state.selectedChannelID = channelID;
|
||||||
},
|
},
|
||||||
|
selectedUserUniqueID(state, uniqueID) {
|
||||||
|
state.selectedUserUniqueID = uniqueID;
|
||||||
|
},
|
||||||
setDMChannelID(state, channelID) {
|
setDMChannelID(state, channelID) {
|
||||||
state.DMChannelID = channelID;
|
state.DMChannelID = channelID;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ const getters = {
|
||||||
const actions = {
|
const actions = {
|
||||||
// server channel
|
// server channel
|
||||||
async openChannel(context, channel) {
|
async openChannel(context, channel) {
|
||||||
|
context.commit("selectedChannelID", channel.channelID)
|
||||||
context.commit("setChannelName", channel.name);
|
context.commit("setChannelName", channel.name);
|
||||||
const messages = context.state.messages[channel.channelID];
|
const messages = context.state.messages[channel.channelID];
|
||||||
if (messages) {
|
if (messages) {
|
||||||
|
|
@ -32,14 +33,12 @@ const actions = {
|
||||||
context.commit("setServerChannelID", channel.channelID);
|
context.commit("setServerChannelID", channel.channelID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.commit("selectedChannelID", "loading")
|
|
||||||
getMessages(context, channel.channelID, true);
|
getMessages(context, channel.channelID, true);
|
||||||
|
|
||||||
},
|
},
|
||||||
//dm channel
|
//dm channel
|
||||||
async openChat(context, { uniqueID, channelID, channelName }) {
|
async openChat(context, { uniqueID, channelID, channelName }) {
|
||||||
if (channelName) context.commit("setChannelName", channelName);
|
if (channelName) context.commit("setChannelName", channelName);
|
||||||
|
|
||||||
const channels = context.rootState.channelModule.channels;
|
const channels = context.rootState.channelModule.channels;
|
||||||
channelID = Object.keys(channels).find(_channelID => {
|
channelID = Object.keys(channels).find(_channelID => {
|
||||||
return channels[_channelID].recipients && channels[_channelID].recipients.length && channels[_channelID].recipients[0].uniqueID === uniqueID
|
return channels[_channelID].recipients && channels[_channelID].recipients.length && channels[_channelID].recipients[0].uniqueID === uniqueID
|
||||||
|
|
@ -47,6 +46,7 @@ const actions = {
|
||||||
const messages = context.state.messages[channelID];
|
const messages = context.state.messages[channelID];
|
||||||
const channel = channels[channelID];
|
const channel = channels[channelID];
|
||||||
|
|
||||||
|
context.commit('selectedUserUniqueID', uniqueID);
|
||||||
if (channelID) {
|
if (channelID) {
|
||||||
context.commit("setDMChannelID", channelID);
|
context.commit("setDMChannelID", channelID);
|
||||||
context.commit("selectedChannelID", channelID);
|
context.commit("selectedChannelID", channelID);
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,18 @@ const state = {
|
||||||
uniqueID: null,
|
uniqueID: null,
|
||||||
x: null,
|
x: null,
|
||||||
y: null
|
y: null
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// TODO: convert all above into one.
|
||||||
|
allPopout: {
|
||||||
|
show: false,
|
||||||
|
type: null,
|
||||||
|
serverID: null,
|
||||||
|
uniqueID: null,
|
||||||
|
creatorUniqueID: null,
|
||||||
|
x: null,
|
||||||
|
y: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +65,9 @@ const getters = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
setAllPopout({commit, state}, data) {
|
||||||
|
commit('setAllPopout', {...state.allPopout, ...data})
|
||||||
|
},
|
||||||
setServerSettings({commit}, {serverID, index}){
|
setServerSettings({commit}, {serverID, index}){
|
||||||
commit('setServerSettings', {serverID, index})
|
commit('setServerSettings', {serverID, index})
|
||||||
},
|
},
|
||||||
|
|
@ -87,6 +101,9 @@ const actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
|
setAllPopout(state, data) {
|
||||||
|
Vue.set(state, 'allPopout', data)
|
||||||
|
},
|
||||||
setServerMemberContext(state, data) {
|
setServerMemberContext(state, data) {
|
||||||
Vue.set(state, 'serverMemberContext', data);
|
Vue.set(state, 'serverMemberContext', data);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ const actions = {
|
||||||
},
|
},
|
||||||
updateNotification(context, data) {
|
updateNotification(context, data) {
|
||||||
let notificationSettings = JSON.parse(localStorage.getItem('notificationSettings')) || {};
|
let notificationSettings = JSON.parse(localStorage.getItem('notificationSettings')) || {};
|
||||||
Object.assign(notificationSettings, data);
|
const assigned = Object.assign({}, notificationSettings, data);
|
||||||
localStorage.setItem("notificationSettings", JSON.stringify(notificationSettings));
|
localStorage.setItem("notificationSettings", JSON.stringify(assigned));
|
||||||
context.commit('updateNotification', notificationSettings)
|
context.commit('updateNotification', assigned)
|
||||||
},
|
},
|
||||||
addRecentEmoji(context, shortcode) {
|
addRecentEmoji(context, shortcode) {
|
||||||
const recentEmojis = JSON.parse(localStorage.getItem('recentEmojis')) || [];
|
const recentEmojis = JSON.parse(localStorage.getItem('recentEmojis')) || [];
|
||||||
|
|
|
||||||
|
|
@ -270,13 +270,18 @@ const actions = {
|
||||||
if (!server.socketID) return;
|
if (!server.socketID) return;
|
||||||
if (this._vm.$socket.id !== server.socketID) return;
|
if (this._vm.$socket.id !== server.socketID) return;
|
||||||
const defaultChannel = channels.find(c => c.channelID === server.default_channel_id)
|
const defaultChannel = channels.find(c => c.channelID === server.default_channel_id)
|
||||||
bus.$emit('changeTab', 2)
|
context.dispatch('setCurrentTab', 2, {root: true})
|
||||||
context.dispatch('servers/setSelectedServerID', server.server_id, {root: true})
|
context.dispatch('servers/setSelectedServerID', server.server_id, {root: true})
|
||||||
context.dispatch('openChannel', defaultChannel, {root: true})
|
context.dispatch('openChannel', defaultChannel, {root: true})
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
['socket_server:leave'](context, {server_id}) {
|
['socket_server:leave'](context, {server_id}) {
|
||||||
|
const lastSelectedChannel = JSON.parse(localStorage.getItem('selectedChannels') || '{}')
|
||||||
|
if (lastSelectedChannel[server_id]) {
|
||||||
|
delete lastSelectedChannel[server_id];
|
||||||
|
localStorage.setItem('selectedChannels', JSON.stringify(lastSelectedChannel));
|
||||||
|
}
|
||||||
// check if server channel selected
|
// check if server channel selected
|
||||||
const serverChannelIDs = context.rootState.servers.channelsIDs[server_id];
|
const serverChannelIDs = context.rootState.servers.channelsIDs[server_id];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,25 @@
|
||||||
|
|
||||||
const config = [
|
const config = [
|
||||||
|
|
||||||
|
{
|
||||||
|
version: 7.8,
|
||||||
|
title: "Redesigns!",
|
||||||
|
shortTitle: "",
|
||||||
|
date: "25/10/2019",
|
||||||
|
headColor: "rgba(25, 130, 255, 0.77)",
|
||||||
|
new: [
|
||||||
|
'Layout has been redesigned.',
|
||||||
|
'Added an option to mute notification sounds.',
|
||||||
|
'Last clicked channels should be remembered for each server.',
|
||||||
|
'You can now delete Join, Left and Ban messages from the chat.',
|
||||||
|
],
|
||||||
|
next: ['Custom server banners.'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: 7.6,
|
version: 7.6,
|
||||||
title: "👻Spooky bug fixes👻",
|
title: "👻Spooky bug fixes👻",
|
||||||
shortTitle: "",
|
shortTitle: "",
|
||||||
date: "16/10/2019",
|
date: "16/10/2019",
|
||||||
headColor: "rgb(255, 166, 0)", // halloween
|
|
||||||
//headColor: "rgba(25, 130, 255, 0.77)",
|
|
||||||
new: [
|
new: [
|
||||||
'Better handled Google Drive linking.',
|
'Better handled Google Drive linking.',
|
||||||
'👻👻👻',
|
'👻👻👻',
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ function replace_custom_emoji(state, silent) {
|
||||||
// console.log(nameEnd, parseUntil(state,nameStart,58))
|
// console.log(nameEnd, parseUntil(state,nameStart,58))
|
||||||
|
|
||||||
// parser failed to find another ':', so it's not a valid emoji
|
// parser failed to find another ':', so it's not a valid emoji
|
||||||
if(nameEnd > max || nameEnd < 0 || nameEnd - nameStart <= 0) { return false; }
|
if((nameEnd+1) > max || nameEnd < 0 || nameEnd - nameStart <= 0) { return false; }
|
||||||
|
|
||||||
let emojiName = state.src.slice(nameStart, nameEnd)
|
let emojiName = state.src.slice(nameStart, nameEnd)
|
||||||
|
|
||||||
|
|
@ -79,7 +79,9 @@ function replace_custom_emoji(state, silent) {
|
||||||
let idStart = pos
|
let idStart = pos
|
||||||
let idEnd = skipUntil(state, pos, 62);
|
let idEnd = skipUntil(state, pos, 62);
|
||||||
|
|
||||||
if(idEnd > max || idEnd < 0 || idEnd - idStart <= 1) { return false; }
|
if((idEnd+1) > max || idEnd < 0 || idEnd - idStart <= 1) { return false; }
|
||||||
|
|
||||||
|
// console.log(idStart, idEnd)
|
||||||
|
|
||||||
let emojiID = state.src.slice(idStart, idEnd)
|
let emojiID = state.src.slice(idStart, idEnd)
|
||||||
|
|
||||||
|
|
@ -88,7 +90,7 @@ function replace_custom_emoji(state, silent) {
|
||||||
state.posMax = idEnd
|
state.posMax = idEnd
|
||||||
|
|
||||||
let token = state.push('custom_emoji', 'img', 0);
|
let token = state.push('custom_emoji', 'img', 0);
|
||||||
token.attrs = [[ 'src', `${config.domain}/media/${emojiID}` ], [ 'alt', emojiName ]]
|
token.attrs = [[ 'src', (`${config.domain}/media/${emojiID}`) ], [ 'alt', (emojiName) ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
state.pos = idEnd + 1
|
state.pos = idEnd + 1
|
||||||
|
|
@ -96,14 +98,17 @@ function replace_custom_emoji(state, silent) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emojiRe = /<:[\w\d]+:[\w\d]+>/
|
||||||
|
|
||||||
export default function custom_emoji_plugin(md, opts) {
|
export default function custom_emoji_plugin(md, opts) {
|
||||||
md.renderer.rules.custom_emoji = (tokens, idx) => {
|
md.renderer.rules.custom_emoji = (tokens, idx) => {
|
||||||
let token = tokens[idx]
|
let token = tokens[idx]
|
||||||
|
|
||||||
|
const srcIdx = token.attrIndex('src');
|
||||||
|
const altIdx = token.attrIndex('alt');
|
||||||
|
|
||||||
// todo: better escaping method,
|
let src = encodeURI(md.utils.escapeHtml(token.attrs[srcIdx][1]))
|
||||||
// even if this is good and covers most cases, there may be edge cases where DOMPurify may be better
|
let alt = md.utils.escapeHtml(token.attrs[altIdx][1])
|
||||||
let src = md.utils.escapeHtml(token.attrs.find(([name]) => name === 'src')[1])
|
|
||||||
let alt = md.utils.escapeHtml(token.attrs.find(([name]) => name === 'alt')[1])
|
|
||||||
|
|
||||||
return `<${md.utils.escapeHtml(token.tag)} class="emoji" title=${alt} alt=${alt} src=${src} />`
|
return `<${md.utils.escapeHtml(token.tag)} class="emoji" title=${alt} alt=${alt} src=${src} />`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
83
src/utils/markdown-it-plugins/normalizeFence.js
Normal file
83
src/utils/markdown-it-plugins/normalizeFence.js
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
function fence(state, startLine, endLine, silent) {
|
||||||
|
var marker, len, params, nextLine, mem, token, markup,
|
||||||
|
haveEndMarker = false,
|
||||||
|
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||||||
|
max = state.eMarks[startLine];
|
||||||
|
|
||||||
|
// if it's indented more than 3 spaces, it should be a code block
|
||||||
|
// if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||||||
|
|
||||||
|
if (pos + 3 > max) { return false; }
|
||||||
|
|
||||||
|
marker = state.src.charCodeAt(pos);
|
||||||
|
|
||||||
|
if (marker !== 0x60 /* ` */) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan marker length
|
||||||
|
mem = pos;
|
||||||
|
pos = state.skipChars(pos, marker);
|
||||||
|
|
||||||
|
len = pos - mem;
|
||||||
|
|
||||||
|
if (len < 3) { return false; }
|
||||||
|
|
||||||
|
markup = state.src.slice(mem, pos);
|
||||||
|
params = state.src.slice(pos, max);
|
||||||
|
|
||||||
|
if (marker === 0x60 /* ` */) {
|
||||||
|
if (params.indexOf(String.fromCharCode(marker)) >= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since start is found, we can report success here in validation mode
|
||||||
|
if (silent) { return true; }
|
||||||
|
|
||||||
|
// search end of block
|
||||||
|
nextLine = startLine;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
nextLine++;
|
||||||
|
if (nextLine >= endLine) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];
|
||||||
|
max = state.eMarks[nextLine];
|
||||||
|
|
||||||
|
if (state.src.charCodeAt(pos) !== marker) { continue; }
|
||||||
|
|
||||||
|
pos = state.skipChars(pos, marker);
|
||||||
|
|
||||||
|
// closing code fence must be at least as long as the opening one
|
||||||
|
if (pos - mem < len) { continue; }
|
||||||
|
|
||||||
|
// make sure tail has spaces only
|
||||||
|
pos = state.skipSpaces(pos);
|
||||||
|
|
||||||
|
if (pos < max) { continue; }
|
||||||
|
|
||||||
|
haveEndMarker = true;
|
||||||
|
// found!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a fence has heading spaces, they should be removed from its inner block
|
||||||
|
len = state.sCount[startLine];
|
||||||
|
|
||||||
|
state.line = nextLine + (haveEndMarker ? 1 : 0);
|
||||||
|
|
||||||
|
token = state.push('fence', 'code', 0);
|
||||||
|
token.info = params;
|
||||||
|
token.content = state.getLines(startLine + 1, nextLine, len, true);
|
||||||
|
token.markup = markup;
|
||||||
|
token.map = [ startLine, state.line ];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function normalizeFence(md, opts) {
|
||||||
|
md.block.ruler.at('fence', fence)
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import config from "@/config.js";
|
||||||
import customEmoji from './markdown-it-plugins/customEmoji'
|
import customEmoji from './markdown-it-plugins/customEmoji'
|
||||||
import formatLink from './markdown-it-plugins/formatLink'
|
import formatLink from './markdown-it-plugins/formatLink'
|
||||||
import formatCode from './markdown-it-plugins/formatCode'
|
import formatCode from './markdown-it-plugins/formatCode'
|
||||||
|
import normalizeFence from './markdown-it-plugins/normalizeFence'
|
||||||
|
|
||||||
import hljs from 'highlight.js'
|
import hljs from 'highlight.js'
|
||||||
|
|
||||||
|
|
@ -25,7 +26,9 @@ const markdown = new MarkdownIt({
|
||||||
|
|
||||||
return '<div class="codeblock"><code>' + markdown.utils.escapeHtml(str) + '</code></div>';
|
return '<div class="codeblock"><code>' + markdown.utils.escapeHtml(str) + '</code></div>';
|
||||||
}
|
}
|
||||||
}).use(chatPlugin)
|
})
|
||||||
|
.use(normalizeFence)
|
||||||
|
.use(chatPlugin)
|
||||||
.use(customEmoji)
|
.use(customEmoji)
|
||||||
.use(formatLink)
|
.use(formatLink)
|
||||||
.use(formatCode);
|
.use(formatCode);
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ const newFriendAudio = new Audio(newFriendSound);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
notification: () => {
|
notification: () => {
|
||||||
if (isBusy()) return;
|
if (isBusy() || isNotificationDisabled()) return;
|
||||||
const audio = new Audio(notificationSound);
|
const audio = new Audio(notificationSound);
|
||||||
audio.play();
|
audio.play();
|
||||||
},
|
},
|
||||||
newFriend: () => {
|
newFriend: () => {
|
||||||
if (isBusy()) return;
|
if (isBusy() || isNotificationDisabled()) return;
|
||||||
const audio = new Audio(newFriendSound);
|
const audio = new Audio(newFriendSound);
|
||||||
audio.play();
|
audio.play();
|
||||||
}
|
}
|
||||||
|
|
@ -25,4 +25,7 @@ export default {
|
||||||
|
|
||||||
function isBusy(){
|
function isBusy(){
|
||||||
return store.getters.user.status == 3
|
return store.getters.user.status == 3
|
||||||
|
}
|
||||||
|
function isNotificationDisabled(){
|
||||||
|
return !!store.getters['settingsModule/settings'].notification.disableNotificationSound;
|
||||||
}
|
}
|
||||||
29
src/utils/simpleMarkdownRules/CustomEmoji.js
Normal file
29
src/utils/simpleMarkdownRules/CustomEmoji.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import SimpleMarkdown from 'simple-markdown';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Specify the order in which this rule is to be run
|
||||||
|
// This rule doesn't conflict with much else, so it should be fine to just put it before the
|
||||||
|
// general-case text rule:
|
||||||
|
order: SimpleMarkdown.defaultRules.text.order - 0.5,
|
||||||
|
|
||||||
|
// First we check whether a string matches
|
||||||
|
match: function(source) {
|
||||||
|
// // || followed by any character repeated [\s\S]+? followed by ||
|
||||||
|
// // Also see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions for more info on regexes
|
||||||
|
return /^\<\:([\S]+?)\:([\S]+?)>/.exec(source);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Then parse this string into a syntax node
|
||||||
|
parse: function(capture, parse, state) {
|
||||||
|
return {
|
||||||
|
// capture[1] is the parenthesis group from the regex in `match`:
|
||||||
|
name: parse(capture[1], state),
|
||||||
|
id: parse(capture[2], state)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Finally transform this syntax node into an html element:
|
||||||
|
html: function(node, output, state) {
|
||||||
|
return '<img class="emoji" title="' + output(node.name, state) + '" alt="' + output(node.name, state) + '" src="https://supertiger.tk/api/media/' + output(node.id, state) + '">'
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/utils/simpleMarkdownRules/linkify.js
Normal file
29
src/utils/simpleMarkdownRules/linkify.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import SimpleMarkdown from 'simple-markdown';
|
||||||
|
import linkify from 'linkify-it'
|
||||||
|
const linkifyInstance = linkify();
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Specify the order in which this rule is to be run
|
||||||
|
// This rule doesn't conflict with much else, so it should be fine to just put it before the
|
||||||
|
// general-case text rule:
|
||||||
|
order: SimpleMarkdown.defaultRules.link - 0.5,
|
||||||
|
|
||||||
|
// First we check whether a string matches
|
||||||
|
match: function(source) {
|
||||||
|
return linkifyInstance.match(source)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Then parse this string into a syntax node
|
||||||
|
parse: function(capture, parse, state) {
|
||||||
|
console.log(capture)
|
||||||
|
return {
|
||||||
|
content: parse(capture[0], state),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Finally transform this syntax node into an html element:
|
||||||
|
html: function(node, output, state) {
|
||||||
|
return 'owo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,42 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app" ref="app">
|
<div id="app" ref="app">
|
||||||
<vue-headful :title="title" description="Nertivia Chat Client"/>
|
<vue-headful :title="title" description="Nertivia Chat Client"/>
|
||||||
<div class="background-image halloween-background"></div>
|
<div class="background-image"></div>
|
||||||
<transition name="fade-between-two" appear>
|
<transition name="fade-between-two" appear>
|
||||||
<ConnectingScreen v-if="!loggedIn"/>
|
<ConnectingScreen v-if="!loggedIn"/>
|
||||||
<div class="box" v-if="loggedIn">
|
<div class="box" v-if="loggedIn">
|
||||||
<div class="frame">
|
<div class="frame" v-if="isElectron">
|
||||||
<div class="tabs">
|
<div class="window-buttons">
|
||||||
|
<electron-frame-buttons />
|
||||||
<div :class="`tab ${currentTab === 0 ? 'selected' : ''}`" @click="switchTab(0)">
|
|
||||||
<i class="material-icons">explore</i>
|
|
||||||
Explore
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="{tab: true, selected: currentTab === 1, notifyAnimation: DMNotification || friendRequestExists}" @click="switchTab(1)">
|
|
||||||
<i class="material-icons">chat</i>
|
|
||||||
Direct Message
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="{tab: true, selected: currentTab === 2, notifyAnimation: serverNotification}" @click="switchTab(2)">
|
|
||||||
<i class="material-icons">forum</i>
|
|
||||||
Servers
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="`tab ${currentTab === 3 ? 'selected' : ''}`" @click="switchTab(3)">
|
|
||||||
<i class="material-icons">list_alt</i>
|
|
||||||
Changelog
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <div :class="`tab ${currentTab === 4 ? 'selected' : ''}`" @click="switchTab(4)">
|
|
||||||
<i class="material-icons">info</i>
|
|
||||||
Ad
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="window-buttons" v-if="isElectron">
|
|
||||||
<electron-frame-buttons />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-layout">
|
<div class="panel-layout">
|
||||||
|
|
@ -59,7 +31,6 @@ import changelog from "@/utils/changelog.js";
|
||||||
import ConnectingScreen from "./../components/app/ConnectingScreen.vue";
|
import ConnectingScreen from "./../components/app/ConnectingScreen.vue";
|
||||||
import Spinner from "./../components/Spinner.vue";
|
import Spinner from "./../components/Spinner.vue";
|
||||||
|
|
||||||
|
|
||||||
const ElectronFrameButtons = () =>
|
const ElectronFrameButtons = () =>
|
||||||
import("@/components/ElectronJS/FrameButtons.vue");
|
import("@/components/ElectronJS/FrameButtons.vue");
|
||||||
|
|
||||||
|
|
@ -87,7 +58,6 @@ const Explore = () => ({
|
||||||
export default {
|
export default {
|
||||||
name: "app",
|
name: "app",
|
||||||
components: {
|
components: {
|
||||||
|
|
||||||
DirectMessage,
|
DirectMessage,
|
||||||
Servers,
|
Servers,
|
||||||
ConnectingScreen,
|
ConnectingScreen,
|
||||||
|
|
@ -98,7 +68,6 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentTab: 0,
|
|
||||||
title: "Nertivia",
|
title: "Nertivia",
|
||||||
isElectron: window && window.process && window.process.type
|
isElectron: window && window.process && window.process.type
|
||||||
};
|
};
|
||||||
|
|
@ -133,7 +102,7 @@ export default {
|
||||||
},
|
},
|
||||||
switchTab(index) {
|
switchTab(index) {
|
||||||
localStorage.setItem("currentTab", index);
|
localStorage.setItem("currentTab", index);
|
||||||
this.currentTab = index;
|
this.$store.dispatch('setCurrentTab', index)
|
||||||
if (index == 1) { //1: direct message tab.
|
if (index == 1) { //1: direct message tab.
|
||||||
this.switchChannel(false)
|
this.switchChannel(false)
|
||||||
} else if (index === 2) { //2: server tab
|
} else if (index === 2) { //2: server tab
|
||||||
|
|
@ -156,25 +125,25 @@ export default {
|
||||||
|
|
||||||
const currentTab = localStorage.getItem("currentTab");
|
const currentTab = localStorage.getItem("currentTab");
|
||||||
if(currentTab) {
|
if(currentTab) {
|
||||||
this.currentTab = parseInt(currentTab);
|
this.$store.dispatch('setCurrentTab', parseInt(currentTab))
|
||||||
}
|
}
|
||||||
// check if changelog is updated
|
// check if changelog is updated
|
||||||
const seenVersion = localStorage.getItem("changelog-version-seen");
|
const seenVersion = localStorage.getItem("changelog-version-seen");
|
||||||
if (seenVersion && seenVersion < changelog[0].version) {
|
if (seenVersion && seenVersion < changelog[0].version) {
|
||||||
localStorage.setItem("currentTab", 3);
|
localStorage.setItem("currentTab", 3);
|
||||||
this.currentTab = 3;
|
this.$store.dispatch('setCurrentTab', 3)
|
||||||
}
|
}
|
||||||
localStorage.setItem("changelog-version-seen", changelog[0].version);
|
localStorage.setItem("changelog-version-seen", changelog[0].version);
|
||||||
bus.$on("title:change", title => {
|
bus.$on("title:change", title => {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
});
|
});
|
||||||
|
|
||||||
bus.$on('changeTab', this.switchTab)
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
bus.$off('changeTab', this.switchTab)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
currentTab() {
|
||||||
|
return this.$store.getters.currentTab;
|
||||||
|
},
|
||||||
loggedIn() {
|
loggedIn() {
|
||||||
return this.$store.getters.loggedIn;
|
return this.$store.getters.loggedIn;
|
||||||
},
|
},
|
||||||
|
|
@ -277,6 +246,8 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
height: 25px;
|
||||||
|
background: #1089ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-buttons {
|
.window-buttons {
|
||||||
|
|
@ -287,6 +258,9 @@ export default {
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
|
|
@ -381,12 +355,6 @@ textarea {
|
||||||
filter: blur(15px);
|
filter: blur(15px);
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
.halloween-background {
|
|
||||||
background: url(./../assets/halloween_background.jpg);
|
|
||||||
filter: blur(10px);
|
|
||||||
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-layout {
|
.panel-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -1,508 +0,0 @@
|
||||||
<template>
|
|
||||||
<div id="app">
|
|
||||||
<vue-headful
|
|
||||||
title="Nertivia"
|
|
||||||
description="Nertivia Chat Client"
|
|
||||||
/>
|
|
||||||
<div class="background-image" />
|
|
||||||
<div class="layout">
|
|
||||||
<div class="small-view-nav-bar">
|
|
||||||
<div class="small-logo" />
|
|
||||||
<div class="small-title">
|
|
||||||
Nertivia
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="show-menu-button"
|
|
||||||
@click="showMobileMenu = !showMobileMenu"
|
|
||||||
>
|
|
||||||
<i class="material-icons">
|
|
||||||
menu
|
|
||||||
</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="panels">
|
|
||||||
<div class="left-panel">
|
|
||||||
<div class="title">
|
|
||||||
The best chat client that wont restrict you from important and fun features.
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
src="../assets/graphics/HomeGraphics.png"
|
|
||||||
class="graphic-app"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="change-log-mini"
|
|
||||||
@click="showChangeLog = true"
|
|
||||||
>
|
|
||||||
<div class="change-title">
|
|
||||||
Change log <span style="font-size: 15px; color: rgba(211, 211, 211, 0.774);">Click for details</span>
|
|
||||||
</div>
|
|
||||||
<div class="change-list">
|
|
||||||
<div
|
|
||||||
v-for="change in changelogFiltered"
|
|
||||||
:key="change.title"
|
|
||||||
class="change"
|
|
||||||
>
|
|
||||||
<div class="notable-changes">
|
|
||||||
{{ change.shortTitle }}
|
|
||||||
</div>
|
|
||||||
<div class="change-date">
|
|
||||||
{{ change.date }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="twitter-outer">
|
|
||||||
<twitter class="twitter">
|
|
||||||
<div slot="loading">
|
|
||||||
loading .....
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
class="twitter-timeline"
|
|
||||||
data-height="500"
|
|
||||||
data-theme="dark"
|
|
||||||
href="https://twitter.com/NertiviaApp?ref_src=twsrc%5Etfw"
|
|
||||||
>Tweets by NertiviaApp</a>
|
|
||||||
</twitter>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<RightPanel :class="{'show-menu-content': showMobileMenu }" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<transition name="fade">
|
|
||||||
<ChangeLog v-if="showChangeLog" />
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { twitter } from 'vue-twitter'
|
|
||||||
import {bus} from '../main';
|
|
||||||
import RightPanel from "./../components/homePage/RightPanel.vue"
|
|
||||||
import ChangeLog from "./../components/ChangeLog.vue"
|
|
||||||
import changelog from '@/utils/changelog.js'
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
RightPanel,
|
|
||||||
ChangeLog,
|
|
||||||
twitter
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loginSelected: true,
|
|
||||||
showMobileMenu: false,
|
|
||||||
showChangeLog: false,
|
|
||||||
changelog
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
changelogFiltered() {
|
|
||||||
return this.changelog.slice(0, 3)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
bus.$on('closeChangeLog', () => {
|
|
||||||
this.showChangeLog = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
html {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
font-family: "Roboto", sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
color: #383838;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.twitter-outer{
|
|
||||||
margin: auto;
|
|
||||||
width: 600px;
|
|
||||||
opacity: 0.8;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
.twitter-outer:hover{
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.fade-enter-active, .fade-leave-active {
|
|
||||||
transition: opacity .2s;
|
|
||||||
}
|
|
||||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
color: #383838;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
}
|
|
||||||
.spinner{
|
|
||||||
margin: auto;
|
|
||||||
padding: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.background-image {
|
|
||||||
background: url(./../assets/background.jpg);
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: bottom;
|
|
||||||
background-size: cover;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout{
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width:100%;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.panels{
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.left-panel {
|
|
||||||
flex: 1;
|
|
||||||
background: rgba(0, 0, 0, 0.253);
|
|
||||||
overflow: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
}
|
|
||||||
.title-panel{
|
|
||||||
width: 100%;
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.graphics-panel{
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.graphic-app{
|
|
||||||
display: table;
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
width: 900px;
|
|
||||||
height: auto;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.title{
|
|
||||||
color: white;
|
|
||||||
font-size: 35px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-log-mini{
|
|
||||||
background: rgba(0, 0, 0, 0.322);
|
|
||||||
height: 150px;
|
|
||||||
width: 640px;
|
|
||||||
margin: auto;
|
|
||||||
margin-top: 20px;
|
|
||||||
color: white;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-title {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-left: 10px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-list{
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change {
|
|
||||||
background: rgba(0, 0, 0, 0.335);
|
|
||||||
width: 200px;
|
|
||||||
height: 90px;
|
|
||||||
margin-left: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: 0.3s;
|
|
||||||
position: relative
|
|
||||||
}
|
|
||||||
.change:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.466);
|
|
||||||
}
|
|
||||||
.notable-changes{
|
|
||||||
margin: 10px;
|
|
||||||
cursor: default;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-date{
|
|
||||||
position: absolute;
|
|
||||||
bottom: 10px;
|
|
||||||
right: 10px;
|
|
||||||
color: rgba(255, 255, 255, 0.753);
|
|
||||||
cursor: default;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-view-nav-bar{
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
background: rgba(0, 0, 0, 0.411);
|
|
||||||
display: none;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-logo {
|
|
||||||
height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
background: url(./../assets/logo.png);
|
|
||||||
background-size: 105%;
|
|
||||||
background-position: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0px 0px 96px -4px rgba(69,212,255,1);
|
|
||||||
margin: auto;
|
|
||||||
margin-left: 10px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-title{
|
|
||||||
color: white;
|
|
||||||
font-size: 20px;
|
|
||||||
flex: 1;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-menu-button{
|
|
||||||
color: rgba(255, 255, 255, 0.698);
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-top: 7px;
|
|
||||||
user-select: none;
|
|
||||||
transition: 0.3s
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-menu-button:hover {
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-menu-content {
|
|
||||||
display: flex !important;
|
|
||||||
width: 400px !important;
|
|
||||||
opacity: 1 !important;
|
|
||||||
transform: scale(1) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1051px) {
|
|
||||||
.change:nth-child(3){
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.change-log-mini{
|
|
||||||
width: 430px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 906px) {
|
|
||||||
|
|
||||||
.change:nth-child(3){
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.change-log-mini{
|
|
||||||
width: 640px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 649px) {
|
|
||||||
.twitter-outer{
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 50px;
|
|
||||||
width: initial;
|
|
||||||
}
|
|
||||||
.change-list{
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.change-log-mini{
|
|
||||||
height: initial;
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
padding-bottom: 10px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
.change{
|
|
||||||
margin-bottom: 5px;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 0;
|
|
||||||
width: calc(100% - 10px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 1380px) {
|
|
||||||
.graphic-app{
|
|
||||||
width: calc(100% - 80px);
|
|
||||||
}
|
|
||||||
.title{
|
|
||||||
font-size: 30px;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-right: 20px;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 906px) {
|
|
||||||
.right-panel-home {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 50px;
|
|
||||||
display: flex;
|
|
||||||
margin-right: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
height:calc(100% - 50px);
|
|
||||||
background-color: rgb(34, 34, 34);
|
|
||||||
width: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
transition: 0.5s ease;
|
|
||||||
transform: scale(0.97);
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
.right-panel-inner{
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
.small-view-nav-bar{
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@media (max-width: 401px) {
|
|
||||||
.show-menu-content {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
.right-panel-inner{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Used for forms !-->
|
|
||||||
<style>
|
|
||||||
@media (max-width: 1380px) {
|
|
||||||
.graphic-app{
|
|
||||||
width: calc(100% - 80px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 906px) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.right-panel-home {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 50px;
|
|
||||||
display: flex;
|
|
||||||
margin-right: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
height:calc(100% - 50px);
|
|
||||||
background-color: rgba(34, 34, 34, 0.877);
|
|
||||||
width: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
transition: 0.5s ease;
|
|
||||||
transform: scale(0.97);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-panel-inner{
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
.small-view-nav-bar{
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@media (max-width: 401px) {
|
|
||||||
.show-menu-content {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
.right-panel-inner{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
color: white;
|
|
||||||
margin: auto;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input{
|
|
||||||
padding: 10px;
|
|
||||||
background: rgba(0, 0, 0, 0.301);
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
width: 200px;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:hover{
|
|
||||||
background: rgba(0, 0, 0, 0.452);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus {
|
|
||||||
background: rgba(0, 0, 0, 0.603);
|
|
||||||
}
|
|
||||||
.input-title{
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.form-button{
|
|
||||||
padding: 10px;
|
|
||||||
background: rgba(0, 0, 0, 0.226);
|
|
||||||
display: table;
|
|
||||||
transition: 0.5s;
|
|
||||||
margin: auto;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-button:hover{
|
|
||||||
background: rgba(0, 0, 0, 0.534)
|
|
||||||
}
|
|
||||||
.alert{
|
|
||||||
color: red;
|
|
||||||
font-size: 15px;
|
|
||||||
width: 220px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in a new issue