Start on Vue 3 changes
This commit is contained in:
parent
dcc4784bfd
commit
c913a40e18
35 changed files with 3570 additions and 1913 deletions
|
|
@ -6,7 +6,7 @@
|
|||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="icon" id="favicon" href="/favicon.ico" />
|
||||
<title></title>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="apple-touch-icon" href="./icons/icon-72x72.png" sizes="72x72" />
|
||||
<link rel="apple-touch-icon" href="./icons/icon-96x96.png" sizes="96x96" />
|
||||
<link rel="apple-touch-icon" href="./icons/icon-128x128.png" sizes="128x128" />
|
||||
|
|
@ -47,6 +47,7 @@
|
|||
<lottie-player autoplay loop mode="normal" src="./loader.json" style="width: 128px"> </lottie-player>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app2"></div>
|
||||
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
|
|
|||
2003
package-lock.json
generated
2003
package-lock.json
generated
File diff suppressed because it is too large
Load diff
24
package.json
24
package.json
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@matrix-org/olm": "^3.2.12",
|
||||
"@vitejs/plugin-vue2": "^2.3.3",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"aes-js": "^3.1.2",
|
||||
"axios": "^1.4.0",
|
||||
"browserify-fs": "^1.0.0",
|
||||
|
|
@ -40,21 +40,23 @@
|
|||
"roboto-fontface": "*",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"util": "^0.12.5",
|
||||
"v-emoji-picker": "^2.3.1",
|
||||
"vue": "^2.7.16",
|
||||
"vue": "^3.5.13",
|
||||
"vue-3-sanitize": "^0.1.4",
|
||||
"vue-clipboard2": "^0.3.3",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-resize": "^1.0",
|
||||
"vue-router": "^3.6.5",
|
||||
"vue-sanitize": "^0.2.3",
|
||||
"vue-i18n": "^11.1.3",
|
||||
"vue-router": "^4.5.1",
|
||||
"vue-swipeable-bottom-sheet": "^0.0.5",
|
||||
"vuetify": "^2.7.2",
|
||||
"vuex": "^3.5.1",
|
||||
"vue3-emoji-picker": "^1.1.8",
|
||||
"vue3-resize": "^0.2.0",
|
||||
"vuetify": "^3.8.3",
|
||||
"vuex": "^4.1.0",
|
||||
"vuex-persist": "^3.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^28.0.3",
|
||||
"@types/jszip": "^3.4.0",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"eslint": "^7.0",
|
||||
|
|
@ -65,9 +67,9 @@
|
|||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.2",
|
||||
"vite-plugin-static-copy": "^2.3.0",
|
||||
"vite-plugin-vuetify": "^2.1.1",
|
||||
"vue-cli-plugin-vuetify": "^2.5.8",
|
||||
"vue-template-compiler": "^2.7.16",
|
||||
"vuetify-loader": "^1.3.0"
|
||||
"vue-template-compiler": "^2.7.16"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
v-on:redact="redact(selectedEvent)"
|
||||
v-on:download="download(selectedEvent)"
|
||||
v-on:more="
|
||||
isEmojiQuickReaction= true
|
||||
isEmojiQuickReaction=true;
|
||||
showMoreMessageOperations({event: selectedEvent, anchor: $event.anchor})
|
||||
"
|
||||
:userCanSendReactionAndAnswerPoll="$matrix.userCanSendReactionAndAnswerPollInCurrentRoom"
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
v-on:download="download(event)"
|
||||
v-on:poll-closed="pollWasClosed(event)"
|
||||
v-on:more="
|
||||
isEmojiQuickReaction = true
|
||||
isEmojiQuickReaction = true;
|
||||
showMoreMessageOperations({event: event, anchor: $event.anchor})
|
||||
"
|
||||
v-on:layout-change="onLayoutChange"
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
|
||||
<v-col class="input-area-button text-center flex-grow-0 flex-shrink-1 input-more-icon">
|
||||
<v-btn fab small elevation="0" v-blur @click.stop="
|
||||
isEmojiQuickReaction = false
|
||||
isEmojiQuickReaction = false;
|
||||
showMoreMessageOperations($event)
|
||||
">
|
||||
<v-icon>$vuetify.icons.addReaction</v-icon>
|
||||
|
|
@ -313,7 +313,7 @@
|
|||
</div>
|
||||
|
||||
<MessageOperationsBottomSheet ref="messageOperationsSheet">
|
||||
<VEmojiPicker ref="emojiPicker" @select="emojiSelected" :i18n="i18nEmoji"/>
|
||||
<EmojiPicker ref="emojiPicker" @select="emojiSelected" :i18n="i18nEmoji"/>
|
||||
</MessageOperationsBottomSheet>
|
||||
|
||||
<StickerPickerBottomSheet ref="stickerPickerSheet" v-on:selectSticker="sendSticker" />
|
||||
|
|
@ -366,7 +366,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
||||
import util, { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE, ROOM_TYPE_CHANNEL } from "../plugins/utils";
|
||||
import MessageOperations from "./messages/MessageOperations.vue";
|
||||
|
|
@ -397,7 +396,7 @@ import MessageOperationsChannel from './messages/channel/MessageOperationsChanne
|
|||
import { imageSize } from "image-size";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import RoomExport from "./RoomExport.vue";
|
||||
import { VEmojiPicker } from 'v-emoji-picker';
|
||||
import EmojiPicker from 'vue3-emoji-picker';
|
||||
|
||||
|
||||
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
|
||||
|
|
@ -452,7 +451,7 @@ export default {
|
|||
MessageErrorHandler,
|
||||
MessageOperationsChannel,
|
||||
RoomExport,
|
||||
VEmojiPicker
|
||||
EmojiPicker
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -755,17 +754,17 @@ export default {
|
|||
let lastDisplayedEvent = undefined;
|
||||
events = events.flatMap((e) => {
|
||||
let result = [];
|
||||
Vue.set(e, "component", this.componentForEvent(e, false));
|
||||
e.component = this.componentForEvent(e, false);
|
||||
if (e.getId() == this.readMarker && showReadMarker) {
|
||||
const readMarkerEvent = ROOM_READ_MARKER_EVENT_PLACEHOLDER;
|
||||
Vue.set(readMarkerEvent, "component", this.componentForEvent(readMarkerEvent, false));
|
||||
readMarkerEvent["component"] = this.componentForEvent(readMarkerEvent, false);
|
||||
if (readMarkerEvent.component) {
|
||||
Vue.set(e, "nextDisplayedEvent", lastDisplayedEvent);
|
||||
e["nextDisplayedEvent"] = lastDisplayedEvent;
|
||||
}
|
||||
result.push(readMarkerEvent);
|
||||
}
|
||||
if (e.component) {
|
||||
Vue.set(e, "nextDisplayedEvent", lastDisplayedEvent);
|
||||
e["nextDisplayedEvent"] = lastDisplayedEvent;
|
||||
lastDisplayedEvent = e;
|
||||
if (e.getSender() !== this.$matrix.currentUserId) {
|
||||
showReadMarker = true;
|
||||
|
|
@ -1006,8 +1005,8 @@ export default {
|
|||
if (this.room) {
|
||||
const pinnedEvents = this.$matrix.getPinnedEvents(this.room);
|
||||
updated.forEach((e) => {
|
||||
Vue.set(e, "isPinned", pinnedEvents.includes(e.threadParent ? e.threadParent.getId() : e.getId()));
|
||||
Vue.set(e, "isChannelMessage", (this.room && this.roomDisplayType == ROOM_TYPE_CHANNEL));
|
||||
e["isPinned"] = pinnedEvents.includes(e.threadParent ? e.threadParent.getId() : e.getId());
|
||||
e["isChannelMessage"] = (this.room && this.roomDisplayType == ROOM_TYPE_CHANNEL);
|
||||
});
|
||||
|
||||
updated = updated.sort((e1, e2) => {
|
||||
|
|
@ -1080,7 +1079,7 @@ export default {
|
|||
}
|
||||
|
||||
this.reverseOrder = (this.room && this.roomDisplayType == ROOM_TYPE_CHANNEL);
|
||||
Vue.set(this.room, "displayType", this.roomDisplayType);
|
||||
this.room["displayType"] = this.roomDisplayType;
|
||||
|
||||
// Listen to events
|
||||
this.$matrix.on("Room.timeline", this.onEvent);
|
||||
|
|
@ -1300,8 +1299,8 @@ export default {
|
|||
setParentThread(event) {
|
||||
const parentEvent = this.timelineSet.findEventById(event.threadRootId) || this.room.findEventById(event.threadRootId);
|
||||
if (parentEvent) {
|
||||
Vue.set(parentEvent, "isMxThread", true);
|
||||
Vue.set(event, "parentThread", parentEvent);
|
||||
parentEvent["isMxThread"] = true;
|
||||
event["parentThread"] = parentEvent;
|
||||
} else {
|
||||
// Try to load from server.
|
||||
this.$matrix.matrixClient.getEventTimeline(this.timelineSet, event.threadRootId)
|
||||
|
|
@ -1311,8 +1310,8 @@ export default {
|
|||
if (parentEvent) {
|
||||
this.setEvents(this.timelineWindow.getEvents());
|
||||
const fn = () => {
|
||||
Vue.set(parentEvent, "isMxThread", true);
|
||||
Vue.set(event, "parentThread", parentEvent);
|
||||
parentEvent["isMxThread"] = true;
|
||||
event["parentThread"] = parentEvent;
|
||||
};
|
||||
if (this.initialLoadDone) {
|
||||
const sel = "[eventId=\"" + parentEvent.getId() + "\"]";
|
||||
|
|
@ -1334,7 +1333,7 @@ export default {
|
|||
setReplyToEvent(event) {
|
||||
const parentEvent = this.timelineSet.findEventById(event.replyEventId) || this.room.findEventById(event.replyEventId);
|
||||
if (parentEvent) {
|
||||
Vue.set(event, "replyEvent", parentEvent);
|
||||
event["replyEvent"] = parentEvent;
|
||||
} else {
|
||||
// Try to load from server.
|
||||
this.$matrix.matrixClient.getEventTimeline(this.timelineSet, event.replyEventId)
|
||||
|
|
@ -1343,7 +1342,7 @@ export default {
|
|||
const parentEvent = tl.getEvents().find((e) => e.getId() === event.replyEventId);
|
||||
if (parentEvent) {
|
||||
this.setEvents(this.timelineWindow.getEvents());
|
||||
const fn = () => {Vue.set(event, "replyEvent", parentEvent);};
|
||||
const fn = () => {event["replyEvent"] = parentEvent;};
|
||||
if (this.initialLoadDone) {
|
||||
const sel = "[eventId=\"" + parentEvent.getId() + "\"]";
|
||||
const element = document.querySelector(sel);
|
||||
|
|
@ -1486,20 +1485,17 @@ export default {
|
|||
outputType: "blob",
|
||||
})
|
||||
.then((img) => {
|
||||
Vue.set(
|
||||
fileObj,
|
||||
"scaled",
|
||||
fileObj["scaled"] =
|
||||
new File([img], file.name, {
|
||||
type: img.type,
|
||||
lastModified: Date.now(),
|
||||
})
|
||||
);
|
||||
Vue.set(fileObj, "useScaled", true);
|
||||
Vue.set(fileObj, "scaledSize", img.size);
|
||||
Vue.set(fileObj, "scaledDimensions", {
|
||||
});
|
||||
fileObj["useScaled"] = true;
|
||||
fileObj["scaledSize"] = img.size;
|
||||
fileObj["scaledDimensions"] = {
|
||||
width: newWidth,
|
||||
height: newHeight,
|
||||
});
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Resize failed:", err);
|
||||
|
|
|
|||
|
|
@ -107,11 +107,11 @@
|
|||
<v-col class="py-0">
|
||||
<v-checkbox id="chk-accept-ua" class="mt-0" v-model="acceptUA">
|
||||
<template slot="label">
|
||||
<i18n path="join.accept_ua" tag="span">
|
||||
<i18n-t keypath="join.accept_ua" tag="span">
|
||||
<template v-slot:agreement>
|
||||
<a href="./ua.html" target="_blank" @click.stop>{{ $t("join.ua") }}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</template>
|
||||
</v-checkbox>
|
||||
</v-col>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,10 @@
|
|||
:value="device.deviceId"
|
||||
>
|
||||
<template v-slot:default="{ active }">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ displayName(device) }}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{
|
||||
verificationStatus(device)
|
||||
}}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action v-if="active">
|
||||
<v-btn icon>
|
||||
<v-icon
|
||||
|
|
|
|||
|
|
@ -43,12 +43,10 @@
|
|||
member.name.substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ memberName(member) }}</v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
v-text="member.userId"
|
||||
></v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-subtitle
|
||||
v-text="member.userId"
|
||||
></v-list-item-subtitle>
|
||||
<v-list-item-action>
|
||||
<v-btn icon v-if="active">
|
||||
<v-icon color="grey lighten-1">check</v-icon>
|
||||
|
|
|
|||
|
|
@ -60,11 +60,11 @@
|
|||
|
||||
<v-checkbox id="chk-accept-ua" class="mt-0" v-model="acceptUA">
|
||||
<template slot="label">
|
||||
<i18n path="join.accept_ua" tag="span">
|
||||
<i18n-t keypath="join.accept_ua" tag="span">
|
||||
<template v-slot:agreement>
|
||||
<a href="./ua.html" target="_blank" @click.stop>{{ $t("join.ua") }}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</template>
|
||||
</v-checkbox>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
v-if="$matrix.currentUser.is_guest && lastRoom"
|
||||
class="dialog-text"
|
||||
>
|
||||
<i18n path="leave.text_public_lastroom" tag="p">
|
||||
<i18n-t keypath="leave.text_public_lastroom" tag="p">
|
||||
<template v-slot:user>
|
||||
<span>{{ $matrix.currentUserDisplayName }}</span>
|
||||
</template>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
$t("leave.create_account")
|
||||
}}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div v-else class="dialog-text">{{ $t("leave.text_public") }}</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ import { mapState } from 'vuex'
|
|||
export default {
|
||||
name: "Profile",
|
||||
mixins: [profileInfoMixin],
|
||||
inject: ['$matrix'],
|
||||
components: {
|
||||
ActionRow,
|
||||
SelectLanguageDialog,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<v-row>
|
||||
<v-col :class="['username', { 'editable': editDisplayName }]" cols="pa-2" ref="username">
|
||||
<div v-if="$matrix.currentUser.is_guest">
|
||||
<i18n path="profile_info_popup.identity_temporary" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity_temporary" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<input v-model="displayName"
|
||||
@keyup.enter="$event => $event.target.blur()"
|
||||
|
|
@ -16,10 +16,10 @@
|
|||
editDisplayName = !editDisplayName;
|
||||
" @focus="editDisplayName = !editDisplayName" />
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div v-else>
|
||||
<i18n path="profile_info_popup.identity" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<input
|
||||
v-model="displayName"
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
@focus="editDisplayName = !editDisplayName"
|
||||
/>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="auto" class="pa-2">
|
||||
|
|
@ -44,12 +44,12 @@
|
|||
<div class="want_more">
|
||||
🙌 {{ $t("profile_info_popup.want_more") }}
|
||||
</div>
|
||||
<i18n path="profile_info_popup.powered_by" tag="div">
|
||||
<i18n-t keypath="profile_info_popup.powered_by" tag="div">
|
||||
<template v-slot:product>{{ product }}</template>
|
||||
<template v-slot:productLink>
|
||||
<a :href="'//' + productLink">{{ productLink }}</a>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
<div class="text-end" v-if="!$config.hide_add_room_on_home">
|
||||
<v-btn id="btn-new-room" class="new_room" text @click="createRoom">
|
||||
{{ $t("profile_info_popup.new_room") }}
|
||||
|
|
|
|||
|
|
@ -50,18 +50,18 @@
|
|||
v-if="$matrix.currentUser.is_guest"
|
||||
class="d-inline-block me-2 white--text"
|
||||
>
|
||||
<i18n path="profile_info_popup.identity_temporary" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity_temporary" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div v-else class="d-inline-block me-2 white--text">
|
||||
<i18n path="profile_info_popup.identity" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<v-avatar
|
||||
class="avatar-32 d-inline-block"
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import MessageIncomingText from "./messages/MessageIncomingText.vue";
|
||||
import MessageIncomingFile from "./messages/MessageIncomingFile.vue";
|
||||
import MessageIncomingImage from "./messages/MessageIncomingImage.vue";
|
||||
|
|
@ -261,14 +260,14 @@ export default {
|
|||
this.events.filter(event => (event.threadRootId && !event.parentThread)).forEach(event => {
|
||||
const parentEvent = this.timelineSet.findEventById(event.threadRootId) || this.room.findEventById(event.threadRootId);
|
||||
if (parentEvent) {
|
||||
Vue.set(parentEvent, "isMxThread", true);
|
||||
Vue.set(event, "parentThread", parentEvent);
|
||||
parentEvent["isMxThread"] = true;
|
||||
event["parentThread"] = parentEvent;
|
||||
}
|
||||
});
|
||||
this.events.filter(event => (event.replyEventId && !event.replyEvent)).forEach(event => {
|
||||
const parentEvent = this.timelineSet.findEventById(event.replyEventId) || this.room.findEventById(event.replyEventId);
|
||||
if (parentEvent) {
|
||||
Vue.set(event, "replyEvent", parentEvent);
|
||||
event["replyEvent"] = parentEvent;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -112,9 +112,7 @@
|
|||
<v-list-item-avatar>
|
||||
<v-icon color="black">{{ item.icon }}</v-icon>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="item.text"></v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title v-text="item.text"></v-list-item-title>
|
||||
<v-list-item-action>
|
||||
<v-btn icon v-if="active">
|
||||
<v-icon color="grey lighten-1">check</v-icon>
|
||||
|
|
@ -142,7 +140,7 @@
|
|||
<v-card-title class="h2">{{ $t("room_info.message_retention") }}</v-card-title>
|
||||
<v-card-text v-if="canViewRetentionPolicy">
|
||||
<v-list v-if="canChangeRetentionPolicy">
|
||||
<v-list-item link v-on:click="showMessageRetentionDialog = true" class="px-0">
|
||||
<v-list-item link v-on:click="showMessageRetentionDialog = true" class="px-0 pb-0">
|
||||
<v-list-item-avatar class="mr-0 pb-0 mb-0">
|
||||
<v-img
|
||||
contain
|
||||
|
|
@ -151,9 +149,7 @@
|
|||
src="@/assets/icons/timer.svg"
|
||||
/>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content class="pb-0">
|
||||
{{ messageRetentionDisplay }}
|
||||
</v-list-item-content>
|
||||
{{ messageRetentionDisplay }}
|
||||
|
||||
<v-list-item-action class="pb-0 mb-0">
|
||||
<v-icon>arrow_drop_down</v-icon>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@
|
|||
<v-list-item-avatar class="round" size="42" color="#d9d9d9">
|
||||
<v-icon size="11">$vuetify.icons.ic_new_room</v-icon>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="room-list-new-room">{{
|
||||
$t("menu.new_room")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<!-- invites -->
|
||||
|
|
@ -22,10 +20,8 @@
|
|||
room.name.substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="room-list-name">{{ room.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ room.topic }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-btn id="btn-accept" class="filled-button" depressed color="black" @click.stop="acceptInvitation(room)">{{
|
||||
$t("menu.join") }}</v-btn>
|
||||
|
|
@ -41,14 +37,12 @@
|
|||
room.name.substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="room-list-name">{{ room.name }}
|
||||
<!-- <v-icon class="ml-2 mb-1" size="10" v-if="isPublic(room)">$vuetify.icons.ic_public</v-icon> -->
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle class="room-list-new-messages" v-if="notificationCount(room) > 0">
|
||||
{{ $t("room.room_list_new_messages", { count: notificationCount(room) }) }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-icon size="16" v-if="room.roomId == $matrix.currentRoomId">$vuetify.icons.ic_circle_filled</v-icon>
|
||||
<v-icon size="16" v-else>$vuetify.icons.ic_circle</v-icon>
|
||||
|
|
@ -60,7 +54,6 @@
|
|||
|
||||
<script>
|
||||
import util from "../plugins/utils";
|
||||
import Vue from "vue";
|
||||
import AuthedImage from "./AuthedImage.vue";
|
||||
|
||||
export default {
|
||||
|
|
@ -143,7 +136,7 @@ export default {
|
|||
},
|
||||
|
||||
acceptInvitation(room) {
|
||||
Vue.set(this.roomsProcessing, room.roomId, true);
|
||||
this.roomsProcessing[room.roomId] = true;
|
||||
this.$matrix.matrixClient
|
||||
.joinRoom(room.roomId)
|
||||
.then((ignoredRoom) => {
|
||||
|
|
@ -165,19 +158,19 @@ export default {
|
|||
console.error("Failed to accept invite: ", err);
|
||||
})
|
||||
.finally(() => {
|
||||
Vue.delete(this.roomsProcessing, room.roomId);
|
||||
delete this.roomsProcessing[room.roomId];
|
||||
});
|
||||
},
|
||||
|
||||
rejectInvitation(room) {
|
||||
Vue.set(this.roomsProcessing, room.roomId, true);
|
||||
this.roomsProcessing[room.roomId] = true;
|
||||
this.$matrix
|
||||
.leaveRoom(room.roomId)
|
||||
.catch((err) => {
|
||||
console.error("Failed to reject invite: ", err);
|
||||
})
|
||||
.finally(() => {
|
||||
Vue.delete(this.roomsProcessing, room.roomId);
|
||||
delete this.roomsProcessing[room.roomId];
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@
|
|||
<template v-slot:selection="{ item }">{{ item.title }}</template>
|
||||
<template v-slot:item="{ item, attrs, on }">
|
||||
<v-list-item v-on="on" v-bind="attrs" #default="{}">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ item.title }}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ item.description }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{ item.title }}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ item.description }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-select>
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@
|
|||
:outlined="!dark"
|
||||
>{{ $t("profile_info_popup.you_are") }}
|
||||
<span v-if="$matrix.currentUser.is_guest">
|
||||
<i18n path="profile_info_popup.identity_temporary" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity_temporary" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</span>
|
||||
<span v-else>
|
||||
<i18n path="profile_info_popup.identity" tag="span">
|
||||
<i18n-t keypath="profile_info_popup.identity" tag="span">
|
||||
<template v-slot:displayName>
|
||||
<b>{{ displayName }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</span>
|
||||
<v-avatar color="#e0e0e0" right @click.stop="viewProfile">
|
||||
<AuthedImage v-if="userAvatar" :src="userAvatar" />
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
>
|
||||
<v-list>
|
||||
<v-subheader class="text-uppercase"> {{ $tc("message.seen_by") }}</v-subheader>
|
||||
<v-list-item v-for="(member, index) in seenBy" :key="index">
|
||||
<v-list-item v-for="(member, index) in seenBy" :key="index" class="text-left">
|
||||
<v-list-item-icon>
|
||||
<v-avatar size="40" color="grey">
|
||||
<AuthedImage v-if="memberAvatar(member.roomMember)" :src="memberAvatar(member.roomMember)" />
|
||||
|
|
@ -34,10 +34,8 @@
|
|||
}}</span>
|
||||
</v-avatar>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content class="text-left">
|
||||
<v-list-item-title>{{member.roomMember.name}}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ seenByTimeStamp(member.readTimestamp) }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{member.roomMember.name}}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ seenByTimeStamp(member.readTimestamp) }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</BottomSheet>
|
||||
|
|
|
|||
|
|
@ -3,27 +3,19 @@
|
|||
<v-list dense>
|
||||
<v-list-item key="edit" v-if="isEditable" @click.stop="edit">
|
||||
<v-list-item-icon><v-icon>$vuetify.icons.ic_edit</v-icon></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.edit") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.edit") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item key="pin" v-if="userCanPin && !event.isPinned" @click.stop="pin">
|
||||
<v-list-item-icon><v-icon>$vuetify.icons.ic_pin</v-icon></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.pin") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.pin") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item key="unpin" v-if="userCanPin && event.isPinned" @click.stop="unpin">
|
||||
<v-list-item-icon><v-icon>$vuetify.icons.ic_pin</v-icon></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.unpin") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.unpin") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item key="redact" v-if="isRedactable" @click.stop="redact">
|
||||
<v-list-item-icon><v-icon color="#222222">delete_outline</v-icon></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.delete") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.delete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ linkify.options.defaults.className = "link";
|
|||
linkify.options.defaults.target = { url: "_blank" };
|
||||
|
||||
export default {
|
||||
inject: ['$matrix'],
|
||||
components: {
|
||||
QuickReactions,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="created-room-welcome-header">
|
||||
<div class="mt-2" v-if="roomJoinRule == 'public'">
|
||||
<i18n path="room_welcome.join_channel" tag="span">
|
||||
<i18n-t keypath="room_welcome.join_channel" tag="span">
|
||||
<template v-slot:link>
|
||||
<div style="position:relative;display:inline-block">
|
||||
<a @click.stop="copyPublicLink" :href="publicRoomLink" class="text-break">{{ publicRoomLink }}</a>
|
||||
|
|
@ -10,17 +10,17 @@
|
|||
$t("room_info.link_copied") }}</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="mt-2" v-else-if="roomJoinRule == 'invite'">
|
||||
{{ $t("room_welcome.join_invite") }}
|
||||
</div>
|
||||
<div class="mt-2" v-if="roomMessageRetention() > 0">
|
||||
<i18n path="room_welcome.info_retention" tag="span">
|
||||
<i18n-t keypath="room_welcome.info_retention" tag="span">
|
||||
<template v-slot:time>
|
||||
<b>{{ messageRetentionDisplay }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
<a href="#" text @click.prevent="showMessageRetentionDialog = true" style="white-space: pre-line;">{{ $t("room_welcome.change") }}</a>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="mt-2" v-if="roomMessageRetention() > 0">
|
||||
<i18n path="room_welcome.info_retention_user" tag="span">
|
||||
<i18n-t keypath="room_welcome.info_retention_user" tag="span">
|
||||
<template v-slot:time>
|
||||
<b>{{ messageRetentionDisplay }}</b>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="created-room-welcome-header">
|
||||
<div>{{ $t("room_welcome.info") }}</div>
|
||||
<div class="mt-2" v-if="roomJoinRule == 'public'">
|
||||
<i18n path="room_welcome.join_public" tag="span">
|
||||
<i18n-t keypath="room_welcome.join_public" tag="span">
|
||||
<template v-slot:link>
|
||||
<div style="position:relative;display:inline-block">
|
||||
<a @click.stop="copyPublicLink" :href="publicRoomLink" class="text-break">{{ publicRoomLink }}</a>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
>
|
||||
</div>
|
||||
</template>
|
||||
</i18n>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="mt-2" v-else-if="roomJoinRule == 'invite'">
|
||||
{{ $t("room_welcome.join_invite") }}
|
||||
|
|
|
|||
79
src/main.js
79
src/main.js
|
|
@ -1,4 +1,3 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import store from './store'
|
||||
import i18n from './plugins/lang';
|
||||
|
|
@ -10,40 +9,44 @@ import analytics from './services/analytics.service'
|
|||
import audioPlayer from './services/audio.service';
|
||||
import 'roboto-fontface/css/roboto/roboto-fontface.css'
|
||||
import 'material-design-icons-iconfont/dist/material-design-icons.css'
|
||||
import VueResize from 'vue-resize';
|
||||
import 'vue-resize/dist/vue-resize.css';
|
||||
import VueResize from 'vue3-resize';
|
||||
import 'vue3-resize/dist/vue3-resize.css';
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import VueSanitize from "vue-sanitize";
|
||||
import Vue3Sanitize from "vue-3-sanitize";
|
||||
import createVuetify from './plugins/vuetify';
|
||||
import { Buffer } from 'buffer/'
|
||||
import { createApp, h } from 'vue';
|
||||
globalThis.Buffer = Buffer;
|
||||
|
||||
var defaultOptions = VueSanitize.defaults;
|
||||
var defaultOptions = Vue3Sanitize.defaults;
|
||||
defaultOptions.disallowedTagsMode = "recursiveEscape";
|
||||
defaultOptions.allowedTags = [];
|
||||
Vue.use(VueSanitize, defaultOptions);
|
||||
|
||||
Vue.config.productionTip = false
|
||||
const app = createApp({
|
||||
render: () => h(App)
|
||||
});
|
||||
app.use(Vue3Sanitize, defaultOptions);
|
||||
|
||||
Vue.use(VueResize);
|
||||
Vue.use(matrix, { store: store, i18n: i18n });
|
||||
app.config.productionTip = false
|
||||
|
||||
app.use(VueResize);
|
||||
|
||||
const configLoadedPromise = new Promise((resolve, ignoredreject) => {
|
||||
// eslint-disable-next-line
|
||||
Vue.use(config, globalThis.window.location.origin, (config) => {
|
||||
app.use(config, globalThis.window.location.origin, (config) => {
|
||||
resolve(config);
|
||||
}); // Use this before cleaninsights below, it depends on config!
|
||||
});
|
||||
Vue.use(analytics);
|
||||
Vue.use(VueClipboard);
|
||||
Vue.use(audioPlayer);
|
||||
app.use(analytics);
|
||||
app.use(VueClipboard);
|
||||
app.use(audioPlayer);
|
||||
|
||||
const vuetify = createVuetify(config);
|
||||
|
||||
// Add bubble functionality to custom events.
|
||||
// From here: https://stackoverflow.com/questions/41993508/vuejs-bubbling-custom-events
|
||||
Vue.use((Vue) => {
|
||||
Vue.prototype.$bubble = function $bubble(eventName, ...args) {
|
||||
app.use((instance) => {
|
||||
instance.$bubble = function $bubble(eventName, ...args) {
|
||||
// Emit the event on all parent components
|
||||
let component = this;
|
||||
let arg = args.at(0);
|
||||
|
|
@ -62,7 +65,7 @@ Vue.use((Vue) => {
|
|||
});
|
||||
|
||||
// Register a global custom directive called `v-blur` that prevents focus
|
||||
Vue.directive('blur', {
|
||||
app.directive('blur', {
|
||||
inserted: function (el) {
|
||||
el.onfocus = (ev) => ev.target.blur()
|
||||
}
|
||||
|
|
@ -75,7 +78,7 @@ Vue.directive('blur', {
|
|||
*
|
||||
* Like this: v-linkTap:500="[tapped,longTapped]"
|
||||
*/
|
||||
Vue.directive('longTap', {
|
||||
app.directive('longTap', {
|
||||
bind: function (el, binding, ignoredvnode) {
|
||||
el.longTapTimeout = parseInt(binding.arg || "500");
|
||||
el.longTapCallbacks = binding.value;
|
||||
|
|
@ -168,27 +171,35 @@ Vue.directive('longTap', {
|
|||
},
|
||||
});
|
||||
|
||||
Vue.use(navigation, router);
|
||||
app.use(store);
|
||||
app.$store = store;
|
||||
app.config.globalProperties.$store = store;
|
||||
|
||||
const vueInstance = new Vue({
|
||||
vuetify,
|
||||
store,
|
||||
i18n,
|
||||
router,
|
||||
matrix,
|
||||
config,
|
||||
analytics,
|
||||
audioPlayer,
|
||||
render: h => h(App),
|
||||
});
|
||||
if (vueInstance.$config.accentColor) {
|
||||
vueInstance.$vuetify.theme.themes.light.primary = vueInstance.$config.accentColor;
|
||||
app.use(router);
|
||||
router.app = app;
|
||||
|
||||
app.use(navigation, router);
|
||||
app.use(vuetify);
|
||||
app.use(i18n);
|
||||
|
||||
app.use(matrix, { store: store, i18n: i18n });
|
||||
|
||||
//app.use(matrix);
|
||||
//app.use(config);
|
||||
// app.use(analytics);
|
||||
// app.use(audioPlayer);
|
||||
// app.render = h => {
|
||||
// console.error("RENDERRENDERRENDERRENDERRENDSNAENNRENRANERNARE");
|
||||
// h(App);
|
||||
// }
|
||||
if (app.$config.accentColor) {
|
||||
app.$vuetify.theme.themes.light.primary = app.$config.accentColor;
|
||||
}
|
||||
vueInstance.$audioPlayer.$root = vueInstance; // Make sure a $root is available here
|
||||
app.$audioPlayer.$root = app; // Make sure a $root is available here
|
||||
configLoadedPromise.then((config) => {
|
||||
if (config.accentColor) {
|
||||
vueInstance.$vuetify.theme.themes.light.primary = config.accentColor;
|
||||
app.$vuetify.theme.themes.light.primary = config.accentColor;
|
||||
}
|
||||
vueInstance.$mount('#app');
|
||||
app.mount('#app');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
import Vue from 'vue'
|
||||
import VueI18n from 'vue-i18n'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
var messages = {}
|
||||
|
||||
|
|
@ -13,9 +10,10 @@ Object.keys(modules).map(path => {
|
|||
messages[locale] = modules[path];
|
||||
});
|
||||
|
||||
const vue18n = new VueI18n({
|
||||
const vue18n = new createI18n({
|
||||
locale: 'en',
|
||||
fallbackLocale: 'en',
|
||||
globalInjection: true,
|
||||
silentFallbackWarn: true,
|
||||
messages: messages,
|
||||
pluralizationRules: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify/lib';
|
||||
import {createVuetify } from "vuetify";
|
||||
|
||||
// Import all .vue icons and process them, so they can be used
|
||||
// as $vuetify.icons.<iconname>
|
||||
|
|
@ -12,11 +11,8 @@ Object.keys(modules).map(path => {
|
|||
icons[iconName] = { component: modules[path].default }
|
||||
});
|
||||
|
||||
|
||||
Vue.use(Vuetify);
|
||||
|
||||
export default function(ignoredconfig) {
|
||||
return new Vuetify({
|
||||
return createVuetify({
|
||||
icons: {
|
||||
iconfont: 'md',
|
||||
values: icons,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from '../components/Home.vue'
|
||||
import Chat from '../components/Chat.vue'
|
||||
import Join from '../components/Join.vue'
|
||||
|
|
@ -12,8 +10,7 @@ import CreateChannel from '../components/CreateChannel.vue'
|
|||
import CreateFileDrop from '../components/CreateFileDrop.vue'
|
||||
import User from '../models/user'
|
||||
import util from '../plugins/utils'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
|
@ -110,8 +107,9 @@ const routes = [
|
|||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
routes
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes: routes
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import cleaninsights from './cleaninsights.service'
|
|||
import matomo from './matomo.service'
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
const analyticsService = new Vue({
|
||||
install(app) {
|
||||
const analyticsService = ({
|
||||
data() {
|
||||
return {
|
||||
engines: [],
|
||||
|
|
@ -60,6 +60,8 @@ export default {
|
|||
}
|
||||
}
|
||||
});
|
||||
Vue.prototype.$analytics = analyticsService;
|
||||
|
||||
app.$analytics = analyticsService;
|
||||
app.config.globalProperties.$analytics = analyticsService;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import utils from "../plugins/utils";
|
|||
* an audio matrix event and a unique component id (for example the ._uid property).
|
||||
*/
|
||||
export default {
|
||||
install(Vue) {
|
||||
install(app) {
|
||||
class SharedAudioPlayer {
|
||||
constructor() {
|
||||
this.player = new Audio();
|
||||
|
|
@ -34,12 +34,12 @@ export default {
|
|||
// Listeners is just a Set of component "uid" entries for now.
|
||||
entry = { url: null, listeners: new Set() };
|
||||
// Make these reactive, so AudioPlayer (and others) can listen to them
|
||||
Vue.set(entry, "loading", false);
|
||||
Vue.set(entry, "loadPercent", 0);
|
||||
Vue.set(entry, "duration", 0);
|
||||
Vue.set(entry, "currentTime", 0);
|
||||
Vue.set(entry, "playPercent", 0);
|
||||
Vue.set(entry, "playing", false);
|
||||
entry["loading"] = false;
|
||||
entry["loadPercent"] = 0;
|
||||
entry["duration"] = 0;
|
||||
entry["currentTime"] = 0;
|
||||
entry["playPercent"] = 0;
|
||||
entry["playing"] = false;
|
||||
this.infoMap.set(eventId, entry);
|
||||
|
||||
// Get duration information
|
||||
|
|
@ -263,6 +263,8 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$audioPlayer = new SharedAudioPlayer();
|
||||
const audioPlayer = new SharedAudioPlayer();
|
||||
app.$audioPlayer = audioPlayer;
|
||||
app.config.globalProperties.$audioPlayer = audioPlayer;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import * as defaultConfig from "@/assets/config.json";
|
||||
|
||||
export default {
|
||||
install(Vue, defaultServerFromLocation, onloaded) {
|
||||
var config = Vue.observable(defaultConfig.default);
|
||||
Vue.set(config, "loaded", false);
|
||||
install(app, defaultServerFromLocation, onloaded) {
|
||||
var config = defaultConfig.default;
|
||||
config["loaded"] = false;
|
||||
const getRuntimeConfig = () => {
|
||||
return fetch('./config.json?ms=' + Date.now()).then((res) => res.json()).catch(err => {
|
||||
console.error("Failed to get config:", err);
|
||||
|
|
@ -14,25 +14,25 @@ export default {
|
|||
config.promise = getRuntimeConfig().then((json) => {
|
||||
// Reactively use all the config values
|
||||
for (const key of Object.keys(json)) {
|
||||
Vue.set(config, key, json[key]);
|
||||
config[key] = json[key];
|
||||
}
|
||||
// If default server is not set, default to current server address
|
||||
if (!json.defaultBaseUrl) {
|
||||
if (json.defaultServer) {
|
||||
// TODO - Only to migrate old values (defaultServer was renamed defaultBaseUrl), can be removed later...
|
||||
Vue.set(config, "defaultBaseUrl", defaultServerFromLocation);
|
||||
config["defaultBaseUrl"] = defaultServerFromLocation;
|
||||
} else {
|
||||
Vue.set(config, "defaultBaseUrl", json.defaultServer);
|
||||
config["defaultBaseUrl"] = json.defaultServer;
|
||||
}
|
||||
}
|
||||
if (json.useFullyQualifiedDMLinks == undefined) {
|
||||
Vue.set(config, "useFullyQualifiedDMLinks", true); // Default to true
|
||||
config["useFullyQualifiedDMLinks"] = true; // Default to true
|
||||
}
|
||||
if (json.disableMediaSharing == undefined) {
|
||||
Vue.set(config, "disableMediaSharing", false);
|
||||
}
|
||||
if (!json.maxSizeAutoDownloads) {
|
||||
Vue.set(config, "maxSizeAutoDownloads", 10 * 1024 * 1024);
|
||||
config["maxSizeAutoDownloads"] = 10 * 1024 * 1024;
|
||||
}
|
||||
if (!json.roomTypes) {
|
||||
let roomTypes = ["group_chat", "channel"];
|
||||
|
|
@ -40,9 +40,9 @@ export default {
|
|||
if (fileDropEnabled) {
|
||||
roomTypes.push("file_drop");
|
||||
}
|
||||
Vue.set(config, "roomTypes", roomTypes);
|
||||
config["roomTypes"] = roomTypes;
|
||||
}
|
||||
Vue.set(config, "loaded", true);
|
||||
config["loaded"] = true;
|
||||
|
||||
document.title = config.appName || "";
|
||||
|
||||
|
|
@ -70,6 +70,7 @@ export default {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
Vue.prototype.$config = config;
|
||||
app.$config = config;
|
||||
app.config.globalProperties.$config = config;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
1281
src/services/matrix.vue
Normal file
1281
src/services/matrix.vue
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
install(Vue, router) {
|
||||
install(app, router) {
|
||||
var routes = [];
|
||||
var nextRoutes = null;
|
||||
var zeroIndex = undefined;
|
||||
|
|
@ -75,6 +75,8 @@ export default {
|
|||
router.go(-1);
|
||||
}
|
||||
}
|
||||
Vue.prototype.$navigation = navigationService;
|
||||
|
||||
app.$navigation = navigationService;
|
||||
app.config.globalProperties.$navigation = navigationService;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import { createStore } from 'vuex'
|
||||
import VuexPersistence from 'vuex-persist'
|
||||
|
||||
Vue.use(Vuex)
|
||||
const USER = `convene_${ window.location.hostname }_user`
|
||||
const SETTINGS = `convene_${ window.location.hostname }_settings`
|
||||
|
||||
|
|
@ -67,7 +65,7 @@ const vuexPersistSessionStorage = new VuexPersistence({
|
|||
|
||||
const defaultUseSessionStorage = (sessionStorage.getItem(USER) != null);
|
||||
|
||||
export default new Vuex.Store({
|
||||
const store = createStore({
|
||||
state: { language: null, currentRoomId: null, auth: null, tempuser: null, useLocalStorage: !defaultUseSessionStorage, globalNotification: false },
|
||||
mutations: {
|
||||
loginSuccess(state, user) {
|
||||
|
|
@ -144,4 +142,6 @@ export default new Vuex.Store({
|
|||
}
|
||||
},
|
||||
plugins: [vuexPersistLocalStorage.plugin, vuexPersistSessionStorage.plugin, persistUserPlugin]
|
||||
})
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue2";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import vitePluginVuetify from "vite-plugin-vuetify";
|
||||
import { fileURLToPath, URL } from "node:url";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
|
|
@ -11,8 +13,9 @@ function VuetifyResolver() {
|
|||
return {
|
||||
type: 'component',
|
||||
resolve: (name) => {
|
||||
console.log("rESOLVE", name);
|
||||
if (name.match(/^V[A-Z]/) && !name.includes("VEmojiPicker"))
|
||||
return { name, from: 'vuetify/lib' }
|
||||
return { name, from: './node_modules/vuetify/lib/components' }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -28,9 +31,11 @@ export default defineConfig(({mode}) => ({
|
|||
// exclude: ["*vuex-persist*", "*deepmerge*"]
|
||||
// }),
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [VuetifyResolver()],
|
||||
}),
|
||||
vueJsx(),
|
||||
vitePluginVuetify(),
|
||||
// Components({
|
||||
// resolvers: [VuetifyResolver()],
|
||||
// }),
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{
|
||||
|
|
@ -54,7 +59,8 @@ export default defineConfig(({mode}) => ({
|
|||
alias: [
|
||||
{ find: "@", replacement: fileURLToPath(new URL("./src", import.meta.url)) },
|
||||
{ find: "~@", replacement: fileURLToPath(new URL("./src", import.meta.url)) },
|
||||
{ find: "~vuetify", replacement: fileURLToPath(new URL("./node_modules/vuetify", import.meta.url)) },
|
||||
{ find: "~vuetify/src", replacement: fileURLToPath(new URL("./node_modules/vuetify/lib", import.meta.url)) },
|
||||
{ find: "vue", replacement: fileURLToPath(new URL("./node_modules/vue/dist/vue.esm-bundler.js", import.meta.url)) },
|
||||
],
|
||||
},
|
||||
define: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue