Profile Component now accepts a user-object as paramter.
Started to implement the settings popup
This commit is contained in:
18
package-lock.json
generated
18
package-lock.json
generated
@@ -20,7 +20,7 @@
|
||||
"devDependencies": {
|
||||
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
|
||||
"@quasar/app-vite": "^1.8.5",
|
||||
"@quasar/cli": "^2.4.0",
|
||||
"@quasar/cli": "^2.4.1",
|
||||
"@types/node": "^12.20.21",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
@@ -590,9 +590,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@quasar/cli": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/cli/-/cli-2.4.0.tgz",
|
||||
"integrity": "sha512-VhmNnVFy/eLgKqofJh6dXYudMVhXDdCqNY/d1oPR1saMXsmqYB9tJKaW1FJIlPnnY3oDlcYwMSUeQwc4pehWyQ==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/cli/-/cli-2.4.1.tgz",
|
||||
"integrity": "sha512-MrOmlqdkQhBxfPMbSrch3O7ClCAc0sLTLp9AWLzdB7uNaLbxcLP6zXN8+EPhDzFfMyxdG7jBP0FKEi7Wh+ezrQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@quasar/ssl-certificate": "^1.0.0",
|
||||
@@ -601,7 +601,7 @@
|
||||
"connect-history-api-fallback": "^2.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"express": "^4.18.3",
|
||||
"express": "^4.19.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"kolorist": "^1.8.0",
|
||||
@@ -8102,9 +8102,9 @@
|
||||
}
|
||||
},
|
||||
"@quasar/cli": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/cli/-/cli-2.4.0.tgz",
|
||||
"integrity": "sha512-VhmNnVFy/eLgKqofJh6dXYudMVhXDdCqNY/d1oPR1saMXsmqYB9tJKaW1FJIlPnnY3oDlcYwMSUeQwc4pehWyQ==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/cli/-/cli-2.4.1.tgz",
|
||||
"integrity": "sha512-MrOmlqdkQhBxfPMbSrch3O7ClCAc0sLTLp9AWLzdB7uNaLbxcLP6zXN8+EPhDzFfMyxdG7jBP0FKEi7Wh+ezrQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@quasar/ssl-certificate": "^1.0.0",
|
||||
@@ -8113,7 +8113,7 @@
|
||||
"connect-history-api-fallback": "^2.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"express": "^4.18.3",
|
||||
"express": "^4.19.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"kolorist": "^1.8.0",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"devDependencies": {
|
||||
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
|
||||
"@quasar/app-vite": "^1.8.5",
|
||||
"@quasar/cli": "^2.4.0",
|
||||
"@quasar/cli": "^2.4.1",
|
||||
"@types/node": "^12.20.21",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
displayName: String,
|
||||
username: String,
|
||||
profilePictureUrl: String,
|
||||
status: String,
|
||||
})
|
||||
import {message, ptpTestUser} from 'src/models';
|
||||
|
||||
const profilePicture = "url("+props.profilePictureUrl+")";
|
||||
const props = defineProps({
|
||||
user: Object,
|
||||
selected: Boolean,
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="profileCard">
|
||||
<div class="profilePicture"></div>
|
||||
<div class="profileCard" :class="selected ? 'selected' : ''">
|
||||
<div class="profilePicture" :style="{'background-image' : 'url('+props.user!.profilePictureUrl+')' }"></div>
|
||||
<div style="margin-left:10px;">
|
||||
<p style="margin-bottom: 0;line-height: 25px;vertical-align: middle;height: 25px;display: table-cell;">
|
||||
<span style="font-weight: bold;font-size: 1.2rem;">{{props.displayName}}</span>
|
||||
@{{props.username}}
|
||||
<span style="font-weight: bold;font-size: 1.2rem;">{{props.user!.firstName}} {{ props.user!.lastName }}</span>
|
||||
@{{props.user!.username}}
|
||||
</p>
|
||||
|
||||
<p style="margin: 0;">{{ props.status }}</p>
|
||||
<p style="margin: 0;">{{ props.user!.status }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -31,7 +29,7 @@ const profilePicture = "url("+props.profilePictureUrl+")";
|
||||
border-radius: 50%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: v-bind('profilePicture');
|
||||
|
||||
}
|
||||
|
||||
.profileCard {
|
||||
@@ -46,4 +44,8 @@ const profilePicture = "url("+props.profilePictureUrl+")";
|
||||
transition: .3s;
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.selected {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,17 @@ export interface ptpUser {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
username: string;
|
||||
status?: string;
|
||||
profilePictureUrl?: string;
|
||||
}
|
||||
|
||||
export interface ptpTestUser {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
username: string;
|
||||
status?: string;
|
||||
profilePictureUrl?: string;
|
||||
}
|
||||
|
||||
export interface responseModel {
|
||||
|
||||
@@ -1,5 +1,93 @@
|
||||
<template>
|
||||
<div style="width:100%;display: flex; align-items: center; justify-content: space-between;height:100vh;position: fixed;">
|
||||
<!-- Hier gibt es die ganzen PopUps und so -->
|
||||
|
||||
<q-dialog v-model="settingsDialog" backdrop-filter="brightness(60%)" full-width>
|
||||
<q-card style="margin: 3rem 20rem;padding: 30px;height: 80vh;overflow-y:scroll">
|
||||
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<h4 style="margin: 0;">Einstellungen</h4>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<h5>Nutzerdaten</h5>
|
||||
<div style="display: flex; flex-wrap: nowrap">
|
||||
<div>
|
||||
<div v-if="userStore.userLoaded">
|
||||
<p>{{ userStore.user?.firstName }}</p>
|
||||
<p>{{ userStore.user?.lastName }}</p>
|
||||
<p>{{ userStore.user?.username }}</p>
|
||||
<p>{{ userStore.user?.id }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 50px;">
|
||||
<div style="border-radius:100%;height:10rem;width:10rem;background-image: url('https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0');background-size: cover; background-position: center;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<h5>Status</h5>
|
||||
<p>Hier kannst du deinen Status festlegen</p>
|
||||
|
||||
<q-input filled v-model="newStatus" placeholder="" counter maxlength="256">
|
||||
<!--<template v-slot:prepend>
|
||||
<q-icon name="search"></q-icon>
|
||||
</template>-->
|
||||
<template v-slot:after>
|
||||
<q-btn flat :disable="newStatus == newStatus">Speichern</q-btn>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<h5>Profilbild</h5>
|
||||
<p>Du kannst eins der folgenden Porfilbilder aussuchen</p>
|
||||
|
||||
<div class="flex-center">
|
||||
<q-btn
|
||||
style="background-image: url('https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0');"
|
||||
round
|
||||
flat
|
||||
class="profilePictureSelector"
|
||||
>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
style="background-image: url('https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0');"
|
||||
round
|
||||
flat
|
||||
class="profilePictureSelector"
|
||||
>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
style="background-image: url('https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0');"
|
||||
round
|
||||
flat
|
||||
class="profilePictureSelector"
|
||||
>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
style="background-image: url('https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0');"
|
||||
round
|
||||
flat
|
||||
class="profilePictureSelector"
|
||||
>
|
||||
</q-btn>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<q-btn @click="logout()" label="Abmelden" style="color:darkred;border:2px solid darkred;border-radius: 6px;"/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
|
||||
|
||||
<div style="background: gray; width: 25%;height:100%;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between;" class="navigation">
|
||||
<div title="Nach Nutzern suchen" @click="activeMenu = 'search'" :class="{menuItemActive : activeMenu === 'search', menuItemInactive : activeMenu !== 'search'}">
|
||||
@@ -19,11 +107,16 @@
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<div v-if="userStore.usersLoaded && searchQuery.length > 0" style="margin-top: 20px;">
|
||||
<ProfileCardComponent v-for="user in userStore.users.filter(u => (u.username.includes(searchQuery) || (u.firstName + ' ' + u.lastName).includes(searchQuery) || searchQuery == '*') && u.id != userStore.id)" :displayName="user.firstName + ' ' + user.lastName" :username="user.username" profilePictureUrl="https://th.bing.com/th/id/OIP.ab5MRsPm1MXfNDVSMW6cjQHaHa?rs=1&pid=ImgDetMain" status="Hey there!"></ProfileCardComponent>
|
||||
<div v-if="userStore.users.filter(u => u.username.includes(searchQuery) || (u.firstName + ' ' + u.lastName).includes(searchQuery) || searchQuery == '*').length == 0" style="text-align: center;">
|
||||
<!--<q-icon name="error"></q-icon>
|
||||
<p>Wir konnten keine Nutzer mit diesem Nutzernamen finden</p>-->
|
||||
<div v-if="userStore.usersLoaded && searchQuery.length > 0 && searchQuery.replace(/\s/g, '').length" style="margin-top: 20px;">
|
||||
<ProfileCardComponent
|
||||
v-for="user in userStore.users.filter(u => (u.username.toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase()) || (u.firstName + ' ' + u.lastName).toLocaleLowerCase().includes(searchQuery.trimStart().toLocaleLowerCase()) || searchQuery == '*') && u.id != userStore.id && searchQuery.replace(/\s/g, '').length)" :displayName="user.firstName + ' ' + user.lastName" :username="user.username"
|
||||
:profilePictureUrl="user.profilePictureUrl"
|
||||
:status="user.status"
|
||||
:user="user"
|
||||
:selected="selectedUser.id == user.id"
|
||||
@click="selectUser(user as ptpTestUser)"
|
||||
></ProfileCardComponent>
|
||||
<div v-if="userStore.users.filter(u => u.username.toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase()) || (u.firstName + ' ' + u.lastName).toLocaleLowerCase().includes(searchQuery.trimStart().toLocaleLowerCase()) || searchQuery == '*').length == 0 || !searchQuery.replace(/\s/g, '').length" style="text-align: center;">
|
||||
<img src="https://media.tenor.com/KOZLvzU0o4kAAAAd/no-results.gif" style="border-radius: 1rem;" alt="No search results found">
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,7 +125,29 @@
|
||||
</div>
|
||||
|
||||
<div style="margin: 20px;" v-if="activeMenu == 'chats'">
|
||||
<p>Hier werden dann die Chats angezeigt</p>
|
||||
<p>Chats, in denen du Mitglied bist:</p>
|
||||
<div v-if="chatStore.chatsLoaded">
|
||||
<div v-for="chat in chatStore.chats" :key="chat.id">
|
||||
<div v-if="chat.members.length > 2">
|
||||
<h5>{{ chat.displayName }}</h5>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h5>Ist ein Chat für zwei</h5>
|
||||
</div>
|
||||
|
||||
<p v-for="member in chat.members">
|
||||
{{ member.id }}
|
||||
</p>
|
||||
<!----<ProfileCardComponent
|
||||
v-else
|
||||
:user="userStore.users.find((user) => user.id === chat.members.find((member) => member.id !== userStore.user!.id)?.id)"
|
||||
:selected="selectedUser.id == chat.members[0].id"
|
||||
@click="selectUser(chat.members[0] as ptpTestUser)"
|
||||
></ProfileCardComponent>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<br>
|
||||
<q-input
|
||||
v-model="chatName"
|
||||
@@ -56,43 +171,30 @@
|
||||
<q-option-group
|
||||
v-model="usersForChat"
|
||||
rules="[val => val.length > 0 || 'Please select at least one user']"
|
||||
:options="userStore.users.filter(u => (u.username.includes(searchQuery) || (u.firstName + ' ' + u.lastName).includes(searchQuery) || searchQuery == '*') && u.id != userStore.id).map((u) => {
|
||||
:options="userStore.users.filter(u => (u.username.toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase()) || (u.firstName + ' ' + u.lastName).toLocaleLowerCase().includes(searchQuery.toLocaleLowerCase()) || searchQuery == '*') && u.id != userStore.id).map((u) => {
|
||||
return {label: u.firstName + ' ' + u.lastName, value: u.id}})"
|
||||
type="checkbox"
|
||||
color="primary"
|
||||
inline
|
||||
>
|
||||
|
||||
</q-option-group>
|
||||
</div>
|
||||
<q-btn @click="createChat(chatName)" label="Create Chat"/>
|
||||
<br>
|
||||
<q-btn @click="loadChats()" label="Load Chats"/>
|
||||
<div v-if="chatStore.chatsLoaded">
|
||||
<p>Chats:</p>
|
||||
<div v-for="chat in chatStore.chats" :key="chat.id">
|
||||
<h5>{{ chat.displayName }}</h5>
|
||||
<div v-for="ptpUser in chat.members" :key="ptpUser.id">
|
||||
<p>{{ ptpUser.id }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<q-btn @click="logout()" label="Logout"/>
|
||||
<h5>Nutzerdaten</h5>
|
||||
<div v-if="userStore.userLoaded">
|
||||
<p>{{ userStore.user?.firstName }}</p>
|
||||
<p>{{ userStore.user?.lastName }}</p>
|
||||
<p>{{ userStore.user?.username }}</p>
|
||||
<p>{{ userStore.user?.id }}</p>
|
||||
</div>
|
||||
<q-btn round flat icon="settings" title="Einstellungen" @click="settingsDialog = true">
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
<div style="width: 75%;height: 100%;background: #DFD0BF;">
|
||||
|
||||
<div id="messageContainer" style="padding: 25px;overflow-y: auto;height: 90%;display: flex;flex-direction: column-reverse;">
|
||||
<div v-if="selectedUser.id != null" id="messageContainer" style="padding: 25px;overflow-y: auto;height: 90%;display: flex;flex-direction: column-reverse;">
|
||||
<div v-if="!hasChatWith(selectedUser.id)" style="width: 100%; text-align: center;font-size: 1.2rem;">
|
||||
<p>Das ist der Beginn deines Chats mit <strong>{{selectedUser.firstName}} {{selectedUser.lastName}}</strong></p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>Du hast schonmal mit dem geschrieben wie schön</p>
|
||||
|
||||
<div v-for="(message, index) in messages" :key="index">
|
||||
<MessageComponent
|
||||
v-if="message.gif"
|
||||
@@ -118,6 +220,7 @@
|
||||
></MessageComponent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
@@ -165,7 +268,7 @@
|
||||
import MessageComponent from 'components/MessageComponent.vue';
|
||||
import { useTenorStore } from 'stores/tenor-store';
|
||||
import ProfileCardComponent from 'components/ProfileCardComponent.vue';
|
||||
import {message} from 'src/models';
|
||||
import {message, ptpTestUser} from 'src/models';
|
||||
import {useUserStore} from 'stores/user-store';
|
||||
import { useChatStore } from 'stores/chat-store';
|
||||
|
||||
@@ -173,6 +276,10 @@
|
||||
name: 'IndexPage'
|
||||
});
|
||||
|
||||
const tenorStore = useTenorStore();
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const searchQuery = ref("")
|
||||
const message = ref("");
|
||||
const gifSearch = ref("");
|
||||
@@ -180,6 +287,10 @@
|
||||
const userSearch = ref('');
|
||||
const usersForChat = ref([] as string[]);
|
||||
|
||||
const settingsDialog = ref(true);
|
||||
|
||||
const newStatus = ref("");
|
||||
|
||||
|
||||
const activeMenu = ref("search");
|
||||
|
||||
@@ -236,9 +347,7 @@
|
||||
changed.value = true;
|
||||
}
|
||||
|
||||
const tenorStore = useTenorStore();
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
|
||||
|
||||
|
||||
function getGifs() {
|
||||
@@ -289,12 +398,32 @@
|
||||
chatName = "Chat";
|
||||
}
|
||||
await chatStore.createChat(chatName, usersForChat.value);
|
||||
loadChats();
|
||||
}
|
||||
|
||||
const loadChats = async() => {
|
||||
await chatStore.loadChatsByUser();
|
||||
};
|
||||
|
||||
const selectedUser = ref({} as ptpTestUser);
|
||||
|
||||
function selectUser(user : ptpTestUser) {
|
||||
selectedUser.value = user;
|
||||
}
|
||||
|
||||
function hasChatWith(id : string) : boolean {
|
||||
// Hier wird geprüft, ob es ein Chat mit einem bestimmten anderen Nutzer existiert
|
||||
const chatExists = chatStore.chats.find((chat) => chat.members.length === 2 && chat.members.find((member) => member.id === id));
|
||||
|
||||
if(chatExists) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Init methods
|
||||
loadChats();
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -349,4 +478,23 @@
|
||||
.menuItemInactive {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.profilePictureSelector {
|
||||
transition: .3s;
|
||||
background-size: cover;
|
||||
background-position:center;
|
||||
width: 6rem;
|
||||
height:6rem;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.profilePictureSelector:hover {
|
||||
transition: .3s;
|
||||
filter: brightness(0.6);
|
||||
}
|
||||
|
||||
h4, h5 {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { chat } from 'src/models';
|
||||
import {chat, responseModel} from 'src/models';
|
||||
import { api } from 'src/boot/axios';
|
||||
import { useUserStore } from 'stores/user-store';
|
||||
|
||||
export const useChatStore = defineStore('chatStore',{
|
||||
state:() => ({
|
||||
chats: [] as chat[],
|
||||
chatsLoaded: false
|
||||
chatsLoaded: false,
|
||||
chatExistsReponse: false,
|
||||
}),
|
||||
actions: {
|
||||
async getChatsByUser(): Promise<chat[]> {
|
||||
@@ -33,6 +34,13 @@ export const useChatStore = defineStore('chatStore',{
|
||||
}
|
||||
console.log(members);
|
||||
return (await api.post("/chats/create/" + chatName, members)).data;
|
||||
},
|
||||
async loadDoesChatExist(keycloakID : string, otherKeycloakID : string) : Promise<responseModel> {
|
||||
return (await api.get("/chats/"+keycloakID+"/"+otherKeycloakID)).data;
|
||||
},
|
||||
doesChatExist(keycloakID : string, otherKeycloakID : string) {
|
||||
this.loadDoesChatExist(keycloakID, otherKeycloakID)
|
||||
.then(m => this.chatExistsReponse = m.success);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import {api} from 'boot/axios';
|
||||
import { ptpUser, responseModel, tenorResponseElement } from 'src/models';
|
||||
import { tenorResponseElement } from 'src/models';
|
||||
import Keycloak from 'keycloak-js';
|
||||
|
||||
export const useTenorStore = defineStore('tenorStore', {
|
||||
|
||||
@@ -49,6 +49,17 @@ export const useUserStore = defineStore('userStore', {
|
||||
getAllPtpUsers() {
|
||||
this.loadAllPtpUsers().then((response : ptpUser[]) => {
|
||||
this.users = response;
|
||||
|
||||
this.users.forEach((user : ptpUser) => {
|
||||
if(user.profilePictureUrl == null) {
|
||||
user.profilePictureUrl = "https://th.bing.com/th/id/R.487fe8708797950ab745a3800c31b7a4?rik=qW3zkDdZfweqmQ&pid=ImgRaw&r=0";
|
||||
}
|
||||
|
||||
if(user.status == null) {
|
||||
user.status = "Hey there, I am using ptpChat!";
|
||||
}
|
||||
})
|
||||
|
||||
this.usersLoaded = true;
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user