other components... (2)
This commit is contained in:
1
src/views/messages/index.ts
Executable file
1
src/views/messages/index.ts
Executable file
@@ -0,0 +1 @@
|
||||
export {default as Messages} from './messages'
|
||||
47
src/views/messages/messages.scss
Executable file
47
src/views/messages/messages.scss
Executable file
@@ -0,0 +1,47 @@
|
||||
.messages_page{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.title_msg{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.active-user{
|
||||
color:blue;
|
||||
background-color: rgba(174, 189, 241, 0.71);
|
||||
border-radius: 1rem !important;
|
||||
}
|
||||
|
||||
.chat-list{
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.chat_dest{
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.chat_my{
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.bottomfixed {
|
||||
// right: 0;
|
||||
// position: fixed;
|
||||
z-index: 9999;
|
||||
// box-sizing: border-box;
|
||||
margin-right: 0;
|
||||
margin-left: auto;
|
||||
// bottom: 0;
|
||||
}
|
||||
276
src/views/messages/messages.ts
Executable file
276
src/views/messages/messages.ts
Executable file
@@ -0,0 +1,276 @@
|
||||
import { defineComponent, ref, computed, watch } from 'vue'
|
||||
import { useI18n } from '@src/boot/i18n'
|
||||
import { useUserStore } from '@store/UserStore'
|
||||
import { useGlobalStore } from '@store/globalStore'
|
||||
import { useQuasar } from 'quasar'
|
||||
|
||||
import { tools } from '@store/Modules/tools'
|
||||
|
||||
import { IChat, IMessage, IMsgUsers, StatusMessage } from 'model'
|
||||
import MixinUsers from '../../mixins/mixin-users'
|
||||
import { CMyAvatar } from '../../components/CMyAvatar'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useMessageStore } from '@store/MessageStore'
|
||||
import { func_tools } from '@store/Modules/toolsext'
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Messages',
|
||||
props: {
|
||||
mystr: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
myval: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
mybool: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: { CMyAvatar },
|
||||
setup(props, { emit }) {
|
||||
const $q = useQuasar()
|
||||
const { t } = useI18n()
|
||||
const userStore = useUserStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const messageStore = useMessageStore()
|
||||
const $router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const {
|
||||
getUsernameChatByMsg, getNumMsg,
|
||||
getImgByMsg, getMsgText, Username
|
||||
} = MixinUsers()
|
||||
|
||||
const mydrawer = ref(true)
|
||||
const miniState = ref(false)
|
||||
const usernameloading = ref(<string | undefined>'')
|
||||
const widthdrawer = ref(300)
|
||||
const chatsel = ref(<IChat>{
|
||||
username: '',
|
||||
lasttimeActive: new Date()
|
||||
})
|
||||
const mytexttosend = ref('')
|
||||
const loading = ref(false)
|
||||
|
||||
const lasts_messages = computed(() => messageStore.getlasts_messages)
|
||||
|
||||
// function users_msg_saved: IMsgUsers[] = []
|
||||
|
||||
|
||||
function getLastUserChatted() {
|
||||
const lastmsg: IMessage = messageStore.getlasts_messages().slice(-1)[0]
|
||||
console.log('lastmsg', lastmsg)
|
||||
if (lastmsg) {
|
||||
return (lastmsg.origin!.username !== Username()) ? lastmsg.origin!.username : lastmsg.origin!.username
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
function getlastdataread(username: string): any {
|
||||
const myrec = msgchat(username)
|
||||
// Get msg for this chat
|
||||
const lastdata: any = (myrec) ? myrec.lastdataread : tools.getLastDateReadReset()
|
||||
console.table(myrec)
|
||||
let mydate = ''
|
||||
if (!tools.isIsoDate(lastdata))
|
||||
mydate = lastdata.toISOString()
|
||||
else
|
||||
return lastdata
|
||||
|
||||
// console.log('getlastdataread', mydate)
|
||||
return mydate
|
||||
}
|
||||
|
||||
function refreshdata(username: string) {
|
||||
loading.value = true
|
||||
|
||||
chatsel.value.username = ''
|
||||
|
||||
return messageStore.updateMsgDataFromServer({
|
||||
username,
|
||||
lastdataread: getlastdataread(username)
|
||||
}).then((ris) => {
|
||||
usernameloading.value = username
|
||||
chatsel.value.username = username
|
||||
loading.value = false
|
||||
|
||||
const element = document.getElementById('last')
|
||||
tools.scrollToElement(element)
|
||||
|
||||
// changemsgs('', '')
|
||||
|
||||
}).catch((err) => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const changeusername = watch(() => route.params.un, (newval, oldval) => {
|
||||
if (route.params.un === undefined || route.params.un === ':un') {
|
||||
usernameloading.value = getLastUserChatted()
|
||||
} else {
|
||||
let mystr2: any = route.params.un ? route.params.un : ''
|
||||
usernameloading.value = mystr2
|
||||
}
|
||||
|
||||
if (!miniState.value && tools.isMobile()) {
|
||||
miniState.value = true
|
||||
}
|
||||
|
||||
if (usernameloading.value) {
|
||||
// Retrieve last msgs data from the server
|
||||
refreshdata(usernameloading.value)
|
||||
}
|
||||
})
|
||||
|
||||
function styletextbar() {
|
||||
|
||||
let mystr = ''
|
||||
|
||||
if (mydrawer.value) {
|
||||
if (!miniState.value)
|
||||
mystr = `left: ${widthdrawer.value}px;`
|
||||
else
|
||||
mystr = 'left: 57px;'
|
||||
} else {
|
||||
mystr = 'left: 0;'
|
||||
}
|
||||
|
||||
// console.log('tools.getwidth', tools.getwidth)
|
||||
|
||||
mystr += ` width: ${tools.getwidth($q) - widthdrawer.value - 40 - 300}px; `
|
||||
|
||||
return mystr
|
||||
}
|
||||
|
||||
function showNotif(msgcode: any) {
|
||||
tools.showNotif($q, (msgcode))
|
||||
}
|
||||
|
||||
function drawerClick(e: any) {
|
||||
// if in "mini" state and user
|
||||
// click on drawer, we switch it to "normal" mode
|
||||
if (miniState.value) {
|
||||
miniState.value = false
|
||||
|
||||
// notice we have registered an event with capture flag;
|
||||
// we need to stop further propagation as this click is
|
||||
// intended for switching drawer to "normal" mode only
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
function getheight() {
|
||||
// return height()
|
||||
return $q.screen.height - 43 // .toolbar
|
||||
}
|
||||
|
||||
function isMenuActive(username: string) {
|
||||
return chatsel.value.username === username
|
||||
}
|
||||
|
||||
function selChat(mymsg: IMessage) {
|
||||
if (chatsel.value.username !== mymsg.dest!.username)
|
||||
$router.replace('/messages/' + mymsg.dest!.username)
|
||||
else {
|
||||
// refresh
|
||||
refreshdata(chatsel.value.username)
|
||||
}
|
||||
}
|
||||
|
||||
function msgchat(username: string): any {
|
||||
// Get msg for this chat
|
||||
if (messageStore.users_msg)
|
||||
return messageStore.users_msg.find((rec: IMsgUsers) => rec.username === username)
|
||||
// return users_msg_saved[username]
|
||||
}
|
||||
|
||||
function msgchat_records(): IMessage[] {
|
||||
const myrec = msgchat(chatsel.value.username)
|
||||
// console.log('msgchat_records', myrec)
|
||||
// Get msg for this chat
|
||||
return (myrec) ? myrec.msgs : []
|
||||
}
|
||||
|
||||
function sendMsg() {
|
||||
|
||||
const data: IMessage = {
|
||||
dest: {
|
||||
idapp: process.env.APP_ID,
|
||||
username: chatsel.value.username
|
||||
},
|
||||
message: mytexttosend.value
|
||||
}
|
||||
data.dest!.username = chatsel.value.username
|
||||
data.message = mytexttosend.value
|
||||
|
||||
mytexttosend.value = ''
|
||||
|
||||
messageStore.SendMsgEvent(data).then((ris) => {
|
||||
data.status = StatusMessage.Sending
|
||||
|
||||
const element = document.getElementById('last')
|
||||
tools.scrollToElement(element)
|
||||
|
||||
if (!ris)
|
||||
tools.showNegativeNotif($q, t('cal.sendmsg_error'))
|
||||
|
||||
// tools.showPositiveNotif(self.$q, self.('cal.sendmsg_sent'))
|
||||
// else
|
||||
})
|
||||
}
|
||||
|
||||
function loadMorePosts() {
|
||||
// ....
|
||||
}
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
function myonScroll({ target: { scrollTop, clientHeight, scrollHeight } }: {scrollTop: number, clientHeight: number, scrollHeight: number}) {
|
||||
if (scrollTop + clientHeight >= scrollHeight) {
|
||||
loadMorePosts()
|
||||
}
|
||||
}
|
||||
|
||||
function created() {
|
||||
|
||||
changeusername()
|
||||
}
|
||||
|
||||
created()
|
||||
|
||||
return {
|
||||
msgchat_records,
|
||||
msgchat,
|
||||
sendMsg,
|
||||
selChat,
|
||||
isMenuActive,
|
||||
getheight,
|
||||
drawerClick,
|
||||
showNotif,
|
||||
styletextbar,
|
||||
lasts_messages,
|
||||
myonScroll,
|
||||
widthdrawer,
|
||||
chatsel,
|
||||
mytexttosend,
|
||||
loading,
|
||||
mydrawer,
|
||||
getUsernameChatByMsg,
|
||||
getNumMsg,
|
||||
getImgByMsg,
|
||||
getMsgText,
|
||||
Username,
|
||||
func_tools,
|
||||
tools,
|
||||
}
|
||||
}
|
||||
})
|
||||
179
src/views/messages/messages.vue
Executable file
179
src/views/messages/messages.vue
Executable file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<div class="q-pr-md">
|
||||
<q-layout
|
||||
view="hHh Lpr lff" container :style="`height: ` + getheight + `px`"
|
||||
class="shadow-2 rounded-borders messages_page">
|
||||
<q-drawer
|
||||
v-model="mydrawer"
|
||||
|
||||
:mini="!mydrawer || miniState"
|
||||
@click.capture="drawerClick"
|
||||
|
||||
:width="widthdrawer"
|
||||
:breakpoint="300"
|
||||
bordered
|
||||
content-class="bg-grey-3">
|
||||
|
||||
<q-scroll-area class="fit">
|
||||
<q-list bordered class="rounded-borders chat-list">
|
||||
<q-item-label header class="title_msg">{{ $t('msgs.messages') }}</q-item-label>
|
||||
|
||||
<q-separator/>
|
||||
|
||||
<div v-if="getNumMsg() === 0">
|
||||
<q-item>
|
||||
{{ $t('msgs.nomessage') }}
|
||||
|
||||
</q-item>
|
||||
</div>
|
||||
|
||||
<q-item
|
||||
clickable
|
||||
|
||||
:active="isMenuActive(msg.dest.username)"
|
||||
active-class="active-user"
|
||||
v-for="(msg, index) in lasts_messages()"
|
||||
:key="index"
|
||||
@click="selChat(msg)">
|
||||
|
||||
<q-item-section avatar>
|
||||
<q-avatar>
|
||||
<img :src="getImgByMsg(msg)" :alt="getUsernameChatByMsg(msg)">
|
||||
</q-avatar>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>
|
||||
<q-item-label lines="1">{{ getUsernameChatByMsg(msg) }}</q-item-label>
|
||||
<q-item-label caption lines="2">
|
||||
{{ getMsgText(msg, false) }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section side top>
|
||||
{{ tools.getstrDateTimeShort(msg.datemsg) }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator/>
|
||||
</q-list>
|
||||
</q-scroll-area>
|
||||
|
||||
<div class="q-mini-drawer-hide absolute" style="top: 15px; right: -17px">
|
||||
<q-btn
|
||||
dense
|
||||
round
|
||||
unelevated
|
||||
color="accent"
|
||||
icon="chevron_left"
|
||||
@click="miniState = true">
|
||||
</q-btn>
|
||||
</div>
|
||||
</q-drawer>
|
||||
|
||||
<div class="row column">
|
||||
<div>
|
||||
<q-page-container style="">
|
||||
<q-page class="q-px-lg q-py-md">
|
||||
<div>
|
||||
<q-item clickable v-if="!!chatsel.username" @scroll="myonScroll">
|
||||
|
||||
<q-item-section avatar>
|
||||
<CMyAvatar :username="chatsel.username"></CMyAvatar>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>
|
||||
<q-item-label lines="1">{{ getUserByUsername(chatsel.username) }}</q-item-label>
|
||||
<q-item-label caption lines="2">
|
||||
{{ func_tools.getDateTimeShortStr(chatsel.lasttimeActive) }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</div>
|
||||
<q-separator/>
|
||||
<div class="q-pa-md">
|
||||
<q-item
|
||||
clickable v-for="(msg, index) in msgchat_records()" :key="index">
|
||||
<div v-if="msg.dest">
|
||||
<div>
|
||||
<div class="chat_dest" v-if="msg.dest.username === Username()">
|
||||
<q-chat-message
|
||||
:name="getUsernameChatByMsg(msg)"
|
||||
:text="getMsgText(msg, true)"
|
||||
:stamp="tools.getstrDateTimeShort(msg.datemsg)"
|
||||
text-color="black"
|
||||
bg-color="grey-2">
|
||||
<template v-slot:avatar>
|
||||
<q-avatar size="sm">
|
||||
<img :src="getImgByMsg(msg)" :alt="getUsernameChatByMsg(msg)">
|
||||
</q-avatar>
|
||||
</template>
|
||||
</q-chat-message>
|
||||
</div>
|
||||
<div class="chat_my" v-else>
|
||||
<q-chat-message
|
||||
name="me"
|
||||
:text="getMsgText(msg, true)"
|
||||
:stamp="tools.getstrDateTimeShort(msg.datemsg)"
|
||||
sent
|
||||
bg-color="blue-2">
|
||||
<template v-slot:avatar>
|
||||
<CMyAvatar size="sm" :username="Username()"></CMyAvatar>
|
||||
</template>
|
||||
|
||||
</q-chat-message>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</q-item>
|
||||
<div id="last"></div>
|
||||
<q-inner-loading id="spinner" :showing="loading">
|
||||
<q-spinner-tail
|
||||
color="primary"
|
||||
size="4em">
|
||||
</q-spinner-tail>
|
||||
</q-inner-loading>
|
||||
</div>
|
||||
</q-page>
|
||||
</q-page-container>
|
||||
</div>
|
||||
<div class="bottomfixed row" :style="styletextbar">
|
||||
<div class="" style="max-width: 50px; align-self: center; order: 1;">
|
||||
<q-btn
|
||||
rounded
|
||||
size="sm"
|
||||
icon="fas fa-smile">
|
||||
</q-btn>
|
||||
</div>
|
||||
<div class="" style="max-height: 100px; flex-grow:1; order: 2;">
|
||||
<q-input
|
||||
bordered
|
||||
rounded
|
||||
v-model="mytexttosend"
|
||||
debounce="1000"
|
||||
filled
|
||||
autogrow
|
||||
input-style="max-height: 95px;">
|
||||
</q-input>
|
||||
</div>
|
||||
<div class="" style="max-width: 50px; align-self: center; order: 3;">
|
||||
<q-btn
|
||||
push
|
||||
rounded
|
||||
size="sm"
|
||||
icon="send"
|
||||
@click="sendMsg">
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./messages.ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './messages.scss';
|
||||
</style>
|
||||
Reference in New Issue
Block a user