Skip to content
Snippets Groups Projects
Verified Commit 07f8987d authored by Mateusz Tyszczak's avatar Mateusz Tyszczak :scroll:
Browse files

Add dynamic route detection

parent ff50039b
No related branches found
No related tags found
No related merge requests found
Pipeline #118122 failed
......@@ -6,8 +6,9 @@ import AppSidebar from '@/components/sidebar';
import { SidebarProvider } from '@/components/ui/sidebar';
import ToggleSidebar from './components/sidebar/ToggleSidebar.vue';
import { Toaster } from 'vue-sonner';
import { useUserStore } from './stores/user.store';
import { getWax } from './stores/wax.store';
import { useUserStore } from '@/stores/user.store';
import { getWax } from '@/stores/wax.store';
import AppHeader from '@/components/AppHeader.vue';
const WalletOnboarding = defineAsyncComponent(() => import('@/components/onboarding/index'));
......@@ -49,8 +50,8 @@ const complete = async(data: { account: string; wallet: UsedWallet }) => {
<ToggleSidebar class="m-3" />
<RouterView />
</main>
<aside v-if="settingsStore.isLoaded && !hasUser" class="fixed inset-0 flex items-center justify-center z-20">
<WalletOnboarding @complete="complete" />
<aside v-if="walletStore.isWalletSelectModalOpen" class="fixed inset-0 flex items-center justify-center z-20">
<WalletOnboarding @close="walletStore.closeWalletSelectModal()" @complete="complete" />
</aside>
</SidebarProvider>
<Toaster theme="dark" closeButton richColors />
......
......@@ -11,6 +11,7 @@ const props = defineProps<{
description: string;
disabled?: boolean;
downloadUrl: string;
downloadUrlTriggersClick?: boolean;
}>();
const emit = defineEmits(['click']);
......@@ -28,7 +29,7 @@ const emit = defineEmits(['click']);
<TooltipProvider :delayDuration="200" disableHoverableContent>
<Tooltip>
<TooltipTrigger class="absolute right-4 top-1/2 transform -translate-y-1/2 w-8 h-8">
<a :href="props.downloadUrl" v-if="props.disabled" target="_blank">
<a :href="props.downloadUrl" @click="props.downloadUrlTriggersClick && emit('click')" v-if="props.disabled" target="_blank">
<Button variant="ghost" class="w-8 h-8 p-0">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path style="fill: hsl(var(--foreground))" :d="mdiDownload"/></svg>
</Button>
......
<script setup lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import OnboardingButton from "@/components/onboarding/OnboardingWalletButton.vue";
import { onMounted, onUnmounted, ref } from 'vue';
import { useMetamaskStore } from "@/stores/metamask.store";
import { Button } from "@/components/ui/button";
import { getWalletIcon, UsedWallet } from "@/stores/settings.store";
import { useWalletStore } from "@/stores/wallet.store";
import { mdiClose } from "@mdi/js";
import { computed } from "vue";
const hasMetamask = ref(false);
const hasKeychain = ref(false);
const hasPeakVault = ref(false);
let timeoutId: number;
const walletStore = useWalletStore();
const walletsStatus = computed(() => walletStore.walletsStatus);
const metamaskStore = useMetamaskStore();
const checkForWallets = () => {
if (!hasMetamask.value)
metamaskStore.connect().then(() => hasMetamask.value = true).catch(console.error);
if (!hasKeychain.value)
hasKeychain.value = "hive_keychain" in window;
if (!hasPeakVault.value)
hasPeakVault.value = "peakvault" in window;
};
onMounted(() => {
timeoutId = setTimeout(() => checkForWallets(), 1500) as unknown as number;
checkForWallets();
});
onUnmounted(() => {
clearTimeout(timeoutId);
});
const emit = defineEmits(["walletSelect"]);
const emit = defineEmits(["walletSelect", "close"]);
const useWallet = (type: UsedWallet) => {
emit("walletSelect", type);
};
const close = () => {
emit("close");
};
</script>
<template>
<Card class="w-[350px]">
<CardHeader>
<CardTitle>Select wallet</CardTitle>
<CardDescription>We support multiple on-chain wallets</CardDescription>
<CardTitle>
<div class="inline-flex justify-between w-full">
<div class="inline-flex items-center">
<span class="mt-[2px]">Select wallet</span>
</div>
<Button variant="ghost" size="sm" class="px-2" @click="close">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path style="fill: hsl(var(--foreground))" :d="mdiClose"/></svg>
</Button>
</div>
</CardTitle>
<CardDescription>If your wallet is not detected, try unlocking it and refreshing the page</CardDescription>
</CardHeader>
<CardContent class="space-y-2">
<OnboardingButton downloadUrl="https://docs.metamask.io/snaps/get-started/install-flask/" :disabled="!hasMetamask" @click="useWallet(UsedWallet.METAMASK)" :logoUrl="getWalletIcon(UsedWallet.METAMASK)" name="Metamask" description="Use your derived keys"/>
<OnboardingButton downloadUrl="https://hive-keychain.com/" :disabled="!hasKeychain" @click="useWallet(UsedWallet.KEYCHAIN)" :logoUrl="getWalletIcon(UsedWallet.KEYCHAIN)" name="Keychain" description="Use already imported accounts"/>
<OnboardingButton downloadUrl="https://vault.peakd.com/peakvault/guide.html#installation" :disabled="!hasPeakVault" @click="useWallet(UsedWallet.PEAKVAULT)" :logoUrl="getWalletIcon(UsedWallet.PEAKVAULT)" name="PeakVault" description="Use already imported accounts"/>
<OnboardingButton downloadUrl="https://docs.metamask.io/snaps/get-started/install-flask/" :disabled="!walletsStatus.metamask" @click="useWallet(UsedWallet.METAMASK)" :logoUrl="getWalletIcon(UsedWallet.METAMASK)" name="Metamask" description="Use your derived keys"/>
<OnboardingButton downloadUrl="https://hive-keychain.com/" :disabled="!walletsStatus.keychain" @click="useWallet(UsedWallet.KEYCHAIN)" :logoUrl="getWalletIcon(UsedWallet.KEYCHAIN)" name="Keychain" description="Use already imported accounts"/>
<OnboardingButton downloadUrl="https://vault.peakd.com/peakvault/guide.html#installation" :disabled="!walletsStatus.peakvault" @click="useWallet(UsedWallet.PEAKVAULT)" :logoUrl="getWalletIcon(UsedWallet.PEAKVAULT)" name="PeakVault" description="Use already imported accounts"/>
</CardContent>
<CardFooter></CardFooter>
</Card>
......
......@@ -7,7 +7,7 @@ import KeychainConnect from '@/components/onboarding/wallets/keychain/KeychainCo
import MetamaskConnect from '@/components/onboarding/wallets/metamask/MetamaskConnect.vue';
import ThankYou from '@/components/onboarding/ThankYou.vue';
const emit = defineEmits(["complete"]);
const emit = defineEmits(["complete", "close"]);
const selectedWallet = ref<UsedWallet | null>(null);
const selectedAccount = ref<string | null>(null);
......@@ -49,7 +49,7 @@ const backToStage1 = () => {
<template>
<div class="bg-black/30 backdrop-blur-sm h-full w-full z-50 flex items-center justify-center">
<div class="onboarding-container">
<SelectWallet v-if="stage_1_SelectWallet" @walletSelect="walletSelect" />
<SelectWallet v-if="stage_1_SelectWallet" @close="emit('close')" @walletSelect="walletSelect" />
<div v-if="stage_2_ConnectWallet">
<KeychainConnect v-if="selectedWallet === UsedWallet.KEYCHAIN" @close="backToStage1" @setaccount="setAccount" />
<PeakVaultConnect v-if="selectedWallet === UsedWallet.PEAKVAULT" @close="backToStage1" @setaccount="setAccount" />
......
......@@ -8,6 +8,8 @@ import { computed } from 'vue';
import { Button } from '@/components/ui/button';
import { useUserStore } from "@/stores/user.store";
import ThemeSwitch from "../ui/theme-switch";
import { useWalletStore } from "@/stores/wallet.store";
import { useRouter } from "vue-router";
const settingsStore = useSettingsStore();
const hasUser = computed(() => settingsStore.settings.account !== undefined);
......@@ -17,58 +19,77 @@ const logout = () => {
window.location.reload();
};
const router = useRouter();
const walletStore = useWalletStore();
const { toggleSidebar, isMobile } = useSidebar();
const userStore = useUserStore();
const items = [
{
title: "Home",
url: "/",
icon: mdiHomeOutline,
},
{
title: "Memo encryption",
url: "/sign/message",
icon: mdiMessageLockOutline,
},
{
title: "Transaction signing",
url: "/sign/transaction",
icon: mdiFileSign,
},
{
title: "Process Account Creation",
url: "/account/create",
icon: mdiAccountPlusOutline,
},
const groups = [{
title: "Account management",
items: [
{
title: "Home",
url: "/",
icon: mdiHomeOutline,
},
{
title: "Process Account Creation",
url: "/account/create",
icon: mdiAccountPlusOutline,
},
{
title: "Process Authority Update",
url: "/account/update",
icon: mdiAccountArrowUpOutline,
},
]
}, {
title: "Signing",
items: [
{
title: "Process Authority Update",
url: "/account/update",
icon: mdiAccountArrowUpOutline,
}
];
title: "Memo encryption",
url: "/sign/message",
icon: mdiMessageLockOutline,
},
{
title: "Transaction signing",
url: "/sign/transaction",
icon: mdiFileSign,
},
]
}];
</script>
<template>
<Sidebar>
<SidebarHeader class="pb-0">
<div class="flex items-center p-2">
<img src="/icon.svg" class="h-8 w-8" />
<span class="text-foreground/80 font-bold text-xl ml-2">Hive Bridge</span>
</div>
<div class="flex items-center rounded-lg p-2 mt-1 mx-1 bg-background/40 border">
<Avatar class="w-8 h-8 mr-2">
<AvatarImage v-if="userStore.profileImage" :src="userStore.profileImage" />
<AvatarImage :src="userStore.profileImage ? userStore.profileImage : '/icon.svg'" />
<AvatarFallback v-if="settingsStore.isLoaded && hasUser">{{ settingsStore.settings.account?.slice(0, 2) }}</AvatarFallback>
</Avatar>
<span class="font-bold max-w-[140px] truncate" v-if="settingsStore.isLoaded && hasUser">@{{ settingsStore.settings.account }}</span>
<ThemeSwitch class="ml-auto w-5 h-5 mr-1" />
</div>
<Button class="bg-background/40" variant="outline" @click="settingsStore.isLoaded && hasUser ? logout : walletStore.openWalletSelectModal()">
<img v-if="hasUser" :src="getWalletIcon(settingsStore.settings.wallet!)" class="h-6 w-6" />
<span class="font-bold">{{ settingsStore.isLoaded && hasUser ? 'Disconnect' : 'Connect' }}</span>
</Button>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel class="text-foreground/60">Hive Bridge</SidebarGroupLabel>
<SidebarGroup class="pb-0" v-for="group in groups" :key="group.title">
<SidebarGroupLabel class="text-foreground/60">{{ group.title }}</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="item in items" :key="item.title">
<SidebarMenuButton asChild>
<SidebarMenuItem v-for="item in group.items" :key="item.title">
<SidebarMenuButton asChild :class="{ 'bg-primary/5': router.currentRoute.value.path === item.url }">
<RouterLink @click="isMobile && toggleSidebar()" :to="item.url">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path style="fill: hsl(var(--foreground))" :d="item.icon"/></svg>
<span class="text-foreground/80">{{item.title}}</span>
......@@ -80,10 +101,6 @@ const items = [
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<Button class="bg-background/40" variant="outline" :disabled="!settingsStore.isLoaded || !hasUser" @click="logout">
<img v-if="hasUser" :src="getWalletIcon(settingsStore.settings.wallet!)" class="h-6 w-6" />
<span class="font-bold">Disconnect</span>
</Button>
</SidebarFooter>
</Sidebar>
</template>
......
......@@ -40,7 +40,7 @@ export const sidebarMenuButtonVariants = cva(
{
variants: {
variant: {
default: 'hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground',
default: 'hover:bg-primary/10 hover:text-sidebar-accent-foreground',
outline:
'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
},
......
......@@ -5,14 +5,44 @@ import { useMetamaskStore } from "./metamask.store";
import { createKeychainWalletFor } from "@/utils/wallet/keychain";
import { createPeakVaultWalletFor } from "@/utils/wallet/peakvault";
let intervalId: NodeJS.Timeout | undefined;
export const useWalletStore = defineStore('wallet', {
state: () => ({
wallet: undefined as undefined | Wallet
_walletsStatus: {
metamask: false,
keychain: false,
peakvault: false
},
wallet: undefined as undefined | Wallet,
isWalletSelectModalOpen: false
}),
getters: {
hasWallet: state => !!state.wallet,
walletsStatus: state => {
if (!intervalId) {
const metamaskStore = useMetamaskStore();
const checkForWallets = () => {
metamaskStore.connect().then(() => state._walletsStatus.metamask = true).catch(console.error);
state._walletsStatus.keychain = "hive_keychain" in window;
state._walletsStatus.peakvault = "peakvault" in window;
};
intervalId = setInterval(checkForWallets, 1000);
checkForWallets();
}
return state._walletsStatus;
}
},
actions: {
openWalletSelectModal() {
this.isWalletSelectModalOpen = true;
},
closeWalletSelectModal() {
this.isWalletSelectModalOpen = false;
},
async createWalletFor(settings: Settings) {
switch(settings.wallet) {
case UsedWallet.METAMASK: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment