Merge branch '584-update-profile-view-feedback-changes' into 'dev'
Improvement based on "Update profile view" feedback See merge request keanuapp/keanuapp-weblite!287
This commit is contained in:
commit
7b434d2b3f
9 changed files with 104 additions and 180 deletions
|
|
@ -4,6 +4,7 @@ $app-background: #f6f6f6;
|
||||||
$main-desktop-width: 900px;
|
$main-desktop-width: 900px;
|
||||||
$dialog-desktop-width: 940px;
|
$dialog-desktop-width: 940px;
|
||||||
$very-very-purple: #536dfe;
|
$very-very-purple: #536dfe;
|
||||||
|
$lighter-gray: #FDFBF9;
|
||||||
|
|
||||||
$chat-background: $background;
|
$chat-background: $background;
|
||||||
$chat-standard-padding: 32px;
|
$chat-standard-padding: 32px;
|
||||||
|
|
|
||||||
|
|
@ -740,8 +740,7 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-operations-strut,
|
.message-operations-strut {
|
||||||
.avatar-operations-strut {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
@ -757,16 +756,6 @@ body {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-operations {
|
|
||||||
position: absolute;
|
|
||||||
width: fit-content;
|
|
||||||
background-color: white;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 0px 20px;
|
|
||||||
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.send-options {
|
.send-options {
|
||||||
z-index: 11; // Above mic button
|
z-index: 11; // Above mic button
|
||||||
}
|
}
|
||||||
|
|
@ -922,7 +911,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.room-info {
|
.room-info {
|
||||||
background-color: #FDFBF9;
|
background-color: $lighter-gray;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.chat-header {
|
.chat-header {
|
||||||
|
|
@ -1004,6 +993,19 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-icon-with-badge {
|
||||||
|
display: inline;
|
||||||
|
|
||||||
|
.user-badge {
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||||
|
position: absolute;
|
||||||
|
left: 35px;
|
||||||
|
top: 30px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.show-all {
|
.show-all {
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 14 * $chat-text-size;
|
font-size: 14 * $chat-text-size;
|
||||||
|
|
@ -1088,7 +1090,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile {
|
.profile {
|
||||||
background-color: #e8e8e8;
|
background-color: $lighter-gray;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.chat-header {
|
.chat-header {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
@ -1098,6 +1100,7 @@ body {
|
||||||
.v-card {
|
.v-card {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.05) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info {
|
.user-info {
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,6 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ref="avatarOperationsStrut" class="avatar-operations-strut">
|
|
||||||
<avatar-operations ref="avatarOperations" :style="avatarOpStyle" v-on:close="
|
|
||||||
showAvatarMenu = false;
|
|
||||||
showAvatarMenuAnchor = null;
|
|
||||||
" v-on:start-private-chat="startPrivateChat($event)" v-if="selectedEvent && showAvatarMenu" :room="room"
|
|
||||||
:originalEvent="selectedEvent" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Handle resizes, e.g. when soft keyboard is shown/hidden -->
|
<!-- Handle resizes, e.g. when soft keyboard is shown/hidden -->
|
||||||
<resize-observer ref="chatContainerResizer" @notify="handleChatContainerResize" />
|
<resize-observer ref="chatContainerResizer" @notify="handleChatContainerResize" />
|
||||||
|
|
||||||
|
|
@ -324,6 +316,12 @@
|
||||||
|
|
||||||
<CreatePollDialog :show="showCreatePollDialog" @close="showCreatePollDialog = false" />
|
<CreatePollDialog :show="showCreatePollDialog" @close="showCreatePollDialog = false" />
|
||||||
|
|
||||||
|
<UserProfileDialog
|
||||||
|
:show="showProfileDialog"
|
||||||
|
:activeMember="compActiveMember"
|
||||||
|
:room="room"
|
||||||
|
@close="showProfileDialog = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -332,7 +330,6 @@ import Vue from "vue";
|
||||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
||||||
import util, { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE } from "../plugins/utils";
|
import util, { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE } from "../plugins/utils";
|
||||||
import MessageOperations from "./messages/MessageOperations.vue";
|
import MessageOperations from "./messages/MessageOperations.vue";
|
||||||
import AvatarOperations from "./messages/AvatarOperations.vue";
|
|
||||||
import ChatHeader from "./ChatHeader";
|
import ChatHeader from "./ChatHeader";
|
||||||
import ChatHeaderPrivate from "./ChatHeaderPrivate.vue";
|
import ChatHeaderPrivate from "./ChatHeaderPrivate.vue";
|
||||||
import VoiceRecorder from "./VoiceRecorder";
|
import VoiceRecorder from "./VoiceRecorder";
|
||||||
|
|
@ -342,6 +339,7 @@ import DirectChatWelcomeHeader from "./DirectChatWelcomeHeader";
|
||||||
import NoHistoryRoomWelcomeHeader from "./NoHistoryRoomWelcomeHeader.vue";
|
import NoHistoryRoomWelcomeHeader from "./NoHistoryRoomWelcomeHeader.vue";
|
||||||
import MessageOperationsBottomSheet from "./MessageOperationsBottomSheet";
|
import MessageOperationsBottomSheet from "./MessageOperationsBottomSheet";
|
||||||
import StickerPickerBottomSheet from "./StickerPickerBottomSheet";
|
import StickerPickerBottomSheet from "./StickerPickerBottomSheet";
|
||||||
|
import UserProfileDialog from "./UserProfileDialog.vue"
|
||||||
import BottomSheet from "./BottomSheet.vue";
|
import BottomSheet from "./BottomSheet.vue";
|
||||||
import ImageResize from "image-resize";
|
import ImageResize from "image-resize";
|
||||||
import CreatePollDialog from "./CreatePollDialog.vue";
|
import CreatePollDialog from "./CreatePollDialog.vue";
|
||||||
|
|
@ -399,10 +397,10 @@ export default {
|
||||||
MessageOperationsBottomSheet,
|
MessageOperationsBottomSheet,
|
||||||
StickerPickerBottomSheet,
|
StickerPickerBottomSheet,
|
||||||
BottomSheet,
|
BottomSheet,
|
||||||
AvatarOperations,
|
|
||||||
CreatePollDialog,
|
CreatePollDialog,
|
||||||
AudioLayout,
|
AudioLayout,
|
||||||
FileDropLayout
|
FileDropLayout,
|
||||||
|
UserProfileDialog
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -432,8 +430,6 @@ export default {
|
||||||
showNoRecordingAvailableDialog: false,
|
showNoRecordingAvailableDialog: false,
|
||||||
showContextMenu: false,
|
showContextMenu: false,
|
||||||
showContextMenuAnchor: null,
|
showContextMenuAnchor: null,
|
||||||
showAvatarMenu: false,
|
|
||||||
showAvatarMenuAnchor: null,
|
|
||||||
initialLoadDone: false,
|
initialLoadDone: false,
|
||||||
loading: false, // Set this to true during long operations to show a "spinner" overlay
|
loading: false, // Set this to true during long operations to show a "spinner" overlay
|
||||||
showRecorder: false,
|
showRecorder: false,
|
||||||
|
|
@ -489,7 +485,8 @@ export default {
|
||||||
/**
|
/**
|
||||||
* A timer to handle message retention/auto deletion
|
* A timer to handle message retention/auto deletion
|
||||||
*/
|
*/
|
||||||
retentionTimer: null
|
retentionTimer: null,
|
||||||
|
showProfileDialog: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -521,7 +518,7 @@ export default {
|
||||||
if (this.retentionTimer) {
|
if (this.retentionTimer) {
|
||||||
clearInterval(this.retentionTimer);
|
clearInterval(this.retentionTimer);
|
||||||
this.retentionTimer = null;
|
this.retentionTimer = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
|
@ -530,6 +527,10 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
compActiveMember() {
|
||||||
|
const currentUserId= this.selectedEvent?.sender.userId || this.$matrix.currentUserId
|
||||||
|
return this.joinedAndInvitedMembers.find(({userId}) => userId === currentUserId)
|
||||||
|
},
|
||||||
nonImageFiles() {
|
nonImageFiles() {
|
||||||
return this.isCurrentFileInputsAnArray && this.currentFileInputs.filter(file => !file?.type.includes("image/"))
|
return this.isCurrentFileInputsAnArray && this.currentFileInputs.filter(file => !file?.type.includes("image/"))
|
||||||
},
|
},
|
||||||
|
|
@ -615,30 +616,6 @@ export default {
|
||||||
showMessageOperations() {
|
showMessageOperations() {
|
||||||
return this.selectedEvent && this.showContextMenu;
|
return this.selectedEvent && this.showContextMenu;
|
||||||
},
|
},
|
||||||
avatarOpStyle() {
|
|
||||||
// Calculate where to show the context menu.
|
|
||||||
//
|
|
||||||
const ref = this.selectedEvent && this.$refs[this.selectedEvent.getId()];
|
|
||||||
var top = 0;
|
|
||||||
var left = "unset";
|
|
||||||
var right = "unset";
|
|
||||||
if (ref && ref[0]) {
|
|
||||||
if (this.showAvatarMenuAnchor) {
|
|
||||||
var rectAnchor = this.showAvatarMenuAnchor.getBoundingClientRect();
|
|
||||||
var rectChat = this.$refs.avatarOperationsStrut.getBoundingClientRect();
|
|
||||||
top = rectAnchor.top - rectChat.top;
|
|
||||||
if (this.$vuetify.rtl) {
|
|
||||||
right = (rectAnchor.right - rectChat.right)+ "px";
|
|
||||||
} else {
|
|
||||||
left = (rectAnchor.left - rectChat.left) + "px";
|
|
||||||
}
|
|
||||||
// if (left + 250 > rectChat.right) {
|
|
||||||
// left = rectChat.right - 250; // Pretty ugly, but we want to make sure it does not escape the screen, and we don't have the exakt width of it (yet)!
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "top:" + top + "px;left:" + left + ";right:" + right;
|
|
||||||
},
|
|
||||||
canRecordAudio() {
|
canRecordAudio() {
|
||||||
return util.browserCanRecordAudio();
|
return util.browserCanRecordAudio();
|
||||||
},
|
},
|
||||||
|
|
@ -910,7 +887,7 @@ export default {
|
||||||
if (this.retentionTimer) {
|
if (this.retentionTimer) {
|
||||||
clearInterval(this.retentionTimer);
|
clearInterval(this.retentionTimer);
|
||||||
this.retentionTimer = null;
|
this.retentionTimer = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
removeTimedOutEvents(events) {
|
removeTimedOutEvents(events) {
|
||||||
|
|
@ -921,7 +898,7 @@ export default {
|
||||||
}
|
}
|
||||||
return events.filter((e) => {
|
return events.filter((e) => {
|
||||||
if (maxLifetime > 0 && !e.isState()) { // Keep all state events
|
if (maxLifetime > 0 && !e.isState()) { // Keep all state events
|
||||||
return e.getLocalAge() < maxLifetime;
|
return e.getLocalAge() < maxLifetime;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
@ -1700,50 +1677,20 @@ export default {
|
||||||
showAvatarMenuForEvent(e) {
|
showAvatarMenuForEvent(e) {
|
||||||
const event = e.event;
|
const event = e.event;
|
||||||
this.selectedEvent = event;
|
this.selectedEvent = event;
|
||||||
this.showAvatarMenu = true;
|
|
||||||
this.showAvatarMenuAnchor = e.anchor;
|
this.showProfileDialog = true
|
||||||
},
|
},
|
||||||
|
|
||||||
viewProfile() {
|
viewProfile() {
|
||||||
this.$navigation.push({ name: "Profile" }, 1);
|
this.$navigation.push({ name: "Profile" }, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
startPrivateChat(e) {
|
|
||||||
this.loading = true;
|
|
||||||
this.$matrix
|
|
||||||
.getOrCreatePrivateChat(e.event.getSender())
|
|
||||||
.then((room) => {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$navigation.push(
|
|
||||||
{
|
|
||||||
name: "Chat",
|
|
||||||
params: {
|
|
||||||
roomId: util.sanitizeRoomId(room.getCanonicalAlias() || room.roomId),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
closeContextMenusIfOpen(e) {
|
closeContextMenusIfOpen(e) {
|
||||||
if (this.showContextMenu) {
|
if (this.showContextMenu) {
|
||||||
this.showContextMenu = false;
|
this.showContextMenu = false;
|
||||||
this.showContextMenuAnchor = null;
|
this.showContextMenuAnchor = null;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
if (this.showAvatarMenu) {
|
|
||||||
this.showAvatarMenu = false;
|
|
||||||
this.showAvatarMenuAnchor = null;
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Stop Read Receipt timer */
|
/** Stop Read Receipt timer */
|
||||||
|
|
|
||||||
|
|
@ -120,26 +120,6 @@ export default {
|
||||||
room() {
|
room() {
|
||||||
return this.$matrix.currentRoom;
|
return this.$matrix.currentRoom;
|
||||||
},
|
},
|
||||||
memberAvatar() {
|
|
||||||
let roomMember;
|
|
||||||
if (this.room) {
|
|
||||||
this.room.getMembers().forEach(member => {
|
|
||||||
if (this.room.name === member.name) {
|
|
||||||
roomMember = member;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (roomMember) {
|
|
||||||
return roomMember.getAvatarUrl(
|
|
||||||
this.$matrix.matrixClient.getHomeserverUrl(),
|
|
||||||
40,
|
|
||||||
40,
|
|
||||||
"scale",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
notifications() {
|
notifications() {
|
||||||
return this.$matrix.joinedRooms.some(r => (r.roomId !== this.$matrix.currentRoomId && r.getCanonicalAlias() !== this.$matrix.currentRoomId) && r.getUnreadNotificationCount("total") > 0) ||
|
return this.$matrix.joinedRooms.some(r => (r.roomId !== this.$matrix.currentRoomId && r.getCanonicalAlias() !== this.$matrix.currentRoomId) && r.getUnreadNotificationCount("total") > 0) ||
|
||||||
this.$matrix.invites.length > 0;
|
this.$matrix.invites.length > 0;
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,6 @@ import RoomEncrypted from "./messages/RoomEncrypted.vue";
|
||||||
import RoomDeletionNotice from "./messages/RoomDeletionNotice.vue";
|
import RoomDeletionNotice from "./messages/RoomDeletionNotice.vue";
|
||||||
import DebugEvent from "./messages/DebugEvent.vue";
|
import DebugEvent from "./messages/DebugEvent.vue";
|
||||||
import MessageOperations from "./messages/MessageOperations.vue";
|
import MessageOperations from "./messages/MessageOperations.vue";
|
||||||
import AvatarOperations from "./messages/AvatarOperations.vue";
|
|
||||||
import ChatHeader from "./ChatHeader.vue";
|
import ChatHeader from "./ChatHeader.vue";
|
||||||
import VoiceRecorder from "./VoiceRecorder.vue";
|
import VoiceRecorder from "./VoiceRecorder.vue";
|
||||||
import RoomInfoBottomSheet from "./RoomInfoBottomSheet.vue";
|
import RoomInfoBottomSheet from "./RoomInfoBottomSheet.vue";
|
||||||
|
|
@ -141,7 +140,6 @@ export default {
|
||||||
MessageOperationsBottomSheet,
|
MessageOperationsBottomSheet,
|
||||||
StickerPickerBottomSheet,
|
StickerPickerBottomSheet,
|
||||||
BottomSheet,
|
BottomSheet,
|
||||||
AvatarOperations,
|
|
||||||
CreatePollDialog,
|
CreatePollDialog,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -264,7 +262,7 @@ export default {
|
||||||
if (parentEvent) {
|
if (parentEvent) {
|
||||||
Vue.set(parentEvent, "isMxThread", true);
|
Vue.set(parentEvent, "isMxThread", true);
|
||||||
Vue.set(event, "parentThread", parentEvent);
|
Vue.set(event, "parentThread", parentEvent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.events.filter(event => (event.replyEventId && !event.replyEvent)).forEach(event => {
|
this.events.filter(event => (event.replyEventId && !event.replyEvent)).forEach(event => {
|
||||||
const parentEvent = this.timelineSet.findEventById(event.replyEventId) || this.room.findEventById(event.replyEventId);
|
const parentEvent = this.timelineSet.findEventById(event.replyEventId) || this.room.findEventById(event.replyEventId);
|
||||||
|
|
|
||||||
|
|
@ -214,12 +214,17 @@
|
||||||
@click="onListItemClick(member)"
|
@click="onListItemClick(member)"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<v-avatar class="avatar" size="32" color="grey">
|
<div class="user-icon-with-badge">
|
||||||
<img v-if="memberAvatar(member)" :src="memberAvatar(member)" />
|
<v-avatar class="avatar" size="32" color="grey">
|
||||||
<span v-else class="white--text headline">{{
|
<img v-if="memberAvatar(member)" :src="memberAvatar(member)" />
|
||||||
member.name.substring(0, 1).toUpperCase()
|
<span v-else class="white--text headline">{{
|
||||||
}}</span>
|
member.name.substring(0, 1).toUpperCase()
|
||||||
</v-avatar>
|
}}</span>
|
||||||
|
</v-avatar>
|
||||||
|
<v-avatar circle class="user-badge" size="15" v-if="isAdmin(member) || isModerator(member)">
|
||||||
|
<v-icon>{{ `$vuetify.icons.${isAdmin(member)? 'make_admin' : 'make_moderator'}` }}</v-icon>
|
||||||
|
</v-avatar>
|
||||||
|
</div>
|
||||||
<span class="user-name">
|
<span class="user-name">
|
||||||
{{
|
{{
|
||||||
member.userId == $matrix.currentUserId
|
member.userId == $matrix.currentUserId
|
||||||
|
|
@ -266,7 +271,7 @@
|
||||||
{{ $t("room_info.version_info", { version: buildVersion }) }}
|
{{ $t("room_info.version_info", { version: buildVersion }) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MemberActionDialog
|
<UserProfileDialog
|
||||||
:show="showMemberActionConfirmation"
|
:show="showMemberActionConfirmation"
|
||||||
:activeMember="activeMember || members[0]"
|
:activeMember="activeMember || members[0]"
|
||||||
:room="room"
|
:room="room"
|
||||||
|
|
@ -304,7 +309,7 @@ import RoomExport from "../components/RoomExport";
|
||||||
import RoomAvatarPicker from "../components/RoomAvatarPicker";
|
import RoomAvatarPicker from "../components/RoomAvatarPicker";
|
||||||
import CopyLink from "../components/CopyLink.vue"
|
import CopyLink from "../components/CopyLink.vue"
|
||||||
import RoomTypeSelector from "./RoomTypeSelector.vue";
|
import RoomTypeSelector from "./RoomTypeSelector.vue";
|
||||||
import MemberActionDialog from "./MemberActionDialog.vue"
|
import UserProfileDialog from "./UserProfileDialog.vue"
|
||||||
import roomInfoMixin from "./roomInfoMixin";
|
import roomInfoMixin from "./roomInfoMixin";
|
||||||
import roomTypeMixin from "./roomTypeMixin";
|
import roomTypeMixin from "./roomTypeMixin";
|
||||||
import util, { STATE_EVENT_ROOM_TYPE } from "../plugins/utils";
|
import util, { STATE_EVENT_ROOM_TYPE } from "../plugins/utils";
|
||||||
|
|
@ -316,7 +321,7 @@ export default {
|
||||||
LeaveRoomDialog,
|
LeaveRoomDialog,
|
||||||
PurgeRoomDialog,
|
PurgeRoomDialog,
|
||||||
MessageRetentionDialog,
|
MessageRetentionDialog,
|
||||||
MemberActionDialog,
|
UserProfileDialog,
|
||||||
RoomExport,
|
RoomExport,
|
||||||
RoomAvatarPicker,
|
RoomAvatarPicker,
|
||||||
RoomTypeSelector,
|
RoomTypeSelector,
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<v-dialog
|
<v-dialog
|
||||||
|
v-if="activeMember"
|
||||||
v-model="showDialog"
|
v-model="showDialog"
|
||||||
v-show="room"
|
v-show="room"
|
||||||
class="ma-0 pa-0"
|
class="ma-0 pa-0"
|
||||||
:width="$vuetify.breakpoint.smAndUp ? '688px' : '95%'"
|
:width="$vuetify.breakpoint.smAndUp ? '688px' : '95%'"
|
||||||
>
|
>
|
||||||
<div class="dialog-content text-center member-action-dialog">
|
<div class="dialog-content text-center member-action-dialog">
|
||||||
<div>
|
<div class="pt-4">
|
||||||
<v-avatar class="avatar" size="56" color="grey">
|
<v-avatar class="avatar" size="56" color="grey">
|
||||||
<img v-if="memberAvatar(activeMember)" :src="memberAvatar(activeMember)" />
|
<img v-if="memberAvatarComp" :src="memberAvatarComp" />
|
||||||
<span v-else class="white--text headline">{{
|
<span v-else class="white--text headline">{{ firstLetterUserName }}</span>
|
||||||
activeMember.name.substring(0, 1).toUpperCase()
|
|
||||||
}}</span>
|
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
<div>
|
<div>
|
||||||
<span class="user-name">
|
<span class="user-name">
|
||||||
{{
|
{{
|
||||||
activeMember.userId == $matrix.currentUserId
|
isCurrentUser
|
||||||
? $t("room_info.user_you", {
|
? $t("room_info.user_you", {
|
||||||
user: activeMemberName(activeMember)
|
user: activeMemberNameComp
|
||||||
})
|
})
|
||||||
: $t("room_info.user", {
|
: $t("room_info.user", {
|
||||||
user: activeMemberName(activeMember)
|
user: activeMemberNameComp
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="isAdmin(activeMember)" class="user-power">
|
<span v-if="isAdminComp" class="user-power">
|
||||||
{{ $t("room_info.user_admin") }}
|
{{ $t("room_info.user_admin") }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="isModerator(activeMember)" class="user-power">
|
<span v-else-if="isModeratorComp" class="user-power">
|
||||||
{{ $t("room_info.user_moderator") }}
|
{{ $t("room_info.user_moderator") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="activeMember.userId != $matrix.currentUserId && sharedRooms.length">
|
<template v-if="activeMember.userId != $matrix.currentUserId && sharedRooms.length">
|
||||||
<span v-if="sharedRooms.length < 3">{{ $t("room_info.shared_room_number", {count: sharedRooms.length, name: activeMemberName(activeMember)}) }}</span>
|
<span v-if="sharedRooms.length < 3">{{ $t("room_info.shared_room_number", {count: sharedRooms.length, name: activeMemberNameComp}) }}</span>
|
||||||
<span v-else>{{ $t("room_info.shared_room_number_more", {count: sharedRooms.length, name: activeMemberName(activeMember)}) }}</span>
|
<span v-else>{{ $t("room_info.shared_room_number_more", {count: sharedRooms.length, name: activeMemberNameComp}) }}</span>
|
||||||
<p class="font-weight-light">{{ sharedRooms.slice(0, 3).join(", ") }}</p>
|
<p class="font-weight-light">{{ sharedRooms.slice(0, 3).join(", ") }}</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -43,18 +42,18 @@
|
||||||
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !$matrix.isDirectRoomWith(room, activeMember.userId)" class="start-private-chat clickable d-block text-none justify-start" @click="startPrivateChat(activeMember.userId)">
|
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !$matrix.isDirectRoomWith(room, activeMember.userId)" class="start-private-chat clickable d-block text-none justify-start" @click="startPrivateChat(activeMember.userId)">
|
||||||
<v-icon left>$vuetify.icons.direct_chat</v-icon> {{ $t("menu.direct_chat") }}
|
<v-icon left>$vuetify.icons.direct_chat</v-icon> {{ $t("menu.direct_chat") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<div v-if="canBanUser(activeMember)">
|
<div v-if="canBanUserComp">
|
||||||
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && canBanUser(activeMember)" class="start-private-chat clickable d-block text-none justify-start" @click="banUser(activeMember)">
|
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && canBanUserComp" class="start-private-chat clickable d-block text-none justify-start" @click="banUser(activeMember)">
|
||||||
<v-icon left>$vuetify.icons.kickout</v-icon> {{ $t("menu.user_kick_and_ban") }}
|
<v-icon left>$vuetify.icons.kickout</v-icon> {{ $t("menu.user_kick_and_ban") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !isAdmin(activeMember) && canMakeAdmin(activeMember)" class="start-private-chat clickable d-block text-none justify-start" @click="makeAdmin(activeMember)">
|
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !isAdminComp && canMakeAdminComp" class="start-private-chat clickable d-block text-none justify-start" @click="makeAdmin(activeMember)">
|
||||||
<v-icon left>$vuetify.icons.make_admin</v-icon> {{ $t("menu.user_make_admin") }}
|
<v-icon left>$vuetify.icons.make_admin</v-icon> {{ $t("menu.user_make_admin") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !isModerator(activeMember) && !isAdmin(activeMember) && canMakeModerator(activeMember)" class="start-private-chat clickable d-block text-none justify-start" @click="makeModerator(activeMember)">
|
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && !isModeratorComp && !isAdminComp && canMakeModeratorComp" class="start-private-chat clickable d-block text-none justify-start" @click="makeModerator(activeMember)">
|
||||||
<v-icon left>$vuetify.icons.make_moderator</v-icon> {{ $t("menu.user_make_moderator") }}
|
<v-icon left>$vuetify.icons.make_moderator</v-icon> {{ $t("menu.user_make_moderator") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && isModerator(activeMember) && canRevokeModerator(activeMember)" class="start-private-chat clickable d-block text-none justify-start" @click="revokeModerator(activeMember)">
|
<v-btn text x-large block v-if="activeMember.userId != $matrix.currentUserId && isModeratorComp && canRevokeModeratorComp" class="start-private-chat clickable d-block text-none justify-start" @click="revokeModerator(activeMember)">
|
||||||
<v-icon left>$vuetify.icons.revoke</v-icon> {{ $t("menu.user_revoke_moderator") }}
|
<v-icon left>$vuetify.icons.revoke</v-icon> {{ $t("menu.user_revoke_moderator") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -67,7 +66,7 @@ import DeviceList from "../components/DeviceList";
|
||||||
import util from "../plugins/utils";
|
import util from "../plugins/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MemberActionDialog",
|
name: "UserProfileDialog",
|
||||||
mixins: [roomInfoMixin],
|
mixins: [roomInfoMixin],
|
||||||
components: {
|
components: {
|
||||||
DeviceList
|
DeviceList
|
||||||
|
|
@ -80,7 +79,10 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
activeMember: {
|
activeMember: {
|
||||||
type: Object
|
type: Object,
|
||||||
|
default: function () {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -89,6 +91,36 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
canRevokeModeratorComp () {
|
||||||
|
return this.canRevokeModerator(this.activeMember)
|
||||||
|
},
|
||||||
|
isModeratorComp() {
|
||||||
|
return this.isModerator(this.activeMember)
|
||||||
|
},
|
||||||
|
canMakeModeratorComp() {
|
||||||
|
return this.canMakeModerator(this.activeMember)
|
||||||
|
},
|
||||||
|
canMakeAdminComp() {
|
||||||
|
return this.canMakeAdmin(this.activeMember)
|
||||||
|
},
|
||||||
|
canBanUserComp() {
|
||||||
|
return this.canBanUser(this.activeMember)
|
||||||
|
},
|
||||||
|
isAdminComp() {
|
||||||
|
return this.isAdmin(this.activeMember)
|
||||||
|
},
|
||||||
|
activeMemberNameComp() {
|
||||||
|
return this.activeMember.user ? this.activeMember.user.displayName : this.activeMember.name
|
||||||
|
},
|
||||||
|
isCurrentUser() {
|
||||||
|
return this.activeMember.userId == this.$matrix.currentUserId
|
||||||
|
},
|
||||||
|
firstLetterUserName() {
|
||||||
|
return this.activeMember.name.substring(0, 1).toUpperCase()
|
||||||
|
},
|
||||||
|
memberAvatarComp() {
|
||||||
|
return this.memberAvatar(this.activeMember)
|
||||||
|
},
|
||||||
joinedMembersByRoomId() {
|
joinedMembersByRoomId() {
|
||||||
const joinedRooms = this.$matrix.joinedRooms.filter(room => !this.$matrix.isDirectRoom(room)) || [];
|
const joinedRooms = this.$matrix.joinedRooms.filter(room => !this.$matrix.isDirectRoom(room)) || [];
|
||||||
return joinedRooms.map(room => ({
|
return joinedRooms.map(room => ({
|
||||||
|
|
@ -120,9 +152,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
activeMemberName(activeMember) {
|
|
||||||
return activeMember.user ? activeMember.user.displayName : activeMember.name
|
|
||||||
},
|
|
||||||
startPrivateChat(userId) {
|
startPrivateChat(userId) {
|
||||||
this.$matrix
|
this.$matrix
|
||||||
.getOrCreatePrivateChat(userId)
|
.getOrCreatePrivateChat(userId)
|
||||||
|
|
@ -38,7 +38,6 @@ import RoomTopicChanged from "./messages/RoomTopicChanged.vue";
|
||||||
import RoomAvatarChanged from "./messages/RoomAvatarChanged.vue";
|
import RoomAvatarChanged from "./messages/RoomAvatarChanged.vue";
|
||||||
import RoomHistoryVisibility from "./messages/RoomHistoryVisibility.vue";
|
import RoomHistoryVisibility from "./messages/RoomHistoryVisibility.vue";
|
||||||
import MessageOperations from "./messages/MessageOperations.vue";
|
import MessageOperations from "./messages/MessageOperations.vue";
|
||||||
import AvatarOperations from "./messages/AvatarOperations.vue";
|
|
||||||
import ChatHeader from "./ChatHeader";
|
import ChatHeader from "./ChatHeader";
|
||||||
import VoiceRecorder from "./VoiceRecorder";
|
import VoiceRecorder from "./VoiceRecorder";
|
||||||
import RoomInfoBottomSheet from "./RoomInfoBottomSheet";
|
import RoomInfoBottomSheet from "./RoomInfoBottomSheet";
|
||||||
|
|
@ -100,7 +99,6 @@ export default {
|
||||||
MessageOperationsBottomSheet,
|
MessageOperationsBottomSheet,
|
||||||
StickerPickerBottomSheet,
|
StickerPickerBottomSheet,
|
||||||
BottomSheet,
|
BottomSheet,
|
||||||
AvatarOperations,
|
|
||||||
CreatePollDialog,
|
CreatePollDialog,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
:class="{
|
|
||||||
'avatar-operations': true,
|
|
||||||
incoming: incoming,
|
|
||||||
outgoing: !incoming,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<v-btn id="btn-private-chat" v-if="incoming" text @click.stop="startPrivateChat" class="ma-0 pa-0"
|
|
||||||
>{{ $t("menu.start_private_chat") }}</v-btn
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import messageMixin from "./messageMixin";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mixins: [messageMixin],
|
|
||||||
mounted() {
|
|
||||||
// Any items to show?
|
|
||||||
if (this.room && this.event && this.$matrix.isDirectRoomWith(this.room, this.event.getSender())) {
|
|
||||||
this.$emit("close");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
startPrivateChat() {
|
|
||||||
this.$emit("close");
|
|
||||||
this.$emit("start-private-chat", { event: this.event });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import "@/assets/css/chat.scss";
|
|
||||||
</style>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue