implement empty states for contacts and channels

This commit is contained in:
liamcottle
2025-02-16 21:25:06 +13:00
parent b2873ec983
commit 660efb3fca
5 changed files with 48 additions and 12 deletions

View File

@@ -2,10 +2,24 @@
<div class="flex flex-col h-full w-full overflow-hidden">
<!-- channels -->
<div class="h-full overflow-y-auto">
<div v-if="channels.length > 0" class="h-full overflow-y-auto">
<ChannelListItem :key="channel.idx" v-for="channel of channels" :channel="channel" @click="onChannelClick(channel)"/>
</div>
<!-- empty state -->
<div v-if="channels.length === 0" class="mx-auto my-auto">
<div class="flex flex-col mx-auto my-auto text-gray-700 text-center">
<div class="mb-2 mx-auto">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-10">
<path fill-rule="evenodd" d="M8.25 6.75a3.75 3.75 0 1 1 7.5 0 3.75 3.75 0 0 1-7.5 0ZM15.75 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM2.25 9.75a3 3 0 1 1 6 0 3 3 0 0 1-6 0ZM6.31 15.117A6.745 6.745 0 0 1 12 12a6.745 6.745 0 0 1 6.709 7.498.75.75 0 0 1-.372.568A12.696 12.696 0 0 1 12 21.75c-2.305 0-4.47-.612-6.337-1.684a.75.75 0 0 1-.372-.568 6.787 6.787 0 0 1 1.019-4.38Z" clip-rule="evenodd" />
<path d="M5.082 14.254a8.287 8.287 0 0 0-1.308 5.135 9.687 9.687 0 0 1-1.764-.44l-.115-.04a.563.563 0 0 1-.373-.487l-.01-.121a3.75 3.75 0 0 1 3.57-4.047ZM20.226 19.389a8.287 8.287 0 0 0-1.308-5.135 3.75 3.75 0 0 1 3.57 4.047l-.01.121a.563.563 0 0 1-.373.486l-.115.04c-.567.2-1.156.349-1.764.441Z" />
</svg>
</div>
<div class="font-semibold">No Channels</div>
<div>Add an encrypted channel to send broadcast messages.</div>
</div>
</div>
</div>
</template>

View File

@@ -44,10 +44,23 @@
</div>
<!-- contacts -->
<div class="h-full overflow-y-auto">
<div v-if="contacts.length > 0" class="h-full overflow-y-auto">
<ContactListItem :key="contact.publicKey" v-for="contact of searchedContacts" :contact="contact" @click="onContactClick(contact)"/>
</div>
<!-- empty state -->
<div v-if="contacts.length === 0" class="mx-auto my-auto">
<div class="flex flex-col mx-auto my-auto text-gray-700 text-center">
<div class="mb-2 mx-auto">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-10">
<path fill-rule="evenodd" d="M5.636 4.575a.75.75 0 0 1 0 1.061 9 9 0 0 0 0 12.728.75.75 0 1 1-1.06 1.06c-4.101-4.1-4.101-10.748 0-14.849a.75.75 0 0 1 1.06 0Zm12.728 0a.75.75 0 0 1 1.06 0c4.101 4.1 4.101 10.75 0 14.85a.75.75 0 1 1-1.06-1.061 9 9 0 0 0 0-12.728.75.75 0 0 1 0-1.06ZM7.757 6.697a.75.75 0 0 1 0 1.06 6 6 0 0 0 0 8.486.75.75 0 0 1-1.06 1.06 7.5 7.5 0 0 1 0-10.606.75.75 0 0 1 1.06 0Zm8.486 0a.75.75 0 0 1 1.06 0 7.5 7.5 0 0 1 0 10.606.75.75 0 0 1-1.06-1.06 6 6 0 0 0 0-8.486.75.75 0 0 1 0-1.06ZM9.879 8.818a.75.75 0 0 1 0 1.06 3 3 0 0 0 0 4.243.75.75 0 1 1-1.061 1.061 4.5 4.5 0 0 1 0-6.364.75.75 0 0 1 1.06 0Zm4.242 0a.75.75 0 0 1 1.061 0 4.5 4.5 0 0 1 0 6.364.75.75 0 0 1-1.06-1.06 3 3 0 0 0 0-4.243.75.75 0 0 1 0-1.061ZM10.875 12a1.125 1.125 0 1 1 2.25 0 1.125 1.125 0 0 1-2.25 0Z" clip-rule="evenodd" />
</svg>
</div>
<div class="font-semibold">No Contacts</div>
<div>If someone Adverts, they will show up here.</div>
</div>
</div>
</div>
</template>
@@ -58,10 +71,12 @@ import IconButton from "../IconButton.vue";
import DropDownMenu from "../DropDownMenu.vue";
import DropDownMenuItem from "../DropDownMenuItem.vue";
import ContactListItem from "./ContactListItem.vue";
import ConnectButtons from "../connect/ConnectButtons.vue";
export default {
name: 'ContactsList',
components: {
ConnectButtons,
ContactListItem,
DropDownMenuItem,
DropDownMenu,

View File

@@ -5,7 +5,7 @@
<Header/>
<!-- tabs -->
<div v-if="GlobalState.selfInfo" class="bg-white border-b border-gray-200">
<div v-if="GlobalState.connection || (contacts.length > 0 || channels.length > 0)" class="bg-white border-b border-gray-200">
<div class="-mb-px flex">
<div @click="tab = 'contacts'" class="w-full border-b-2 py-3 px-1 text-center text-sm font-medium cursor-pointer" :class="[ tab === 'contacts' ? 'border-blue-500 text-blue-600' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700']">Contacts</div>
<div @click="tab = 'channels'" class="w-full border-b-2 py-3 px-1 text-center text-sm font-medium cursor-pointer" :class="[ tab === 'channels' ? 'border-blue-500 text-blue-600' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700']">Channels</div>
@@ -13,13 +13,13 @@
</div>
<!-- tab content -->
<div v-if="GlobalState.selfInfo" class="flex h-full w-full overflow-hidden">
<div v-if="GlobalState.connection || (contacts.length > 0 || channels.length > 0)" class="flex h-full w-full overflow-hidden">
<ContactsList v-if="tab === 'contacts'" :contacts="contacts" @contact-click="onContactClick"/>
<ChannelsList v-if="tab === 'channels'" :channels="channels" @channel-click="onChannelClick"/>
</div>
<!-- not connected and no content -->
<div v-if="!GlobalState.connection && contacts.length === 0" class="mx-auto my-auto">
<div v-if="!GlobalState.connection && contacts.length === 0 && channels.length === 0" class="mx-auto my-auto">
<ConnectButtons/>
</div>

View File

@@ -61,6 +61,7 @@ class Connection {
// clear previous connection state
GlobalState.selfInfo = null;
GlobalState.contacts = [];
GlobalState.channels = [];
GlobalState.batteryPercentage = null;
// update connection and listen for events
@@ -156,6 +157,7 @@ class Connection {
// fetch data after database is ready
await this.loadContacts();
await this.loadChannels();
await this.syncMessages();
await this.updateBatteryPercentage();
@@ -178,6 +180,17 @@ class Connection {
GlobalState.contacts = await GlobalState.connection.getContacts();
}
static async loadChannels() {
// todo fetch from device when implemented in firmware
GlobalState.channels = [
{
idx: 0,
name: "Public Channel",
description: "This is the default public channel.",
},
];
}
static async updateBatteryPercentage() {
if(GlobalState.connection){
try {

View File

@@ -8,13 +8,7 @@ const globalState = reactive({
batteryPercentage: null,
batteryPercentageInterval: null,
contacts: [],
channels: [
{
idx: 0,
name: "Public Channel",
description: "This is the default public channel.",
},
],
channels: [],
});
export default globalState;