UI updates
This commit is contained in:
parent
3dc1fa3567
commit
24b72cab1e
9 changed files with 193 additions and 58 deletions
|
|
@ -120,6 +120,21 @@ $chat-text-size: 0.7pt;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.op-button {
|
||||
position:absolute;
|
||||
right:-30px;
|
||||
top:0;
|
||||
.v-icon {
|
||||
color: #cccccc;
|
||||
&:hover {
|
||||
color: #888888;
|
||||
}
|
||||
}
|
||||
}
|
||||
.messageOut .op-button {
|
||||
right:70%;
|
||||
}
|
||||
}
|
||||
|
||||
.messageJoin {
|
||||
|
|
@ -139,6 +154,9 @@ $chat-text-size: 0.7pt;
|
|||
border-radius: 10px 10px 0 10px;
|
||||
padding: 8px;
|
||||
}
|
||||
.audio-bubble {
|
||||
overflow: scroll;
|
||||
}
|
||||
.bubble.image-bubble {
|
||||
padding: 0px;
|
||||
overflow: hidden;
|
||||
|
|
@ -179,6 +197,7 @@ $chat-text-size: 0.7pt;
|
|||
}
|
||||
.audio-bubble {
|
||||
margin-left: 40px;
|
||||
overflow: scroll;
|
||||
}
|
||||
.bubble.image-bubble {
|
||||
padding: 0px;
|
||||
|
|
@ -248,14 +267,21 @@ $chat-text-size: 0.7pt;
|
|||
margin: 20px;
|
||||
}
|
||||
|
||||
.messageOperations {
|
||||
.message-operations-strut {
|
||||
position: relative;
|
||||
height: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.message-operations {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
width: auto;
|
||||
background-color: #ffe2e2;
|
||||
&.incoming {
|
||||
left: -20px;
|
||||
right: 30%;
|
||||
}
|
||||
&.outgoing {
|
||||
right: 20px;
|
||||
left: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,17 +6,32 @@
|
|||
ref="chatContainer"
|
||||
style="overflow-x: hidden; overflow-y: auto"
|
||||
v-on:scroll="onScroll"
|
||||
@click.prevent="closeContextMenuIfOpen"
|
||||
>
|
||||
<div class="message-operations-strut">
|
||||
<message-operations
|
||||
:style="opStyle"
|
||||
v-on:close="showContextMenu = false"
|
||||
v-if="selectedEvent && showContextMenu"
|
||||
v-on:addreaction="addReaction"
|
||||
v-on:edit="edit(selectedEvent)"
|
||||
:event="selectedEvent"
|
||||
:incoming="selectedEvent.getSender() != $matrix.currentUserId"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Handle resizes, e.g. when soft keyboard is shown/hidden -->
|
||||
<resize-observer
|
||||
ref="chatContainerResizer"
|
||||
@notify="handleChatContainerResize"
|
||||
/>
|
||||
|
||||
<div v-for="event in events" :key="event.getId()">
|
||||
<div
|
||||
v-if="
|
||||
!event.isRelation() && !event.isRedacted() && !event.isRedaction()
|
||||
"
|
||||
:ref="event.getId()"
|
||||
>
|
||||
<div
|
||||
style="position: relative; user-select: none"
|
||||
|
|
@ -41,14 +56,15 @@
|
|||
)
|
||||
"
|
||||
v-on:send-quick-reaction="sendQuickReaction"
|
||||
v-on:context-menu="showContextMenuForEvent($event)"
|
||||
/>
|
||||
<message-operations
|
||||
<!-- <message-operations
|
||||
v-on:close="showContextMenu = false"
|
||||
v-if="selectedEvent == event && showContextMenu"
|
||||
v-on:addreaction="addReaction"
|
||||
:event="event"
|
||||
:incoming="event.getSender() != $matrix.currentUserId"
|
||||
/>
|
||||
/> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -239,6 +255,7 @@ export default {
|
|||
currentSendError: null,
|
||||
showEmojiPicker: false,
|
||||
selectedEvent: null,
|
||||
editedEvent: null,
|
||||
showContextMenu: false,
|
||||
/**
|
||||
* Current chat container size. We need to keep track of this so that if and when
|
||||
|
|
@ -287,7 +304,18 @@ export default {
|
|||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
opStyle() {
|
||||
// Calculate where to show the context menu.
|
||||
//
|
||||
const ref = this.selectedEvent && this.$refs[this.selectedEvent.getId()];
|
||||
if (ref && ref[0]) {
|
||||
const offset = ref[0].offsetTop - this.scrollPosition.node.offsetTop;
|
||||
return "top:" + offset + "px";
|
||||
}
|
||||
return "top:0px";
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
|
@ -459,7 +487,7 @@ export default {
|
|||
) {
|
||||
scrollToSeeNew = true;
|
||||
}
|
||||
if (event.forwardLooking) {
|
||||
if (event.forwardLooking && !event.isRelation()) {
|
||||
this.handleScrolledToBottom(scrollToSeeNew);
|
||||
}
|
||||
},
|
||||
|
|
@ -483,6 +511,13 @@ export default {
|
|||
|
||||
sendMessage() {
|
||||
if (this.currentInput.length > 0) {
|
||||
// Is this an edit?
|
||||
if (this.editedEvent) {
|
||||
console.log("Edit");
|
||||
}
|
||||
|
||||
this.editedEvent = null; //TODO - Is this a good place to reset this?
|
||||
|
||||
util
|
||||
.sendTextMessage(
|
||||
this.$matrix.matrixClient,
|
||||
|
|
@ -640,6 +675,11 @@ export default {
|
|||
this.showEmojiPicker = true;
|
||||
},
|
||||
|
||||
edit(event) {
|
||||
this.editedEvent = event;
|
||||
this.currentInput = event.getContent().body;
|
||||
},
|
||||
|
||||
emojiSelected(e) {
|
||||
this.showEmojiPicker = false;
|
||||
if (this.selectedEvent) {
|
||||
|
|
@ -664,6 +704,22 @@ export default {
|
|||
console.log("Failed to send quick reaction:", err);
|
||||
});
|
||||
},
|
||||
|
||||
showContextMenuForEvent(event) {
|
||||
const ref = this.$refs[event.getId()];
|
||||
if (ref) {
|
||||
console.log("Got the ref", ref);
|
||||
}
|
||||
this.selectedEvent = event;
|
||||
this.showContextMenu = true;
|
||||
},
|
||||
|
||||
closeContextMenuIfOpen(e) {
|
||||
if (this.showContextMenu) {
|
||||
this.showContextMenu = false;
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,16 @@
|
|||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-card class="account ma-3">
|
||||
<v-card-title>Your account</v-card-title>
|
||||
<v-card-text>
|
||||
<div v-if="$matrix.currentUser.is_guest">
|
||||
<div>You don't have a Keanu account, yet ;)</div>
|
||||
<v-btn dark block @click.stop="upgradeAccount">Login</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<!-- EDIT dialog -->
|
||||
<v-dialog v-model="showEditDialog" class="ma-0 pa-0" width="50%">
|
||||
<v-card>
|
||||
|
|
@ -130,6 +140,16 @@ export default {
|
|||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
upgradeAccount() {
|
||||
this.$matrix.upgradeGuestAccount()
|
||||
.then(() => {
|
||||
console.log("Done");
|
||||
})
|
||||
.catch(err => {
|
||||
console.log("ERROR", err);
|
||||
})
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<div class="messageIn">
|
||||
<div class="audio-bubble">
|
||||
<audio controls :src="src">Audio file</audio>
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-avatar class="avatar" size="32" color="#ededed">
|
||||
<img
|
||||
v-if="messageEventAvatar(event)"
|
||||
:src="messageEventAvatar(event)"
|
||||
/>
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<div class="audio-bubble">
|
||||
<audio controls :src="src">Audio file</audio>
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-btn icon class="op-button" @click.stop="showContextMenu"
|
||||
><v-icon>more_vert</v-icon></v-btn
|
||||
>
|
||||
<v-avatar class="avatar" size="32" color="#ededed">
|
||||
<img v-if="messageEventAvatar(event)" :src="messageEventAvatar(event)" />
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<div class="time">
|
||||
{{ formatTime(event.event.origin_server_ts) }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<div class="messageIn">
|
||||
<div class="bubble image-bubble">
|
||||
<v-img :aspect-ratio="16 / 9" ref="image" :src="src" cover />
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-avatar class="avatar" size="40" color="grey">
|
||||
<img
|
||||
v-if="messageEventAvatar(event)"
|
||||
:src="messageEventAvatar(event)"
|
||||
/>
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<div class="bubble image-bubble">
|
||||
<v-img :aspect-ratio="16 / 9" ref="image" :src="src" cover />
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-btn icon class="op-button" @click.stop="showContextMenu"
|
||||
><v-icon>more_vert</v-icon></v-btn
|
||||
>
|
||||
<v-avatar class="avatar" size="32" color="#ededed">
|
||||
<img v-if="messageEventAvatar(event)" :src="messageEventAvatar(event)" />
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<div class="time">
|
||||
{{ formatTime(event.event.origin_server_ts) }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,25 @@
|
|||
<template>
|
||||
<div class="messageIn">
|
||||
<v-avatar class="avatar" size="32" color="#ededed">
|
||||
<img
|
||||
v-if="messageEventAvatar(event)"
|
||||
:src="messageEventAvatar(event)"
|
||||
/>
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<v-avatar class="avatar" size="32" color="#ededed">
|
||||
<img v-if="messageEventAvatar(event)" :src="messageEventAvatar(event)" />
|
||||
<span v-else class="white--text headline">{{
|
||||
messageEventDisplayName(event).substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
|
||||
<div class="bubble">
|
||||
<div class="message">{{ event.getContent().body }}
|
||||
<span class="edit-marker" v-if="event.replacingEventId()">(edited)</span>
|
||||
</div>
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
<div class="bubble">
|
||||
<div class="message">
|
||||
{{ event.getContent().body }}
|
||||
<span class="edit-marker" v-if="event.replacingEventId()"
|
||||
>(edited)</span
|
||||
>
|
||||
</div>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-btn icon class="op-button" @click.stop="showContextMenu"
|
||||
><v-icon>more_vert</v-icon></v-btn
|
||||
>
|
||||
<div class="sender">{{ messageEventDisplayName(event) }}</div>
|
||||
<div class="time">
|
||||
{{ formatTime(event.event.origin_server_ts) }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
<template>
|
||||
<div :class="{'messageOperations':true,'incoming':incoming,'outgoing':!incoming}">
|
||||
<div :class="{'message-operations':true,'incoming':incoming,'outgoing':!incoming}">
|
||||
<v-btn icon @click.stop="addReaction" class="ma-0 pa-0">
|
||||
<v-icon>mood</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-if="incoming" icon @click.stop="addReply" class="ma-0 pa-0">
|
||||
<v-icon>reply</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-if="isEditable" icon @click.stop="edit" class="ma-0 pa-0">
|
||||
<v-icon>edit</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -27,10 +33,24 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
isEditable() {
|
||||
return !this.incoming && this.event.getContent().msgtype == "m.text";
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addReaction() {
|
||||
this.$emit("close");
|
||||
this.$emit("addreaction", {event:this.event});
|
||||
},
|
||||
addReply() {
|
||||
this.$emit("close");
|
||||
this.$emit("addreply", {event:this.event});
|
||||
},
|
||||
edit() {
|
||||
this.$emit("close");
|
||||
this.$emit("edit", {event:this.event});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
<template>
|
||||
<div class="messageOut">
|
||||
<div class="bubble">
|
||||
<div class="message">{{ event.getContent().body }}
|
||||
<span class="edit-marker" v-if="event.replacingEventId()">(edited)</span>
|
||||
</div>
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
<div class="bubble">
|
||||
<div class="message">
|
||||
{{ event.getContent().body }}
|
||||
<span class="edit-marker" v-if="event.replacingEventId()"
|
||||
>(edited)</span
|
||||
>
|
||||
</div>
|
||||
<!-- <div class="sender">{{ "You" }}</div> -->
|
||||
<QuickReactions :event="event" :reactions="reactions" />
|
||||
</div>
|
||||
<v-btn icon class="op-button" @click.stop="showContextMenu"
|
||||
><v-icon>more_vert</v-icon></v-btn
|
||||
>
|
||||
<!-- <div class="sender">{{ "You" }}</div> -->
|
||||
<div class="time">
|
||||
{{ formatTime(event.event.origin_server_ts) }}
|
||||
</div>
|
||||
<div class="status">{{ event.status }}</div>
|
||||
<div class="status">{{ event.status }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ export default {
|
|||
computed: {
|
||||
},
|
||||
methods: {
|
||||
showContextMenu() {
|
||||
this.$emit("context-menu", this.event);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a display name given an event.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue