refactor/split to roomListElement/userListElement

add-admin-interface
adb 3 years ago
parent 5f536adc8f
commit 63d3f6fb47

@ -1,26 +1,21 @@
<template> <template>
<div id="chatInformation"> <div class="chatInfo">
<div id="box"> <div class="box">
<div class="scrollContainer"> <div class="scrollContainer">
<div class="informationBox"> <div class="topContainer">
<div class="picBoxBig"><div class="placeholderBig">{{room.name.substr(0,2)}}</div></div> <avatar
<div class="roomInformation"> class="roomImage"
<div class="roomName">{{room.name}}</div> :mxcURL="getMxcFromRoom(room)"
<div class="users">{{getMembers().length}} members</div> :fallback="room.roomId"
</div> :size="5"
</div>
<div v-for="member in getMembers().slice(0,20)" :key="member" class="contentBox" :title="member">
<userThumbnail
:mxcURL="getUser(member).avatarUrl"
:fallback="getUser(member).displayName"
class="userThumbnail" :size="3"
/> />
<div class="information"> <div class="info">
<div class="userName">{{getUser(member).displayName || member}}</div> <div class="roomName">{{room.name}}</div>
<div class="status">{{getStatus(getUser(member))}}</div> <div class="users">{{members.length}} members</div>
</div> </div>
</div> </div>
<p v-if="getMembers().length>20">and {{getMembers().length-20}} other members</p> <user-list-element v-for="member in members.slice(0,20)" :key="member" :user="getUser(member)"/>
<p v-if="members.length>20">and {{members.length-20}} other members</p>
</div> </div>
</div> </div>
<icon class="closeBtn" @click.native="closeChatInfo()" ic="./sym/ic_close_white_24px.svg" /> <icon class="closeBtn" @click.native="closeChatInfo()" ic="./sym/ic_close_white_24px.svg" />
@ -28,14 +23,17 @@
</template> </template>
<script> <script>
import icon from './icon.vue'; import icon from './icon.vue';
import userThumbnail from './userThumbnail';
import {matrix} from "@/main"; import {matrix} from "@/main";
import UserListElement from "@/components/userListElement";
import avatar from "@/components/avatar";
import {getMxcFromRoom} from "@/lib/getMxc";
export default { export default {
name: "chatInformation", name: "chatInformation",
components:{ components:{
avatar,
UserListElement,
icon, icon,
userThumbnail
}, },
props:{ props:{
room: {}, room: {},
@ -48,14 +46,18 @@ export default {
getMembers(){ getMembers(){
return Object.keys(this.room.currentState.members) return Object.keys(this.room.currentState.members)
}, },
getStatus(){ getMxcFromRoom
},
data(){
return{
members: this.getMembers()
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
#chatInformation{ .chatInfo{
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translate(-50%, 0); transform: translate(-50%, 0);
@ -70,7 +72,7 @@ export default {
z-index: 30; z-index: 30;
} }
@media (max-width: 30rem) { @media (max-width: 30rem) {
#chatInformation{ .chatInfo{
transform: unset; transform: unset;
top: 0; top: 0;
left: 0; left: 0;
@ -79,7 +81,7 @@ export default {
} }
} }
@media (max-height: 40rem) { @media (max-height: 40rem) {
#chatInformation{ .chatInfo{
top: 0; top: 0;
height: 100%; height: 100%;
} }
@ -91,7 +93,7 @@ export default {
background-color: #0000; background-color: #0000;
box-shadow: none; box-shadow: none;
} }
#box{ .box{
position: absolute; position: absolute;
top: 0; top: 0;
width: calc(100% - 2rem); width: calc(100% - 2rem);
@ -106,20 +108,11 @@ export default {
width: 100%; width: 100%;
height: auto; height: auto;
} }
.picBoxBig{ .info{
text-align: center; position: absolute;
background-color: #42a7b9; top: 1rem;
padding-top: 1.5rem; left: 6rem;
width: 5rem;
height: 3.5rem;
border-radius: 5rem;
font-size: 2rem;
}
.roomInformation{
position: relative;
text-align: left; text-align: left;
margin-top: -4rem;
margin-left: 5.7rem;
} }
.roomName{ .roomName{
color: white; color: white;
@ -129,34 +122,15 @@ export default {
font-size: 1.2rem; font-size: 1.2rem;
color: #9c9c9c; color: #9c9c9c;
} }
.contentBox{ .topContainer{
position: relative; position: relative;
margin-top: 0.5rem; height: 6rem;
height: 3rem;
width: 100%; width: 100%;
} }
.userThumbnail{ .roomImage{
position: absolute; position: absolute;
width: 5rem;
height: 5rem;
left: 0; left: 0;
top: 0;
width: 3rem;
height: 3rem;
}
.information{
position: absolute;
left: 4rem;
top: 0;
width: calc(100% - 4rem);
}
.userName{
position: absolute;
top: 0.75rem;
color: white;
}
.status{
position: absolute;
font-size: 0.8rem;
top: 1.75rem;
color: #9c9c9c;
} }
</style> </style>

@ -0,0 +1,92 @@
<template>
<div class="roomListElement" :title="room.name">
<div class="imageContainer">
<avatar
class="roomImage"
:mxcURL="getMxcFromRoom(room)"
:fallback="room.roomId"
:size="3"
/>
</div>
<div class="roomListName">{{room.name}}</div>
<div class="status">{{getPreviewString(room)}}</div>
</div>
</template>
<script>
import avatar from "@/components/avatar";
import {getMxcFromRoom} from "@/lib/getMxc";
import {getTime} from "@/lib/getTimeStrings";
import {matrix} from "@/main";
export default {
name: "userListElement",
components:{
avatar
},
props:{
room: Object
},
methods:{
getPreviewString(room){
let event = this.getLatestEvent(room);
if (!event) return '';
return `${this.calcUserName(event.sender)}: ${event.content.body||'unknown event'} ${getTime(event.origin_server_ts)}`;
},
getLatestEvent(room){
if (!room.timeline[room.timeline.length-1]) return undefined;
return room.timeline[room.timeline.length-1].event;
},
calcUserName(userId) {
if (matrix.user === userId) return 'you';
return matrix.client.getUser(userId).displayName || userId;
},
getMxcFromRoom
}
}
</script>
<style scoped lang="scss">
.roomListElement{
position: relative;
height: 3rem;
width: 100%;
font-size: 1.2rem;
cursor: pointer;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
.imageContainer{
position: absolute;
height: 3rem;
width: 3rem;
left: 0.5rem;
.roomImage {
height: inherit;
width: inherit;
}
}
.roomListName{
position: absolute;
left: 4rem;
top: 0.25rem;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 5rem);
text-align: left;
}
.status{
position: absolute;
top: 1.5rem;
left: 4rem;
font-size: 0.8rem;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: calc(100% - 4.5rem);
}
}
.roomListElement:hover{
background-color: #4444;
}
</style>

@ -9,7 +9,7 @@
<div class="eventGroup" v-for="group in splitArray(timeGroup, obj => obj.sender)" :key="group[0].origin_server_ts"> <div class="eventGroup" v-for="group in splitArray(timeGroup, obj => obj.sender)" :key="group[0].origin_server_ts">
<div class="thumbnailContainer"> <div class="thumbnailContainer">
<div class="filler"></div> <div class="filler"></div>
<userThumbnail <avatar
v-if="group[0].sender !== user && groupTimeline" v-if="group[0].sender !== user && groupTimeline"
:fallback="group[0].sender" :fallback="group[0].sender"
class="userThumbnail" class="userThumbnail"
@ -51,17 +51,15 @@
<script> <script>
import message from "@/components/message"; import message from "@/components/message";
import userThumbnail from "@/components/userThumbnail"; import avatar from "@/components/avatar";
import {matrix} from "@/main"; import {matrix} from "@/main";
import splitArray from "@/lib/splitArray"; import splitArray from "@/lib/splitArray";
import {getDate, getTime} from "@/lib/getTimeStrings"; import {getDate, getTime} from "@/lib/getTimeStrings";
import sdk from "matrix-js-sdk"
export default { export default {
name: 'eventGroup', name: 'eventGroup',
components: { components: {
message, message,
userThumbnail avatar
}, },
props: { props: {
timeline: Array, timeline: Array,
@ -73,18 +71,6 @@ export default {
getUser(userId) { getUser(userId) {
return matrix.client.getUser(userId); return matrix.client.getUser(userId);
}, },
getReplyId(event){
if(!event.content['m.relates_to']) return undefined;
if(!event.content['m.relates_to']['m.in_reply_to']) return undefined;
return event.content['m.relates_to']['m.in_reply_to'].event_id || undefined;
},
async getReplyEvent(event, callback){
let replyId = this.getReplyId(event);
if (replyId === undefined) return undefined;
await matrix.client.fetchRoomEvent(this.roomId, replyId).then((res) => {
callback(new sdk.MatrixEvent(res));
});
},
splitArray, splitArray,
getDate, getDate,
getTime getTime

@ -1,45 +1,34 @@
<template> <template>
<div class="topBanner"> <div class="topBanner">
<div> <div>
<icon @click.native="closeChat()" class="smallIcon" id="icon-arrow" ic="./sym/arrow_back-24px.svg" /> <icon @click.native="closeChat()" class="topIcon" ic="./sym/arrow_back-24px.svg" />
<userThumbnail @click.native="openChatInfo()" class="userThumbnail" <div @click="openChatInfo()" class="container">
:mxcURL="getUrl()" :fallback="room.roomId" :size="3"/> <avatar class="topIcon avatar" :mxcURL="getMxcFromRoom(room)" :fallback="room.roomId" :size="3"/>
<div id="container"> <div class="chatName">{{room.name}}</div>
<div id="chatName">{{room.name}}</div> <div class="info">{{Object.keys(room.currentState.members).length}} members</div>
<div id="users">{{Object.keys(room.currentState.members).length}} members</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import icon from '@/components/icon.vue'; import icon from '@/components/icon.vue';
import {matrix} from "@/main"; import avatar from "@/components/avatar";
import userThumbnail from "@/components/userThumbnail"; import {getMxcFromRoom} from "@/lib/getMxc";
import sdk from 'matrix-js-sdk'
export default { export default {
name: "topBanner", name: "topBanner",
components:{ components:{
icon, icon,
userThumbnail avatar
}, },
props:{ props:{
room: [Object, undefined], room: [Object, undefined],
closeChat: Function, closeChat: Function,
openChatInfo: Function openChatInfo: Function
}, },
data(){
return {
}
},
methods: { methods: {
getRoom(roomId) { getMxcFromRoom
return matrix.client.getRoom(roomId);
},
getUrl(){
let avatarState = this.room.getLiveTimeline().getState(sdk.EventTimeline.FORWARDS).getStateEvents("m.room.avatar");
return avatarState.length>0?avatarState[avatarState.length-1].getContent().url:undefined;
}
} }
} }
</script> </script>
@ -52,43 +41,30 @@ export default {
height: 3.5rem; height: 3.5rem;
background-color: #1d1d1d; background-color: #1d1d1d;
} }
.smallIcon{ .topIcon{
top: 0.25rem;
background-color: #2d2d2d;
padding-top: 0.75rem;
height: 1.75rem;
width: 2.5rem;
box-shadow: none;
border-radius: 1.25rem;
text-align: center;
user-select: none;
cursor: pointer;
}
#icon-arrow{
height: 2.5rem;
position: absolute; position: absolute;
width: 3rem;
height: 3rem;
left: 0.5rem; left: 0.5rem;
top: 0.25rem;
background-color: unset; background-color: unset;
box-shadow: none; box-shadow: none;
} }
.userThumbnail{ .container{
position: absolute; position: absolute;
top: 0.25rem; height: 100%;
left: 3.5rem; width: calc(100% - 3.5rem);
width: 3rem; right: 0;
height: 3rem;
} }
#container{ .chatName{
position: absolute; position: absolute;
top: 0.55rem; top: 1rem;
left: 7rem; left: 4rem;
}
#chatName{
font-size: 1rem;
color: #ededed;
} }
#users{ .info{
font-size: 0.75rem; position: absolute;
color: #9c9c9c; top: 2rem;
left: 4rem;
font-size: 0.8rem;
} }
</style> </style>

@ -0,0 +1,84 @@
<template>
<div class="userListElement" :title="user.userId">
<div class="imageContainer">
<avatar
class="userImage"
:mxcURL="user.avatarUrl"
:fallback="user.userId"
:size="3"
/>
<div v-if="user.currentlyActive" class="online"></div>
</div>
<div class="userListName">{{user.displayName || user.userId}}</div>
<div class="status">{{user.presence}}</div>
</div>
</template>
<script>
import avatar from "@/components/avatar";
export default {
name: "userListElement",
components:{
avatar
},
props:{
user: Object
}
}
</script>
<style scoped lang="scss">
.userListElement{
position: relative;
height: 3rem;
width: 100%;
font-size: 1.2rem;
cursor: pointer;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
.imageContainer{
position: absolute;
height: 3rem;
width: 3rem;
left: 0.5rem;
.userImage {
height: inherit;
width: inherit;
}
.online {
position: absolute;
bottom: 0;
right: 0;
height: 0.6rem;
width: 0.6rem;
background-color: #42b983;
border-radius: 50%;
border: 0.2rem solid #222;
}
}
.userListName{
position: absolute;
left: 4rem;
top: 0.25rem;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 5rem);
text-align: left;
}
.status{
position: absolute;
top: 1.5rem;
left: 4rem;
font-size: 0.8rem;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: calc(100% - 4.5rem);
}
}
.userListElement:hover{
background-color: #4444;
}
</style>

@ -0,0 +1,19 @@
import sdk from 'matrix-js-sdk'
import {matrix} from "@/main";
export function getMxcFromUser(user){
return user.avatarUrl;
}
export function getMxcFromUserId(userId){
return matrix.client.getUser(userId).avatarUrl;
}
export function getMxcFromRoom(room){
let avatarState = room.getLiveTimeline().getState(sdk.EventTimeline.FORWARDS).getStateEvents("m.room.avatar");
return avatarState.length>0?avatarState[avatarState.length-1].getContent().url:undefined;
}
export function getMxcFromRoomId(roomId){
return getMxcFromRoom(matrix.client.getRoom(roomId));
}

@ -14,7 +14,7 @@ export class MatrixHandler {
if (this.client){ console.log('there is already an active session'); return; } if (this.client){ console.log('there is already an active session'); return; }
this.client = new matrix.createClient({ this.client = new matrix.createClient({
baseUrl: baseUrl, baseUrl: baseUrl,
sessionStore: new matrix.WebStorageSessionStore(localStorage) store: new matrix.MemoryStore(window.localStorage)
}); });
this.client.login('m.login.password', { this.client.login('m.login.password', {
user: user, user: user,
@ -45,7 +45,7 @@ export class MatrixHandler {
baseUrl, baseUrl,
accessToken, accessToken,
userId, userId,
sessionStore: new matrix.WebStorageSessionStore(localStorage) store: new matrix.MemoryStore(window.localStorage)
}); });
this.user = userId; this.user = userId;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;

@ -7,16 +7,11 @@
<h1>[chat]</h1> <h1>[chat]</h1>
<input v-model="search" class="input" type="text" maxlength="50" placeholder="search"><br> <input v-model="search" class="input" type="text" maxlength="50" placeholder="search"><br>
<div v-for="room in matrix.rooms" :key="room.roomId" @click="openChat(room)" > <div v-for="room in matrix.rooms" :key="room.roomId" @click="openChat(room)" >
<div v-if="!search || room.name.toLowerCase().includes(search.toLowerCase())" class="roomListElement"> <room-list-element
<userThumbnail v-if="!search || room.name.toLowerCase().includes(search.toLowerCase())"
class="roomImg" :room="room"
:mxcURL="getUrl(room)" class="roomListElement"
:fallback="room.roomId" />
:size="3"
/>
<div class="roomListName">{{room.name}}</div>
<div class="preview">{{getPreviewString(room)}}</div>
</div>
</div> </div>
</div> </div>
<chat <chat
@ -28,18 +23,6 @@
:open-chat-info="()=>showChatInfo=true" :open-chat-info="()=>showChatInfo=true"
/> />
<div class="noRoomSelected" v-else>Please select a room to be displayed.</div> <div class="noRoomSelected" v-else>Please select a room to be displayed.</div>
<div class="roomListSmall">
<h1>[c]</h1>
<div v-for="(room, index) in matrix.rooms" :key="index" @click="openChat(room)" class="roomListElement" :title="room.name">
<userThumbnail
class="roomImg"
:mxcURL="getUrl(room)"
:fallback="room.roomId"
:size="3"
/>
<div class="roomListName">{{room.name}}</div>
</div>
</div>
<chatInformation v-if="currentRoom && showChatInfo" :room="currentRoom" :close-chat-info="()=>showChatInfo=false"/> <chatInformation v-if="currentRoom && showChatInfo" :room="currentRoom" :close-chat-info="()=>showChatInfo=false"/>
</div> </div>
</template> </template>
@ -47,11 +30,10 @@
<script> <script>
import chat from '@/views/chat.vue'; import chat from '@/views/chat.vue';
import chatInformation from "@/components/chatInformation"; import chatInformation from "@/components/chatInformation";
import userThumbnail from "@/components/userThumbnail";
import {matrix} from "@/main"; import {matrix} from "@/main";
import sdk from "matrix-js-sdk";
import {getTime} from "@/lib/getTimeStrings";
import ThrobberOverlay from "@/components/throbberOverlay"; import ThrobberOverlay from "@/components/throbberOverlay";
import {getMxcFromRoom} from "@/lib/getMxc";
import roomListElement from "@/components/roomListElement";
export default { export default {
name: "rooms", name: "rooms",
@ -59,33 +41,17 @@ export default {
ThrobberOverlay, ThrobberOverlay,
chat, chat,
chatInformation, chatInformation,
userThumbnail roomListElement
}, },
methods:{ methods:{
openChat(room){ openChat(room){
this.showChatInfo = false;
this.currentRoom = room; this.currentRoom = room;
this.$router.push(`/rooms/${room.roomId}`); this.$router.push(`/rooms/${room.roomId}`);
this.$forceUpdate(); this.$forceUpdate();
this.search = ''; this.search = '';
}, },
getUrl(room){ getMxcFromRoom
let avatarState = room.getLiveTimeline().getState(sdk.EventTimeline.FORWARDS).getStateEvents("m.room.avatar");
return avatarState.length>0?avatarState[avatarState.length-1].getContent().url:undefined;
},
getLatestEvent(room){
if (!room.timeline[room.timeline.length-1]) return undefined;
return room.timeline[room.timeline.length-1].event;
},
getPreviewString(room){
let event = this.getLatestEvent(room);
if (!event) return '';
return `${this.calcUserName(event.sender)}: ${event.content.body||'unknown event'} ${getTime(event.origin_server_ts)}`;
},
calcUserName(userId) {
if (matrix.user === userId) return 'you';
return matrix.client.getUser(userId).displayName || userId;
}
}, },
data(){ data(){
return { return {

Loading…
Cancel
Save