wip
This commit is contained in:
13
src/App.vue
13
src/App.vue
@@ -1,20 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ChatView from '@/views/ChatView.vue'
|
import ChatView from '@/views/ChatView.vue'
|
||||||
import LoginView from '@/views/LoginView.vue'
|
|
||||||
import { useAuthStore } from '@/stores/auth.ts'
|
import { useAuthStore } from '@/stores/auth.ts'
|
||||||
import { computed } from 'vue'
|
import SignInView from '@/views/SignInView.vue'
|
||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const isAuth = computed(() => !!authStore.token)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-main class="chat-fullscreen">
|
<v-main class="chat-fullscreen">
|
||||||
<v-container fluid class="h-100 pa-0">
|
<v-container fluid class="h-100 pa-0">
|
||||||
<chat-view v-if="isAuth" />
|
<chat-view v-if="authStore.isAuth" />
|
||||||
<login-view v-else />
|
<sign-in-view v-else />
|
||||||
|
<!-- <sign-in-view />-->
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-main>
|
</v-main>
|
||||||
</v-app>
|
</v-app>
|
||||||
@@ -24,7 +22,4 @@ const isAuth = computed(() => !!authStore.token)
|
|||||||
.chat-fullscreen {
|
.chat-fullscreen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
.message-shaped {
|
|
||||||
border-radius: 0 24px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,27 +1,53 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useSharedWebSocket } from '@/composables/useSharedWebSocket.ts'
|
import { type Chat, useChatsStore } from '@/stores/chats.ts'
|
||||||
|
import { SocketDataReq, useSocketsStore } from '@/stores/sockets.ts'
|
||||||
|
import { useAuthStore } from '@/stores/auth.ts'
|
||||||
|
|
||||||
const { messages, chats, isConnected, error, send } = useSharedWebSocket()
|
const authStore = useAuthStore()
|
||||||
|
const chatsStore = useChatsStore()
|
||||||
|
const socketsStore = useSocketsStore()
|
||||||
|
|
||||||
|
function onSelect(value: { id: unknown }) {
|
||||||
|
console.log('onSelectChat', value.id)
|
||||||
|
|
||||||
|
const chatId = value.id as string
|
||||||
|
chatsStore.selected = chatId
|
||||||
|
|
||||||
|
socketsStore.send({
|
||||||
|
type: SocketDataReq.GET_MESSAGES,
|
||||||
|
data: { chat_id: chatId },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChatName(chat: Chat) {
|
||||||
|
if (chat.type_id === 2) {
|
||||||
|
return chat.name
|
||||||
|
} else if (chat.type_id === 1) {
|
||||||
|
const otherUsers = chat.users.filter((user) => user.id !== authStore.me?.id)
|
||||||
|
return otherUsers[0]?.name ?? otherUsers[0]?.email ?? 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'unknown ID'
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-list theme="dark" density="compact" lines="two">
|
<v-list theme="dark" density="compact" lines="two" @click:select="onSelect">
|
||||||
<v-list-subheader>Чаты</v-list-subheader>
|
<v-list-subheader>Чаты</v-list-subheader>
|
||||||
<div>{{ chats }}</div>
|
|
||||||
|
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="n in 5"
|
v-for="chat in chatsStore.chats"
|
||||||
:key="n"
|
:key="chat.id"
|
||||||
:title="'Контакт ' + n"
|
:value="chat.id"
|
||||||
:subtitle="'Последнее сообщение...'"
|
subtitle="last message..."
|
||||||
>
|
>
|
||||||
|
<template v-slot:title>{{ getChatName(chat) }} </template>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-avatar color="grey-lighten-1" text="V"> </v-avatar>
|
<v-avatar color="grey-lighten-1" text="V"> </v-avatar>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<div class="d-flex flex-column align-end">
|
<div class="d-flex flex-column align-end">
|
||||||
<v-chip density="compact" size="small">2</v-chip>
|
<v-chip density="compact" size="small">0</v-chip>
|
||||||
<div class="text-caption">22:22</div>
|
<div class="text-caption">00:00</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{ createdAt?: string; username?: string; side?: 'right'; text?: string }>(),
|
defineProps<{ createdAt?: string; username?: string; my?: boolean; text?: string }>(),
|
||||||
{
|
{
|
||||||
|
my: false,
|
||||||
text: 'foobar',
|
text: 'foobar',
|
||||||
username: 'robot',
|
username: 'robot',
|
||||||
},
|
},
|
||||||
@@ -34,19 +35,13 @@ const avatarLetter = computed(() => {
|
|||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
|
|
||||||
<v-sheet
|
<v-sheet color="transparent" class="d-flex ga-2" :class="{ 'flex-row-reverse': props.my }">
|
||||||
color="transparent"
|
<!-- <v-avatar size="36" color="deep-purple-lighten-4">-->
|
||||||
class="d-flex ga-2"
|
<!-- <span class="text-deep-purple-darken-2">{{ avatarLetter }}</span>-->
|
||||||
:class="{ 'flex-row-reverse': props.side === 'right' }"
|
<!-- </v-avatar>-->
|
||||||
>
|
|
||||||
<v-avatar size="36" color="deep-purple-lighten-4">
|
<!-- :class="props.my ? 'message-shaped-right' : 'message-shaped'"-->
|
||||||
<span class="text-deep-purple-darken-2">{{ avatarLetter }}</span>
|
<v-sheet class="pa-4 message-width rounded-lg" :color="props.my ? 'primary' : 'white'">
|
||||||
</v-avatar>
|
|
||||||
<v-sheet
|
|
||||||
class="pa-4 message-width"
|
|
||||||
:color="props.side === 'right' ? 'primary' : 'white'"
|
|
||||||
:class="props.side === 'right' ? 'message-shaped-right' : 'message-shaped'"
|
|
||||||
>
|
|
||||||
<span class="text-body-1">{{ props.text }}</span>
|
<span class="text-body-1">{{ props.text }}</span>
|
||||||
<span class="text-caption ml-2">{{ createdAt }}</span>
|
<span class="text-caption ml-2">{{ createdAt }}</span>
|
||||||
</v-sheet>
|
</v-sheet>
|
||||||
|
|||||||
@@ -1,9 +1,43 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { SocketDataReq, useSocketsStore } from '@/stores/sockets.ts'
|
||||||
|
import { useChatsStore } from '@/stores/chats.ts'
|
||||||
|
|
||||||
|
const socketsStore = useSocketsStore()
|
||||||
|
const chatsStore = useChatsStore()
|
||||||
|
|
||||||
|
const text = ref('')
|
||||||
|
|
||||||
|
const sendMessage = () => {
|
||||||
|
if (text.value.trim()) {
|
||||||
|
socketsStore.send({
|
||||||
|
type: SocketDataReq.CREATE_MESSAGE,
|
||||||
|
data: {
|
||||||
|
chat_id: chatsStore.selected,
|
||||||
|
text: text.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
text.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const isEmptyText = computed(() => {
|
||||||
|
return !text.value
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-row dense align="center">
|
<v-row dense align="center">
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field rounded="xl" bg-color="white" variant="outlined" hide-details label="Message">
|
<v-text-field
|
||||||
|
rounded="lg"
|
||||||
|
bg-color="white"
|
||||||
|
variant="outlined"
|
||||||
|
hide-details
|
||||||
|
label="Message"
|
||||||
|
v-model="text"
|
||||||
|
@keyup.enter="sendMessage"
|
||||||
|
>
|
||||||
<template v-slot:prepend-inner>
|
<template v-slot:prepend-inner>
|
||||||
<v-btn icon variant="text" density="compact" color="grey-darken-1">
|
<v-btn icon variant="text" density="compact" color="grey-darken-1">
|
||||||
<v-icon>mdi-emoticon-outline</v-icon>
|
<v-icon>mdi-emoticon-outline</v-icon>
|
||||||
@@ -12,14 +46,14 @@
|
|||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="auto">
|
<v-col v-if="false" cols="auto">
|
||||||
<v-btn icon variant="text" color="grey-darken-1">
|
<v-btn icon variant="text" color="grey-darken-1">
|
||||||
<v-icon>mdi-paperclip</v-icon>
|
<v-icon>mdi-paperclip</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="auto">
|
<v-col cols="auto">
|
||||||
<v-btn icon variant="flat" color="primary">
|
<v-btn :disabled="isEmptyText" icon variant="flat" color="primary" @click="sendMessage">
|
||||||
<v-icon>mdi-send</v-icon>
|
<v-icon>mdi-send</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|||||||
@@ -2,6 +2,16 @@
|
|||||||
import MessageToolbar from '@/components/MessageToolbar.vue'
|
import MessageToolbar from '@/components/MessageToolbar.vue'
|
||||||
import MessageForm from '@/components/MessageForm.vue'
|
import MessageForm from '@/components/MessageForm.vue'
|
||||||
import MessageData from '@/components/MessageData.vue'
|
import MessageData from '@/components/MessageData.vue'
|
||||||
|
import { useMessagesStore } from '@/stores/messages.ts'
|
||||||
|
import { useAuthStore } from '@/stores/auth.ts'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const messagesStore = useMessagesStore()
|
||||||
|
|
||||||
|
const messages = computed(() => {
|
||||||
|
return [...messagesStore.messages]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -14,8 +24,14 @@ import MessageData from '@/components/MessageData.vue'
|
|||||||
color="grey-lighten-3"
|
color="grey-lighten-3"
|
||||||
class="flex-grow-1 d-flex flex-column overflow-hidden"
|
class="flex-grow-1 d-flex flex-column overflow-hidden"
|
||||||
>
|
>
|
||||||
<v-card-text class="flex-grow-1 d-flex ga-4 flex-column flex-column-reverse overflow-y-auto">
|
<v-card-text class="flex-grow-1 d-flex ga-1 flex-column overflow-y-auto justify-end">
|
||||||
<message-data />
|
<message-data
|
||||||
|
v-for="message in messages"
|
||||||
|
:key="message.id"
|
||||||
|
:text="message.text"
|
||||||
|
:my="authStore.me?.id === message.user_id"
|
||||||
|
:created-at="message.created_at"
|
||||||
|
/>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions class="flex-grow-0 bg-white pa-4">
|
<v-card-actions class="flex-grow-0 bg-white pa-4">
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useSharedWebSocket, WsDataType } from '../composables/useSharedWebSocket'
|
|
||||||
|
|
||||||
const message = ref('')
|
const message = ref('')
|
||||||
const selectedChat = ref('')
|
const selectedChat = ref('')
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ export interface User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface WsData {
|
export interface WsData {
|
||||||
type: WsDataType
|
type: WsDataType2
|
||||||
// data: Chat | Message | User | User[] | Message[] | Chat[]
|
// data: Chat | Message | User | User[] | Message[] | Chat[]
|
||||||
data: unknown
|
data: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum WsDataType {
|
export enum WsDataType2 {
|
||||||
GET_CHATS = 'GET_CHATS',
|
GET_CHATS = 'GET_CHATS',
|
||||||
GET_USERS = 'GET_USERS',
|
GET_USERS = 'GET_USERS',
|
||||||
GET_MESSAGES = 'GET_MESSAGES',
|
GET_MESSAGES = 'GET_MESSAGES',
|
||||||
@@ -36,7 +36,7 @@ export enum WsDataType {
|
|||||||
ERROR = 'ERROR',
|
ERROR = 'ERROR',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum COMMAND {
|
export enum COMMAND2 {
|
||||||
CONNECT = 'CONNECT',
|
CONNECT = 'CONNECT',
|
||||||
SEND = 'SEND',
|
SEND = 'SEND',
|
||||||
CLOSE = 'CLOSE',
|
CLOSE = 'CLOSE',
|
||||||
@@ -68,24 +68,24 @@ export function useSharedWebSocket(options?: { url?: string; autoConnect?: true
|
|||||||
const { type, data, connected, message } = event.data
|
const { type, data, connected, message } = event.data
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WsDataType.USER:
|
case WsDataType2.USER:
|
||||||
break
|
break
|
||||||
case WsDataType.CHATS:
|
case WsDataType2.CHATS:
|
||||||
chats.value = data
|
chats.value = data
|
||||||
break
|
break
|
||||||
case WsDataType.MESSAGES:
|
case WsDataType2.MESSAGES:
|
||||||
messages.value = data
|
messages.value = data
|
||||||
// if (options.onMessage) {
|
// if (options.onMessage) {
|
||||||
// options.onMessage(data)
|
// options.onMessage(data)
|
||||||
// }
|
// }
|
||||||
break
|
break
|
||||||
case WsDataType.CREATE_MESSAGE:
|
case WsDataType2.CREATE_MESSAGE:
|
||||||
messages.value.push(data)
|
messages.value.push(data)
|
||||||
break
|
break
|
||||||
case WsDataType.STATUS:
|
case WsDataType2.STATUS:
|
||||||
isConnected.value = connected
|
isConnected.value = connected
|
||||||
break
|
break
|
||||||
case WsDataType.ERROR:
|
case WsDataType2.ERROR:
|
||||||
error.value = message
|
error.value = message
|
||||||
logout()
|
logout()
|
||||||
break
|
break
|
||||||
@@ -93,7 +93,7 @@ export function useSharedWebSocket(options?: { url?: string; autoConnect?: true
|
|||||||
}
|
}
|
||||||
|
|
||||||
worker.value.port.postMessage({
|
worker.value.port.postMessage({
|
||||||
command: COMMAND.CONNECT,
|
command: COMMAND2.CONNECT,
|
||||||
data: { url: url, token: getToken() },
|
data: { url: url, token: getToken() },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ export function useSharedWebSocket(options?: { url?: string; autoConnect?: true
|
|||||||
const send = (data: WsData) => {
|
const send = (data: WsData) => {
|
||||||
if (worker.value) {
|
if (worker.value) {
|
||||||
worker.value.port.postMessage({
|
worker.value.port.postMessage({
|
||||||
command: COMMAND.SEND,
|
command: COMMAND2.SEND,
|
||||||
data: data,
|
data: data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ export function useSharedWebSocket(options?: { url?: string; autoConnect?: true
|
|||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
if (worker.value) {
|
if (worker.value) {
|
||||||
worker.value.port.postMessage({ command: COMMAND.CLOSE })
|
worker.value.port.postMessage({ command: COMMAND2.CLOSE })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
import type { WsData } from '@/composables/useSharedWebSocket.ts'
|
||||||
|
import type { User } from '@/stores/users.ts'
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
const token = ref(localStorage.getItem('token'))
|
const token = ref(localStorage.getItem('token'))
|
||||||
|
const me = ref<User>()
|
||||||
|
|
||||||
async function login(email: string) {
|
async function login(email: string) {
|
||||||
try {
|
try {
|
||||||
@@ -25,5 +28,16 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { token, login }
|
const isAuth = computed(() => !!token.value)
|
||||||
|
|
||||||
|
function getToken() {
|
||||||
|
return localStorage.getItem('token')
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
token.value = ''
|
||||||
|
return localStorage.removeItem('token')
|
||||||
|
}
|
||||||
|
|
||||||
|
return { me, token, isAuth, login, logout, getToken }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import type { User } from '@/stores/users.ts'
|
||||||
|
|
||||||
|
export interface Chat {
|
||||||
|
id: string
|
||||||
|
type_id: number
|
||||||
|
name: string
|
||||||
|
users: User[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChatsStore = defineStore('chats', () => {
|
||||||
|
const chats = ref<Chat[]>([])
|
||||||
|
const selected = ref<string>()
|
||||||
|
|
||||||
|
return { chats, selected }
|
||||||
|
})
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export interface Message {
|
||||||
|
id: number
|
||||||
|
text: string
|
||||||
|
user_id: number
|
||||||
|
created_at: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useMessagesStore = defineStore('messages', () => {
|
||||||
|
const messages = ref<Message[]>([])
|
||||||
|
|
||||||
|
return { messages }
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,5 +1,122 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
import { type Chat, useChatsStore } from '@/stores/chats.ts'
|
||||||
|
import { useAuthStore } from '@/stores/auth.ts'
|
||||||
|
import { type Message, useMessagesStore } from '@/stores/messages.ts'
|
||||||
|
|
||||||
export const useSockets = defineStore('sockets', () => {
|
export enum SocketDataReq {
|
||||||
return {}
|
GET_CHATS = 'GET_CHATS',
|
||||||
|
CREATE_CHAT = 'CREATE_CHAT',
|
||||||
|
GET_USERS = 'GET_USERS',
|
||||||
|
GET_USER = 'GET_USER',
|
||||||
|
GET_MESSAGES = 'GET_MESSAGES',
|
||||||
|
CREATE_MESSAGE = 'CREATE_MESSAGE',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SocketDataRes {
|
||||||
|
USERS = 'USERS',
|
||||||
|
CHATS = 'CHATS',
|
||||||
|
MESSAGES = 'MESSAGES',
|
||||||
|
MESSAGE = 'MESSAGE',
|
||||||
|
USER = 'USER',
|
||||||
|
STATUS = 'STATUS',
|
||||||
|
ERROR = 'ERROR',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum COMMAND {
|
||||||
|
CONNECT = 'CONNECT',
|
||||||
|
SEND = 'SEND',
|
||||||
|
CLOSE = 'CLOSE',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSocketsStore = defineStore('sockets', () => {
|
||||||
|
const url = 'ws://localhost:3000/ws'
|
||||||
|
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const chatsStore = useChatsStore()
|
||||||
|
const messagesStore = useMessagesStore()
|
||||||
|
|
||||||
|
const isConnected = ref(false)
|
||||||
|
const error = ref<string>()
|
||||||
|
const worker = ref<SharedWorker>()
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
console.log('INIT SHARED WORKER')
|
||||||
|
|
||||||
|
if (!window.SharedWorker) {
|
||||||
|
console.log('SharedWorker not supported')
|
||||||
|
error.value = 'SharedWorker not supported'
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.value = new SharedWorker(new URL('@/workers/worker.js', import.meta.url), {
|
||||||
|
type: 'module',
|
||||||
|
})
|
||||||
|
|
||||||
|
worker.value.port.onmessage = (event) => {
|
||||||
|
const { type, data, connected, message } = event.data
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SocketDataRes.USERS:
|
||||||
|
console.log('USERS_LIST', data)
|
||||||
|
break
|
||||||
|
case SocketDataRes.USER:
|
||||||
|
console.log('USER', data)
|
||||||
|
authStore.me = data
|
||||||
|
break
|
||||||
|
case SocketDataRes.CHATS:
|
||||||
|
console.log('CHATS', data)
|
||||||
|
chatsStore.chats = data
|
||||||
|
break
|
||||||
|
case SocketDataRes.MESSAGES:
|
||||||
|
console.log('MESSAGES', data)
|
||||||
|
|
||||||
|
messagesStore.messages = data.reverse()
|
||||||
|
// if (options.onMessage) {
|
||||||
|
// options.onMessage(data)
|
||||||
|
// }
|
||||||
|
break
|
||||||
|
case SocketDataRes.MESSAGE:
|
||||||
|
console.log('MESSAGE', data)
|
||||||
|
messagesStore.messages.push(data)
|
||||||
|
break
|
||||||
|
case SocketDataRes.STATUS:
|
||||||
|
isConnected.value = connected
|
||||||
|
break
|
||||||
|
case SocketDataRes.ERROR:
|
||||||
|
error.value = message
|
||||||
|
authStore.logout()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
function postMessage(command: COMMAND, data?: unknown) {
|
||||||
|
if (worker.value) worker.value.port.postMessage({ command, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
function connect() {
|
||||||
|
postMessage(COMMAND.CONNECT, { url: url, token: authStore.getToken() })
|
||||||
|
}
|
||||||
|
|
||||||
|
const send = (data: unknown) => {
|
||||||
|
postMessage(COMMAND.SEND, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
postMessage(COMMAND.CLOSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (worker.value) close()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
isConnected,
|
||||||
|
error,
|
||||||
|
send,
|
||||||
|
close,
|
||||||
|
init,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
id: number
|
||||||
|
email: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useUsersStore = defineStore('users', () => {
|
||||||
|
const users = ref<User[]>([])
|
||||||
|
|
||||||
|
return { users }
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,47 +1,53 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
import { useSharedWebSocket, WsDataType } from '@/composables/useSharedWebSocket.ts'
|
|
||||||
import ChatsPane from '@/components/ChatsPane.vue'
|
import ChatsPane from '@/components/ChatsPane.vue'
|
||||||
import MessagesPane from '@/components/MessagesPane.vue'
|
import MessagesPane from '@/components/MessagesPane.vue'
|
||||||
|
import { useSocketsStore } from '@/stores/sockets.ts'
|
||||||
|
import { useChatsStore } from '@/stores/chats.ts'
|
||||||
|
|
||||||
const { messages, chats, isConnected, error, send } = useSharedWebSocket({ autoConnect: true })
|
const socketsStore = useSocketsStore()
|
||||||
|
// const { messages, chats, isConnected, error, send } = useSharedWebSocket({ autoConnect: true })
|
||||||
|
|
||||||
|
// const socketsStore = useSocketsStore()
|
||||||
|
|
||||||
|
const chatsStore = useChatsStore()
|
||||||
|
|
||||||
const message = ref('')
|
const message = ref('')
|
||||||
const selectedChat = ref('')
|
const selectedChat = ref('')
|
||||||
|
|
||||||
const onChatClick = (id: string) => {
|
// const onChatClick = (id: string) => {
|
||||||
console.log(id)
|
// console.log(id)
|
||||||
selectedChat.value = id
|
// selectedChat.value = id
|
||||||
send({
|
// send({
|
||||||
type: WsDataType.GET_MESSAGES,
|
// type: WsDataType.GET_MESSAGES,
|
||||||
data: { chat_id: id },
|
// data: { chat_id: id },
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
const sendMessage = () => {
|
// const sendMessage = () => {
|
||||||
if (message.value.trim()) {
|
// if (message.value.trim()) {
|
||||||
send({
|
// send({
|
||||||
type: WsDataType.CREATE_MESSAGE,
|
// type: WsDataType.CREATE_MESSAGE,
|
||||||
data: {
|
// data: {
|
||||||
chat_id: selectedChat.value,
|
// chat_id: selectedChat.value,
|
||||||
text: message.value,
|
// text: message.value,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
message.value = ''
|
// message.value = ''
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
onMounted(() => {
|
||||||
|
socketsStore.init()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-row no-gutters class="h-100">
|
<v-row no-gutters class="h-100">
|
||||||
<v-col cols="12" md="4" lg="3">
|
<v-col cols="12" md="4" lg="3" sm="5">
|
||||||
<chats-pane />
|
<chats-pane />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="8" lg="9" class="h-100">
|
<v-col cols="12" md="8" lg="9" sm="7" class="h-100">
|
||||||
<!-- <messages-pane />-->
|
<messages-pane v-if="chatsStore.selected" />
|
||||||
<div>error:{{ error }}</div>
|
|
||||||
<div>is connected:{{ isConnected }}</div>
|
|
||||||
<div>chats {{ chats }}</div>
|
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -6,18 +6,15 @@ const authStore = useAuthStore()
|
|||||||
|
|
||||||
const email = ref('vadim.olonin@gmail.com')
|
const email = ref('vadim.olonin@gmail.com')
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
console.log('onSubmit')
|
|
||||||
await authStore.login(email.value)
|
await authStore.login(email.value)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-row justify="center" class="h-100 mt-10">
|
<v-row justify="center" align="center" class="h-100">
|
||||||
<v-col cols="12" md="4" lg="4">
|
<v-col cols="12" md="4" lg="4">
|
||||||
<v-card elevation="0">
|
<v-card elevation="0" border rounded="lg">
|
||||||
<v-card-item class="justify-center mb-4">
|
<v-card-title class="mb-2">Sign in</v-card-title>
|
||||||
<v-img rounded="lg" src="img.png" width="160" height="160" />
|
|
||||||
</v-card-item>
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<form @submit.prevent="onSubmit">
|
<form @submit.prevent="onSubmit">
|
||||||
<div class="d-flex flex-column ga-4">
|
<div class="d-flex flex-column ga-4">
|
||||||
@@ -27,11 +24,11 @@ async function onSubmit() {
|
|||||||
v-model="email"
|
v-model="email"
|
||||||
placeholder="email"
|
placeholder="email"
|
||||||
type="email"
|
type="email"
|
||||||
rounded="xl"
|
rounded="lg"
|
||||||
/>
|
/>
|
||||||
<div class="d-flex ga-4 align-center justify-space-between">
|
<div class="d-flex ga-4 align-center justify-space-between">
|
||||||
<v-switch color="black" label="Keep me signed in" hide-details></v-switch>
|
<v-switch color="black" label="Keep me signed in" hide-details></v-switch>
|
||||||
<v-btn variant="flat" rounded="xl" type="submit" color="black">login</v-btn>
|
<v-btn variant="flat" rounded="lg" type="submit" color="black">login</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -16,6 +16,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
proxy: {
|
proxy: {
|
||||||
'/login': 'http://localhost:3000',
|
'/login': 'http://localhost:3000',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user