264 lines
9.8 KiB
Vue
Executable File
264 lines
9.8 KiB
Vue
Executable File
<template>
|
|
<meta-head title="Мессенджер"></meta-head>
|
|
<div class="flex sm:grid grid-cols-12 h-full overflow-hidden">
|
|
<!-- flex-shrink-0 -->
|
|
<div ref="userSidebar" class="h-full sm:h-auto transition-transform z-50 absolute transform-gpu -translate-x-full w-64 sm:relative sm:transform-none sm:w-auto col-span-4 bg-indigo-200 border-l border-r border-indigo-300 py-7">
|
|
<div class="mb-7 px-2 xl:px-8">
|
|
<div class="relative">
|
|
<text-input v-model="inputSearchRoom"
|
|
class="pr-12 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light w-full" placeholder="Поиск"
|
|
/>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24"
|
|
height="24" viewBox="0 0 24 24"
|
|
fill="none" stroke="currentColor"
|
|
stroke-width="2" stroke-linecap="round"
|
|
stroke-linejoin="round" class="text-gray-light absolute right-3 top-2"
|
|
><circle cx="11" cy="11"
|
|
r="8"
|
|
></circle><line x1="21" y1="21"
|
|
x2="16.65" y2="16.65"
|
|
></line></svg>
|
|
</div>
|
|
<div class="flex flex-col lg:flex-row lg:space-x-6 mt-2">
|
|
<div class="flex items-center">
|
|
<input id="room-search-1" v-model="typeSearch"
|
|
:value="1" type="radio"
|
|
class="text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent cursor-pointer"
|
|
>
|
|
<label for="room-search-1" class="cursor-pointer select-none ml-2 text-gray-light text-sm">по сообщениям</label>
|
|
</div>
|
|
<div class="flex items-center">
|
|
<input id="room-search-2" v-model="typeSearch"
|
|
:value="2" type="radio"
|
|
class="text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent cursor-pointer"
|
|
>
|
|
<label for="room-search-2" class="cursor-pointer select-none ml-2 text-gray-light text-sm">по пользователям</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="text-right">
|
|
<button class="default mb-2 text-orange text-sm mr-1" @click="openFriendList">
|
|
открыть список друзей
|
|
</button>
|
|
</div>
|
|
<div data-simplebar class="messsage-height overflow-auto">
|
|
<div class="divide-y divide-indigo-300 border-t border-b border-indigo-300">
|
|
<board-room-list v-for="room in userRooms" :key="room.id"
|
|
class="pt-5 pb-5"
|
|
:class="{ 'bg-indigo-300': room.classActive }"
|
|
:room="room"
|
|
@select-room="changeRoom"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex-1 w-full sm:flex-none sm:w-auto col-span-8 bg-indigo-200 overflow-hidden relative">
|
|
<button class="default text-center left-2 top-3 absolute z-40 flex sm:hidden items-center text-white text-xs" @click="openSidebar">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24"
|
|
height="24" viewBox="0 0 24 24"
|
|
fill="none" stroke="currentColor"
|
|
stroke-width="2" stroke-linecap="round"
|
|
stroke-linejoin="round" class="feather feather-menu"
|
|
><line x1="3" y1="12"
|
|
x2="21" y2="12"
|
|
></line><line x1="3" y1="6"
|
|
x2="21" y2="6"
|
|
></line><line x1="3" y1="18"
|
|
x2="21" y2="18"
|
|
></line></svg>
|
|
<span class="ml-1">открыть список пользователей</span>
|
|
</button>
|
|
<board-message :room-id="selectRoom" :user="selectUser"
|
|
:frozen="selectFrozenRoom" :search="searchOnlyMessage"
|
|
@disable="interactDisable" @last-message="updateRoom"
|
|
@change-room="touchRoom" @leave-room="leaveRoom"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, toRef, watch } from 'vue'
|
|
import { onClickOutside } from '@vueuse/core'
|
|
import { usePage } from '@inertiajs/inertia-vue3'
|
|
import { Inertia } from '@inertiajs/inertia'
|
|
import debounce from 'lodash/debounce'
|
|
import pickBy from 'lodash/pickBy'
|
|
|
|
import Layout from '@/Shared/Layout.vue'
|
|
import MetaHead from '@/Shared/MetaHead.vue'
|
|
import TextInput from '@/Shared/Form/TextInput.vue'
|
|
import BoardRoomList from '@/Shared/Messanger/BoardRoomList.vue'
|
|
import BoardMessage from '@/Shared/Messanger/BoardMessage.vue'
|
|
|
|
export default {
|
|
components: {
|
|
MetaHead,
|
|
TextInput,
|
|
BoardRoomList,
|
|
BoardMessage,
|
|
},
|
|
layout: Layout,
|
|
|
|
props: {
|
|
rooms: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
roomSearch: {
|
|
type: String,
|
|
default: ''
|
|
}
|
|
},
|
|
|
|
setup(props){
|
|
var inputSearchRoom = ref(props.roomSearch)
|
|
const typeSearch = ref(1)
|
|
const searchOnlyMessage = ref('')
|
|
var userRooms = toRef(props, 'rooms')
|
|
|
|
var selectUser = ref(null)
|
|
var selectRoom = ref(0)
|
|
var selectFrozenRoom = ref(false)
|
|
|
|
var userSidebar = ref(null)
|
|
var canChangeRoom = ref(true)
|
|
|
|
watch(inputSearchRoom, debounce((search) => {
|
|
selectUser.value = null
|
|
selectRoom.value = 0
|
|
if(typeSearch.value === 1){
|
|
searchOnlyMessage.value = search
|
|
}
|
|
Inertia.get(route('messenger.index'), pickBy({ search: search, type: search ? typeSearch.value : null }), { preserveState: true })
|
|
}, 500))
|
|
|
|
watch(typeSearch, () => {
|
|
inputSearchRoom.value = ''
|
|
})
|
|
|
|
const checkSelectedActiveUser = () => {
|
|
const activeRoom = userRooms.value.find(userRoom => userRoom.classActive === true)
|
|
if(activeRoom){
|
|
selectUser.value = activeRoom.correspond
|
|
selectRoom.value = activeRoom.id
|
|
selectFrozenRoom.value = activeRoom.is_freeze
|
|
}
|
|
}
|
|
checkSelectedActiveUser()
|
|
|
|
function openFriendList() {
|
|
selectUser.value = null
|
|
selectRoom.value = 0
|
|
userRooms.value.forEach(item => item.classActive = false)
|
|
}
|
|
|
|
const touchRoom = (id) => {
|
|
const activeRoom = userRooms.value.find(userRoom => userRoom.id === id)
|
|
if(activeRoom){
|
|
activeRoom.classActive = true
|
|
selectUser.value = activeRoom.correspond
|
|
selectRoom.value = activeRoom.id
|
|
selectFrozenRoom.value = activeRoom.is_freeze
|
|
}
|
|
}
|
|
|
|
const leaveRoom = () => {
|
|
selectRoom.value = 0
|
|
selectUser.value = null
|
|
selectFrozenRoom.value = false
|
|
}
|
|
|
|
|
|
const changeRoom = (room) => {
|
|
closeSidebar()
|
|
if(canChangeRoom.value){
|
|
selectRoom.value = room.id
|
|
selectUser.value = room.correspond
|
|
selectFrozenRoom.value = room.is_freeze
|
|
const lastActiveRoom = userRooms.value.find(userRoom => userRoom.classActive === true)
|
|
if(lastActiveRoom){
|
|
lastActiveRoom.classActive = false
|
|
}
|
|
const nowActiveRoom = userRooms.value.find(userRoom => userRoom.id === room.id)
|
|
nowActiveRoom.classActive = true
|
|
|
|
if(!nowActiveRoom.is_my_message && !nowActiveRoom.is_reading){
|
|
nowActiveRoom.is_reading = true
|
|
usePage().props.value.message_reading_count--
|
|
}
|
|
}
|
|
}
|
|
|
|
let openSidebar = () => {
|
|
if (window.matchMedia('(max-width: 640px)').matches) {
|
|
userSidebar.value.classList.remove('-translate-x-full')
|
|
userSidebar.value.classList.add('-translate-x-0')
|
|
userSidebar.value.classList.add('shadow-classic')
|
|
}
|
|
}
|
|
|
|
let closeSidebar = () => {
|
|
if (window.matchMedia('(max-width: 640px)').matches) {
|
|
userSidebar.value.classList.add('-translate-x-full')
|
|
userSidebar.value.classList.remove('-translate-x-0')
|
|
userSidebar.value.classList.remove('shadow-classic')
|
|
}
|
|
}
|
|
|
|
let interactDisable = (type) => {
|
|
if(type === true){
|
|
canChangeRoom.value = false
|
|
}else{
|
|
canChangeRoom.value = true
|
|
}
|
|
}
|
|
|
|
|
|
let updateRoom = (message) => {
|
|
const upRoom = userRooms.value.find(userRoom => userRoom.id === message.chat_room_id)
|
|
upRoom.message = message.message
|
|
upRoom.is_my_message = true
|
|
upRoom.is_reading = false
|
|
upRoom.updated_at = message.updated_at_room
|
|
upRoom.updated_at_human = message.updated_at_room_human
|
|
|
|
userRooms.value.sort(function(a, b) {
|
|
if (a.updated_at > b.updated_at) {
|
|
return -1
|
|
}
|
|
if (a.updated_at < b.updated_at) {
|
|
return 1
|
|
}
|
|
return 0
|
|
})
|
|
}
|
|
|
|
if (window.matchMedia('(max-width: 640px)').matches) {
|
|
onClickOutside(userSidebar, () => {
|
|
closeSidebar()
|
|
})
|
|
}
|
|
return {
|
|
changeRoom,
|
|
selectUser,
|
|
userRooms,
|
|
selectRoom,
|
|
openSidebar,
|
|
userSidebar,
|
|
closeSidebar,
|
|
interactDisable,
|
|
updateRoom,
|
|
inputSearchRoom,
|
|
typeSearch,
|
|
searchOnlyMessage,
|
|
selectFrozenRoom,
|
|
touchRoom,
|
|
leaveRoom,
|
|
openFriendList,
|
|
}
|
|
},
|
|
}
|
|
</script>
|