Added libs
This commit is contained in:
254
p2private/vue/views/HomeView.vue
Normal file
254
p2private/vue/views/HomeView.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<script setup>
|
||||
import Button from '@/components/buttons/Button.vue';
|
||||
import Card from '@/components/cards/Card.vue';
|
||||
import InputComboBox from '@/components/inputs/InputComboBox.vue';
|
||||
import InputText from '@/components/inputs/InputText.vue';
|
||||
import Label from '@/components/labels/Label.vue';
|
||||
import { CheckIcon, DocumentTextIcon, EllipsisHorizontalIcon, GlobeAltIcon, LockClosedIcon, PaperAirplaneIcon, PaperClipIcon, ShieldCheckIcon, ShieldExclamationIcon, UserPlusIcon, UsersIcon, WifiIcon } from '@heroicons/vue/24/solid';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { p2privateApi } from '../api/p2privateApi';
|
||||
import { p2postApi } from '@/modules/p2post/api/p2postApi';
|
||||
|
||||
// const friends = ref([, {nickname:'Nickname2', unreadCount:2, publicKey:'1234aed233423c', isOnline:false, lastSeen:new Date()}])
|
||||
const friends = ref([])
|
||||
const activeFriend = ref(null)
|
||||
const myUsers = ref([])
|
||||
|
||||
const relays = ref([])
|
||||
|
||||
async function getRelays(){
|
||||
relays.value = await p2privateApi.getNetworks()
|
||||
}
|
||||
|
||||
async function getFriends(){
|
||||
const result = await p2privateApi.getFriends()
|
||||
for (const f of result){
|
||||
const m1 = {id:1, senderId:'me', content:"test Meeeeeeeeeeeeeeeeeeeeee", timestamp:new Date(), status:"SENT"}
|
||||
const m2 = {id:2, senderId:'peer', content:"test Peer", status:"RECEIVED", timestamp:new Date(), files:[{name:'file1', type:'image/jpeg', size:123}]}
|
||||
const mes = [m1,m2]
|
||||
const fr = {nickname:'Nickname', unreadCount:5, publicKey:f.pubkey, isOnline:true, messages:mes}
|
||||
friends.value.push(fr)
|
||||
}
|
||||
}
|
||||
|
||||
async function getMyUsers(){
|
||||
myUsers.value = await p2postApi.getMyUsers()
|
||||
}
|
||||
|
||||
const inputMessageText = ref("")
|
||||
async function createMessage(){
|
||||
const randomIndex = Math.floor(Math.random() * myUsers.value.length);
|
||||
const randomUser = myUsers.value[randomIndex]
|
||||
await p2privateApi.createMessage(randomUser.pubkey, activeFriend.value.publicKey, inputMessageText.value, [])
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
getRelays()
|
||||
getFriends()
|
||||
getMyUsers()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen bg-black text-yellow-400">
|
||||
<header class="border-b border-yellow-400/20 py-6">
|
||||
<div class="container mx-auto px-6">
|
||||
<div class="flex items-center space-x-4">
|
||||
<div class="text-3xl font-black">
|
||||
<span class="text-yellow-400">P2</span>
|
||||
<span class="text-white">PRIVATE</span>
|
||||
</div>
|
||||
<div class="w-1 h-8 bg-yellow-400"></div>
|
||||
<span class="text-gray-400">Encrypted Peer-to-Peer Messaging</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex h-screen">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="w-80 border-r border-yellow-400/20 flex flex-col">
|
||||
|
||||
<!-- Add Peer -->
|
||||
<Card class="m-4 border-yellow-400/20 p-4">
|
||||
<h3 class="text-lg font-bold text-yellow-400 mb-4 flex items-center">
|
||||
<UserPlusIcon class="h-5 w-5 mr-2" />
|
||||
Add Friend
|
||||
</h3>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<Label class="text-gray-300 mb-2 block text-sm">Public Key</Label>
|
||||
<InputText class="bg-black border-yellow-400/30 text-white font-mono text-sm" placeholder="Public Key"/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label class="text-gray-300 mb-2 block text-sm">Relay Networks</Label>
|
||||
<div class="space-y-2">
|
||||
<div v-for="relay of relays" class="flex items-center space-x-2">
|
||||
<input type="checkbox" :id="relay.id" name="options" :value="relay.name">
|
||||
<Label class="text-white text-sm">
|
||||
{{relay.name}}
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button @click="addFriend" class="w-full bg-yellow-400 hover:bg-yellow-300">
|
||||
<UserPlusIcon class="h-5 w-5 mr-2 text-black" />
|
||||
<span class="text-black">Add Peer</span>
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<!-- Friends list -->
|
||||
<div class="flex-1 overflow-hidden flex flex-col">
|
||||
<div class="px-4 py-2 border-b border-yellow-400/20">
|
||||
<h3 class="text-lg font-bold text-yellow-400 flex items-center">
|
||||
<UsersIcon class="w-5 h-5 mr-2" />
|
||||
Friends ({{friends.length}})
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto p-4 space-y-2">
|
||||
<div v-for="friend in friends">
|
||||
<div class="flex items-center space-x-3" @click="activeFriend = friend" :class="friend === activeFriend ? 'border rounded-lg border-yellow-400/30 p-1' : 'p-3'">
|
||||
<div class="relative">
|
||||
<img src="" alt="" class="w-12 h-12 rounded-full" />
|
||||
<div class="absolute -bottom-1 -right-1 w-4 h-4 rounded-full border-2 border-gray-500"
|
||||
:class="{'bg-green-400' : true}"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-white font-semibold truncate">{{friend.nickname}}</span>
|
||||
<span v-if="friend.unreadCount>0" class="bg-yellow-400 text-black text-xs font-bold px-2 py-1 rounded-full">
|
||||
{{friend.unreadCount}}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 font-mono truncate">{{friend.publicKey}}</p>
|
||||
<div class="flex items-center space-x-1 mt-1 text-xs text-gray-500">
|
||||
<div v-if="friend.isOnline" class="flex flex-row">
|
||||
<WifiIcon class="w-5 h-5 text-green-400" />
|
||||
Online
|
||||
</div>
|
||||
<div v-if="!friend.isOnline" class="flex flex-row">
|
||||
<WifiIcon class="h-5 w-5 text-gray-400" />
|
||||
<!-- Last seen {{ friend.lastSeen.toLocaleTimeString() }} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat -->
|
||||
<div v-if="activeFriend" class="flex-1 flex flex-col">
|
||||
<!-- Chat Header -->
|
||||
<div class="border-b border-yellow-400/20 p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="relative">
|
||||
<img
|
||||
src=""
|
||||
alt=""
|
||||
class="w-10 h-10 rounded-full"
|
||||
/>
|
||||
<div class="absolute -bottom-1 -right-1 w-3 h-3 rounded-full border-2 border-gray-500"
|
||||
:class="{'bg-green-400':activeFriend.isOnline}">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-white font-semibold">{{activeFriend.nickname}}</h3>
|
||||
<p class="text-xs text-gray-400 font-mono">{{activeFriend.publicKey}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-1 text-green-400">
|
||||
<LockClosedIcon class="h-5 w-5" />
|
||||
<span class="text-sm">End-to-End Encrypted</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-1 text-yellow-400">
|
||||
<GlobeAltIcon class="h-5 w-5"/>
|
||||
<span class="text-sm">Via Network Relay</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Messages -->
|
||||
<div class="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
<div v-for="message in activeFriend.messages"
|
||||
:key="message.id"
|
||||
class="flex justify-start"
|
||||
:class="{'justify-end':message.senderId=='me'}"
|
||||
>
|
||||
<!-- Message Content -->
|
||||
<div class="max-w-xs lg:max-w-md px-4 py-2 rounded-lg" :class="message.senderId == 'me' ? 'bg-yellow-400 text-black' : 'bg-gray-900 text-white'">
|
||||
|
||||
{{message.content}}
|
||||
|
||||
<!-- Files -->
|
||||
<div class="space-y-2 mb-2">
|
||||
<div v-for="file in message.files" class="flex items-center space-x-2 p-2 rounded">
|
||||
<Button class="p-1 h-auto hover:bg-black/20 gap-2">
|
||||
<DocumentTextIcon class="w-5 h-5" />
|
||||
<p class=" text-s">{{file.name}}</p>
|
||||
<p class="text-xs opacity-70">{{file.size}}</p>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Footer -->
|
||||
<div class="flex items-center justify-between text-xs opacity-80">
|
||||
<span>{{new Date(message.timestamp).toLocaleTimeString()}}</span>
|
||||
<div class="flex items-center space-x-1">
|
||||
<ShieldCheckIcon v-if="true" class="w-4 h-4"/>
|
||||
<ShieldExclamationIcon v-else class="w-4 h-4"/>
|
||||
<CheckIcon v-if="true" class="w-4 h-4"/>
|
||||
<EllipsisHorizontalIcon v-else class="w-4 h-4"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Input -->
|
||||
<div class="sticky bottom-0 border-t border-yellow-400/20 p-4">
|
||||
<!-- File Preview TODO from create post preview-->
|
||||
<div v-if="false" class="mb-3 p-3 bg-black border border-yellow-400/20 rounded-lg">
|
||||
</div>
|
||||
|
||||
<div class="flex items-end space-x-2">
|
||||
<Button class="border border-yellow-400 text-yellow-400 hover:bg-yellow-400 hover:text-black bg-transparent">
|
||||
Add Files
|
||||
</Button>
|
||||
|
||||
<div class="flex-1">
|
||||
<InputText class="bg-black border-yellow-400/30 text-white resize-none" v-model="inputMessageText"/>
|
||||
</div>
|
||||
|
||||
<Button @click="createMessage()" class="bg-yellow-400 text-black hover:bg-yellow-300">
|
||||
<!-- <Send size={16} /> -->
|
||||
Send
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- No Chat Selected -->
|
||||
<div v-if="!activeFriend" class="flex-1 flex items-center justify-center">
|
||||
<div class="text-center">
|
||||
<LockClosedIcon class="w-10 h-10 text-gray-600 mx-auto mb-4" />
|
||||
<h3 class="text-xl font-semibold text-gray-400 mb-2">Select a friend to start chatting</h3>
|
||||
<p class="text-gray-500">Your messages are end-to-end encrypted and decentralized</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user