parent
36ca5b50ff
commit
18f1945c19
10 changed files with 323 additions and 61 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "keanuapp-weblite",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.9",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.9",
|
||||
"dependencies": {
|
||||
"aes-js": "^3.1.2",
|
||||
"axios": "^0.21.0",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"appName": "Keanu Weblite",
|
||||
"product": "Convene",
|
||||
"productLink": "letsconvene.im",
|
||||
"defaultServer": "https://neo.keanu.im",
|
||||
"useShortCodeStickers": false,
|
||||
"analytics": {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,18 @@ $admin-fg: white;
|
|||
margin-top: $chat-standard-padding-xs;
|
||||
margin-bottom: $chat-standard-padding-xs;
|
||||
}
|
||||
.v-btn.avatar {
|
||||
font-family: "Inter", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 11 * $chat-text-size;
|
||||
color: black;
|
||||
background-color: white !important;
|
||||
border: 1px solid black;
|
||||
border-radius: $chat-standard-padding / 2;
|
||||
height: $chat-standard-padding;
|
||||
margin-top: $chat-standard-padding-xs;
|
||||
margin-bottom: $chat-standard-padding-xs;
|
||||
}
|
||||
}
|
||||
|
||||
.room-list-notification-count {
|
||||
|
|
@ -718,20 +730,29 @@ $admin-fg: white;
|
|||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.action {
|
||||
padding: 4px 20px;
|
||||
cursor: pointer;
|
||||
&::after {
|
||||
/* divider */
|
||||
content: " ";
|
||||
display: block;
|
||||
margin: 10px 0px;
|
||||
bottom: 0px;
|
||||
height: 1px;
|
||||
background-color: #e1e1e1;
|
||||
width: 100%;
|
||||
}
|
||||
.action-row {
|
||||
padding: 4px 20px;
|
||||
cursor: pointer;
|
||||
height: 55px;
|
||||
font-family: "Inter", sans-serif;
|
||||
font-size: 19px;
|
||||
color: black;
|
||||
position: relative;
|
||||
.v-icon {
|
||||
color: black !important;
|
||||
}
|
||||
&:not(:last-of-type):after {
|
||||
/* divider */
|
||||
position: absolute;
|
||||
content: " ";
|
||||
display: block;
|
||||
margin: 0px 10px;
|
||||
bottom: 0px;
|
||||
height: 1px;
|
||||
background-color: #e1e1e1;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -867,3 +888,13 @@ $admin-fg: white;
|
|||
vertical-align: middle;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.avatar-32 {
|
||||
font-size: 18 * $chat-text-size !important;
|
||||
&.clickable {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -116,7 +116,16 @@
|
|||
"password_new": "New password",
|
||||
"password_repeat": "Repeat new password",
|
||||
"display_name": "Display name"
|
||||
|
||||
},
|
||||
"profile_info_popup": {
|
||||
"you_are": "You are",
|
||||
"identity": "{displayName}",
|
||||
"identity_temporary": "{displayName}",
|
||||
"edit_profile": "Edit profile",
|
||||
"logout": "Logout",
|
||||
"want_more": "Want more?",
|
||||
"powered_by": "This room is powered by {product}. Learn more at {productLink} or go ahead and create another room!",
|
||||
"new_room": "+ New room"
|
||||
},
|
||||
"join": {
|
||||
"title": "Welcome to {roomName}",
|
||||
|
|
@ -164,10 +173,6 @@
|
|||
"user_you": "{user} (you)",
|
||||
"hide_all": "Hide",
|
||||
"show_all": "Show all >",
|
||||
"my_profile": "My Profile",
|
||||
"identity": "You are logged in as {displayName}.",
|
||||
"identity_temporary": "Your identity {displayName} is temporary. You can change your name or set a password to keep it.",
|
||||
"view_profile": "View",
|
||||
"leave_room": "Leave",
|
||||
"version_info": "Powered by Guardian Project. Version: {version}"
|
||||
},
|
||||
|
|
|
|||
32
src/components/ActionRow.vue
Normal file
32
src/components/ActionRow.vue
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<v-row class="action-row ma-0 pa-0" no-gutters align-content="center" v-on="$listeners">
|
||||
<v-col cols="auto" class="mr-2">
|
||||
<v-icon size="22">{{ icon }}</v-icon>
|
||||
</v-col>
|
||||
<v-col>{{ text }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ActionRow",
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
</style>
|
||||
|
|
@ -18,26 +18,42 @@
|
|||
<v-col cols="auto" class="text-end ma-0 pa-0">
|
||||
<v-btn text class="leave-button" @click.stop="leaveRoom">{{$t('room.leave')}}</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="auto" class="text-end ma-0 pa-0 ml-2">
|
||||
<v-avatar class="avatar-32 clickable" size="32" color="#e0e0e0" @click.stop="showProfileInfo = true">
|
||||
<img v-if="userAvatar" :src="userAvatar" />
|
||||
<span v-else class="white--text">{{
|
||||
userAvatarLetter
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- "REALLY LEAVE?" dialog -->
|
||||
<LeaveRoomDialog :show="showLeaveConfirmation" :room="room" @close="showLeaveConfirmation = false" />
|
||||
|
||||
<!-- PROFILE INFO POPUP -->
|
||||
<ProfileInfoPopup :show="showProfileInfo" @close="showProfileInfo = false" />
|
||||
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LeaveRoomDialog from '../components/LeaveRoomDialog';
|
||||
import ProfileInfoPopup from '../components/ProfileInfoPopup';
|
||||
import profileInfoMixin from '../components/profileInfoMixin';
|
||||
|
||||
export default {
|
||||
name: "ChatHeader",
|
||||
mixins: [profileInfoMixin],
|
||||
components: {
|
||||
LeaveRoomDialog
|
||||
LeaveRoomDialog,
|
||||
ProfileInfoPopup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
memberCount: null,
|
||||
showLeaveConfirmation: false
|
||||
showLeaveConfirmation: false,
|
||||
showProfileInfo: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@
|
|||
</v-row>
|
||||
</v-container>
|
||||
|
||||
<div class="action" @click="showEditPasswordDialog = true"><v-icon>lock</v-icon><span>{{$t('profile.set_password')}}</span></div>
|
||||
<div class="action" @click="editValue = displayName;showEditDisplaynameDialog = true"><v-icon>edit</v-icon><span>{{$t('profile.change_name')}}</span></div>
|
||||
<v-container class="mt-2 pa-5">
|
||||
<ActionRow @click="showEditPasswordDialog = true" :icon="'lock'" :text="$t('profile.set_password')" />
|
||||
<ActionRow @click="editValue = displayName;showEditDisplaynameDialog = true" :icon="'edit'" :text="$t('profile.change_name')" />
|
||||
</v-container>
|
||||
|
||||
<!-- edit password dialog -->
|
||||
<v-dialog v-model="showEditPasswordDialog" class="ma-0 pa-0" width="50%">
|
||||
|
|
@ -92,8 +94,13 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ActionRow from "./ActionRow.vue";
|
||||
|
||||
export default {
|
||||
name: "Profile",
|
||||
components: {
|
||||
ActionRow
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showEditPasswordDialog: false,
|
||||
|
|
@ -142,14 +149,6 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
logout() {
|
||||
//TODO - For guest accounts, show warning about not being able to rejoin.
|
||||
this.$store.dispatch("logout");
|
||||
this.$nextTick(() => {
|
||||
this.$navigation.push({path: "/login"}, -1);
|
||||
})
|
||||
},
|
||||
|
||||
setDisplayName(name) {
|
||||
this.$matrix.matrixClient.setDisplayName(name);
|
||||
},
|
||||
|
|
|
|||
162
src/components/ProfileInfoPopup.vue
Normal file
162
src/components/ProfileInfoPopup.vue
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
<template>
|
||||
<v-dialog
|
||||
v-model="showDialog"
|
||||
content-class="profile-info-popup"
|
||||
class="ma-0 pa-0"
|
||||
:width="$vuetify.breakpoint.smAndUp ? '60%' : '95%'"
|
||||
>
|
||||
<v-card flat>
|
||||
<v-card-text>
|
||||
<div class="you-are">{{ $t("profile_info_popup.you_are") }}</div>
|
||||
<v-container fluid>
|
||||
<v-row>
|
||||
<v-col class="username" cols="pa-2">
|
||||
<div v-if="$matrix.currentUser.is_guest">
|
||||
<i18n path="profile_info_popup.identity_temporary" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</div>
|
||||
<div v-else>
|
||||
<i18n path="profile_info_popup.identity" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="auto" class="pa-2">
|
||||
<v-avatar
|
||||
class="avatar-32"
|
||||
size="32"
|
||||
color="#e0e0e0"
|
||||
@click.stop="showProfileInfo = true"
|
||||
>
|
||||
<img v-if="userAvatar" :src="userAvatar" />
|
||||
<span v-else class="white--text">{{ userAvatarLetter }}</span>
|
||||
</v-avatar>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
|
||||
<v-container class="mt-4 pa-0">
|
||||
<ActionRow @click="viewProfile" :icon="'account_circle'" :text="$t('profile_info_popup.edit_profile')" />
|
||||
<ActionRow @click="logout" :icon="'logout'" :text="$t('profile_info_popup.logout')" />
|
||||
</v-container>
|
||||
|
||||
<div class="more-container">
|
||||
<div class="want_more">🙌 {{$t('profile_info_popup.want_more')}}</div>
|
||||
<i18n path="profile_info_popup.powered_by" tag="div">
|
||||
<template v-slot:product>{{ product }}</template>
|
||||
<template v-slot:productLink>
|
||||
<a :href="productLink">{{ productLink }}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
<div style="position:relative;width:100%;height: 40px">
|
||||
<v-btn class="new_room" right absolute text @click="createRoom">{{ $t('profile_info_popup.new_room') }}</v-btn></div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import profileInfoMixin from "./profileInfoMixin";
|
||||
import ActionRow from "./ActionRow.vue";
|
||||
import config from "../assets/config";
|
||||
|
||||
export default {
|
||||
name: "ProfileInfoPopup",
|
||||
mixins: [profileInfoMixin],
|
||||
components: {
|
||||
ActionRow
|
||||
},
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: function () {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
product() {
|
||||
return config.product;
|
||||
},
|
||||
productLink() {
|
||||
return config.productLink;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(newVal, ignoredOldVal) {
|
||||
this.showDialog = newVal;
|
||||
},
|
||||
},
|
||||
showDialog() {
|
||||
if (!this.showDialog) {
|
||||
this.$emit("close");
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
viewProfile() {
|
||||
this.showDialog = false;
|
||||
this.$navigation.push({ name: "Profile" }, 1);
|
||||
},
|
||||
createRoom() {
|
||||
this.showDialog = false;
|
||||
this.$navigation.push({ name: "CreateRoom" });
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
.profile-info-popup {
|
||||
font-family: "Inter", sans-serif !important;
|
||||
font-size: 16px;
|
||||
position: fixed;
|
||||
margin: 0px;
|
||||
top: 70px;
|
||||
right: 10px;
|
||||
border-radius: 40px;
|
||||
&::before {
|
||||
content: '▲';
|
||||
position: fixed;
|
||||
top: 57px;
|
||||
right: 22px;
|
||||
color: white;
|
||||
}
|
||||
.you-are {
|
||||
padding-top: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.username {
|
||||
border-radius: 4px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.more-container {
|
||||
border-radius: 10px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 20px;
|
||||
.want_more {
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 13 * $chat-text-size;
|
||||
}
|
||||
.new_room .v-btn__content {
|
||||
font-family: "Poppins", sans-serif !important;
|
||||
font-weight: 700 !important;
|
||||
font-size: 13 * $chat-text-size !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -170,35 +170,6 @@
|
|||
>
|
||||
</div>
|
||||
|
||||
<v-card class="account ma-3" flat>
|
||||
<v-card-title class="h2">{{ $t("room_info.my_profile") }}</v-card-title>
|
||||
<v-card-text>
|
||||
<div>
|
||||
<div v-if="$matrix.currentUser.is_guest">
|
||||
<i18n path="room_info.identity_temporary" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</div>
|
||||
<div v-else>
|
||||
<i18n path="room_info.identity" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</div>
|
||||
<v-btn
|
||||
depressed
|
||||
block
|
||||
class="outlined-button"
|
||||
@click.stop="viewProfile"
|
||||
>{{ $t("room_info.view_profile") }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<div class="build-version">
|
||||
{{ $t("room_info.version_info", { version: buildVersion }) }}
|
||||
</div>
|
||||
|
|
|
|||
44
src/components/profileInfoMixin.js
Normal file
44
src/components/profileInfoMixin.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
export default {
|
||||
computed: {
|
||||
user() {
|
||||
if (!this.$matrix.matrixClient) {
|
||||
return null;
|
||||
}
|
||||
return this.$matrix.matrixClient.getUser(this.$matrix.currentUserId);
|
||||
},
|
||||
|
||||
displayName() {
|
||||
if (!this.user) {
|
||||
return null;
|
||||
}
|
||||
return (this.user.displayName || this.user.userId);
|
||||
},
|
||||
|
||||
userAvatar() {
|
||||
if (!this.user || !this.user.avatarUrl) {
|
||||
return null;
|
||||
}
|
||||
return this.$matrix.matrixClient.mxcUrlToHttp(this.user.avatarUrl, 80, 80, 'scale', true);
|
||||
},
|
||||
|
||||
userAvatarLetter() {
|
||||
if (!this.user) {
|
||||
return null;
|
||||
}
|
||||
return (this.user.displayName || this.user.userId.substring(1)).substring(0, 1).toUpperCase();
|
||||
},
|
||||
|
||||
passwordsMatch() {
|
||||
return this.newPassword1 && this.newPassword2 && this.newPassword1 == this.newPassword2;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
//TODO - For guest accounts, show warning about not being able to rejoin.
|
||||
this.$store.dispatch("logout");
|
||||
this.$nextTick(() => {
|
||||
this.$navigation.push({path: "/login"}, -1);
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue