1. notification via SW 2.manifest json for home screen app 3. icons for mobile/desktop shortcut app

This commit is contained in:
10G Meow 2023-07-17 15:00:40 +03:00
parent 44dd4e9562
commit 2087c2897f
19 changed files with 217 additions and 51 deletions

View file

@ -4,6 +4,7 @@
no-gutters
align-content="center"
v-on="$listeners"
v-show="icon === 'notifications_active' ? this.windowNotificationPermission() !== 'granted' : true"
>
<v-col cols="auto" class="me-2">
<v-icon :size="iconSize">{{ icon }}</v-icon>
@ -13,6 +14,8 @@
</template>
<script>
import { windowNotificationPermission } from "../plugins/notificationAndServiceWorker.js"
export default {
name: "ActionRow",
props: {
@ -35,6 +38,9 @@ export default {
},
},
},
methods: {
windowNotificationPermission
}
};
</script>

View file

@ -1,6 +1,10 @@
<template>
<div class="chat-root fill-height d-flex flex-column">
<ChatHeader class="chat-header flex-grow-0 flex-shrink-0" v-on:header-click="onHeaderClick" v-on:view-room-details="viewRoomDetails" v-if="!useFileModeNonAdmin" />
<ChatHeader class="chat-header flex-grow-0 flex-shrink-0"
v-on:header-click="onHeaderClick"
v-on:view-room-details="viewRoomDetails"
v-on:notify="onNotificationDialog"
v-if="!useFileModeNonAdmin" />
<AudioLayout ref="chatContainer" class="auto-audio-player-root" v-if="useVoiceMode" :room="room"
:events="events" :autoplay="!showRecorder"
:timelineSet="timelineSet"
@ -15,10 +19,10 @@
<VoiceRecorder class="audio-layout" v-if="useVoiceMode" :micButtonRef="$refs.mic_button" :ptt="showRecorderPTT" :show="showRecorder"
v-on:close="showRecorder = false" v-on:file="onVoiceRecording" :sendTypingIndicators="useVoiceMode" />
<FileDropLayout class="file-drop-root" v-if="useFileModeNonAdmin" :room="room"
<FileDropLayout class="file-drop-root" v-if="useFileModeNonAdmin" :room="room"
v-on:pick-file="showAttachmentPicker()"
v-on:add-file="addAttachment($event)"
v-on:remove-file="currentFileInputs.splice($event, 1)"
v-on:remove-file="currentFileInputs.splice($event, 1)"
v-on:reset="resetAttachments"
:attachments="currentFileInputs"
/>
@ -282,6 +286,46 @@
</v-dialog>
<CreatePollDialog :show="showCreatePollDialog" @close="showCreatePollDialog = false" />
<!-- Dialog for request Notification and register service worker-->
<v-dialog
v-model="notificationDialog"
persistent
class="ma-0 pa-0"
:width="$vuetify.breakpoint.smAndUp ? '688px' : '95%'"
>
<div class="dialog-content text-center">
<v-icon size="30">notifications_active</v-icon>
<h2 class="dialog-title">
{{ $t("notification.dialog.title") }}
</h2>
<div class="dialog-text">{{ $t("notification.dialog.body") }}</div>
<v-container fluid>
<v-row cols="12">
<v-col cols="6">
<v-btn
depressed
text
block
class="text-button"
@click="notificationDialog = false"
>{{ $t("global.close") }}</v-btn
>
</v-col>
<v-col cols="6" align="center">
<v-btn
color="primary"
depressed
block
class="filled-button"
@click.stop="onRequestNotificationAndServiceWorker"
>{{ $t("notification.dialog.enable") }}</v-btn
>
</v-col>
</v-row>
</v-container>
</div>
</v-dialog>
</div>
</template>
@ -304,6 +348,8 @@ import CreatePollDialog from "./CreatePollDialog.vue";
import chatMixin from "./chatMixin";
import AudioLayout from "./AudioLayout.vue";
import FileDropLayout from "./file_mode/FileDropLayout";
import { requestNotificationAndServiceWorker, windowNotificationPermission, notificationCount } from "../plugins/notificationAndServiceWorker.js"
import logoMixin from "./logoMixin";
const sizeOf = require("image-size");
const dataUriToBuffer = require("data-uri-to-buffer");
@ -339,7 +385,7 @@ ScrollPosition.prototype.prepareFor = function (direction) {
export default {
name: "Chat",
mixins: [chatMixin],
mixins: [chatMixin, logoMixin],
components: {
ChatHeader,
MessageOperations,
@ -433,7 +479,8 @@ export default {
Symbols: this.$t("emoji.categories.symbols"),
Places: this.$t("emoji.categories.places")
}
}
},
notificationDialog: false
};
},
@ -470,6 +517,7 @@ export default {
},
computed: {
notificationCount,
nonImageFiles() {
return this.isCurrentFileInputsAnArray && this.currentFileInputs.filter(file => !file.type.includes("image/"))
},
@ -636,6 +684,13 @@ export default {
},
watch: {
notificationCount: {
handler(nCount) {
if (nCount > 0 && this.windowNotificationPermission() === "granted") {
this.showNotification()
}
}
},
initialLoadDone: {
immediate: true,
handler(value, oldValue) {
@ -726,6 +781,34 @@ export default {
},
methods: {
windowNotificationPermission,
showNotification() {
if(document.visibilityState === "visible") {
return;
}
const title = this.$t('notification.title');
const self = this;
navigator.serviceWorker.ready.then(function(registration) {
registration.showNotification(title, {
icon: self.logotype,
tag: "new-message-notification",
});
});
},
onNotificationDialog() {
if(this.windowNotificationPermission() === 'denied') {
alert(this.$t("notification.blocked_message"));
} else if(this.windowNotificationPermission() === 'default') {
this.notificationDialog = true;
}
},
onRequestNotificationAndServiceWorker() {
requestNotificationAndServiceWorker()
this.notificationDialog = false;
},
onRoomJoined(initialEventId) {
// Was this room just created (by you)? Show a small info header in
// that case!
@ -954,7 +1037,7 @@ export default {
this.handleScrolledToBottom(scrollToSeeNew);
// If kick or ban event, redirect to "goodbye"...
if (event.getType() === "m.room.member" &&
if (event.getType() === "m.room.member" &&
event.getStateKey() == this.$matrix.currentUserId &&
(event.getPrevContent() || {}).membership == "join" &&
(

View file

@ -177,6 +177,11 @@ export default {
this.$emit("view-room-details", { event: this.event });
}
});
items.push({
icon: 'notifications_active', text: this.$t('global.notify'), handler: () => {
this.$emit("notify");
}
});
items.push({
icon: '$vuetify.icons.ic_member-leave', text: this.$t('leave.leave'), handler: () => {
this.leaveRoom();