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

Add header

parent 2a15a86b
Branches
No related tags found
No related merge requests found
Showing
with 266 additions and 80 deletions
<svg viewBox="0 0 1900 1000" xmlns="http://www.w3.org/2000/svg" fill="none" style="
opacity:0.3;
--bg-base: rgb(20, 20, 20);
--accent-1:rgba(255, 90, 109, 0.56);
--accent-2:rgb(118, 56, 81);
--accent-3:rgb(198, 112, 78);
--accent-4:rgb(116, 0, 73);
--accent-5:rgb(112, 54, 47);
--accent-6:rgba(253, 39, 39, 0.32);
--accent-7:rgb(111, 37, 116);
">
<defs>
<radialGradient gradientTransform="matrix(-381.8856201171875,-718.64599609375,1352.26904296875,-718.5903930664062,1460.033935546875,1616.3768310546875)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint3_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-color="var(--bg-base)" offset="0.82292"/>
<stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(-381.8856201171875,-718.64599609375,1352.26904296875,-718.5903930664062,1523.080078125,1511.2974853515625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint4_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-color="var(--bg-base)" offset="0.82292"/>
<stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(-367.9964599609375,668.3052368164062,-775.7698364257812,-427.1709289550781,1491.2763671875,646.0341186523438)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint5_radial">
<stop stop-color="var(--accent-1)" offset="0.32813"/>
<stop stop-opacity="0" stop-color="white" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(-708.8882446289062,428.3532409667969,-802.1248168945312,-1340.3924560546875,1895.1649169921875,806.4420166015625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint6_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-color="var(--bg-base)" offset="0.78938"/>
<stop stop-opacity="0" stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,-137.4949951171875,-345.2243957519531)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint0_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-color="var(--accent-1)" offset="0.08333"/>
<stop stop-color="var(--accent-2)" offset="0.36458"/>
<stop stop-color="var(--bg-base)" offset="0.65804"/>
<stop stop-color="var(--accent-3)" offset="0.79852"/>
<stop stop-color="var(--bg-base)" offset="0.94271"/>
<stop stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,293.6920166015625,64.984619140625)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint1_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-color="var(--accent-4)" offset="0.08333"/>
<stop stop-color="var(--accent-5)" offset="0.3338"/>
<stop stop-color="var(--bg-base)" offset="0.65804"/>
<stop stop-color="var(--accent-3)" offset="0.79852"/>
<stop stop-color="var(--bg-base)" offset="0.94271"/>
<stop stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
<radialGradient gradientTransform="matrix(1168.929931640625,2499.95166015625,-2448.661865234375,1144.9478759765625,598.625732421875,180.31497192382812)" gradientUnits="userSpaceOnUse" r="1" cy="0" cx="0" id="paint2_radial">
<stop stop-color="var(--bg-base)"/>
<stop stop-opacity="0" stop-color="var(--accent-6)" offset="0.14063"/>
<stop stop-color="var(--accent-7)" offset="0.3338"/>
<stop stop-color="var(--bg-base)" offset="0.65804"/>
<stop stop-color="var(--accent-3)" offset="0.79852"/>
<stop stop-color="var(--bg-base)" offset="0.94271"/>
<stop stop-color="var(--bg-base)" offset="1"/>
</radialGradient>
</defs>
<g>
<g id="svg_1">
<path id="svg_2" fill="url(#paint0_radial)" d="m1502.44912,585.67754c33.10025,39.73622 61.75559,56.73205 38.47076,89.01439c-207.12817,287.18063 -533.50156,932.74603 -749.82619,1033.23391c-875.97368,290.34215 -1794.58437,-383.1195 -929.17869,-874.49315c865.40612,-491.37708 -320.65596,-399.01561 171.18459,-730.25605c572.8894,-385.82665 1337.65958,210.53419 1469.34952,482.5009z"/>
<path id="svg_3" fill="url(#paint1_radial)" d="m587.07817,485.4941l419.66703,159.06733c24.18089,9.16687 41.4162,25.71878 46.94265,45.09221l69.01414,241.88691l313.39974,-96.93921c25.09839,-7.76404 53.68243,-6.95072 77.8676,2.21572l419.66703,159.06737c44.52885,16.87946 61.75559,56.73076 38.47076,89.01482l-111.72942,154.90774c-9.73238,13.49242 -25.6043,24.12944 -44.92329,30.10606l-547.85575,169.45915l120.53144,422.44097c4.32598,15.15593 1.1576,30.93353 -8.9435,44.57172l-156.90567,211.74998l-496.69002,-188.26365c-24.18518,-9.16644 -41.4162,-25.71577 -46.94265,-45.0905c-121.18569,-424.72615 -163.28659,-464.9033 -346.7638,-1107.95457c-17.09383,-59.91029 10.94014,-95.04032 20.67252,-108.5336l111.72985,-154.90851c23.28397,-32.28243 78.25947,-44.76903 122.79132,-27.88995z"/>
<path id="svg_4" fill="url(#paint2_radial)" d="m892.01032,600.82489l419.66703,159.06737c24.18518,9.16644 41.4162,25.71835 46.94265,45.09178l69.01843,241.88605l313.39546,-96.93792c25.10268,-7.76447 53.68672,-6.95072 77.8676,2.21572l419.66703,159.06737c44.53314,16.87946 61.75559,56.73076 38.47076,89.01482l-111.72942,154.90774c-9.73238,13.49242 -25.6043,24.12944 -44.92329,30.10606l-547.85146,169.45915l120.53144,422.44097c4.32169,15.15593 1.1576,30.93353 -8.94779,44.57172l-156.90567,211.74998l-496.69002,-188.26365c-24.18518,-9.16644 -41.4162,-25.71577 -46.94265,-45.0905l-69.01414,-241.88605l-313.40017,96.93792c-25.10096,7.76447 -53.68414,6.94986 -77.86803,-2.21658c0,0 -435.59683,-164.42146 -346.34633,-402.50031c89.25033,-238.07456 341.27735,-122.28069 592.71786,-200.05397l-120.6472,-422.84656c-4.25738,-14.91069 -1.26478,-30.42933 8.4676,-43.92261l111.72942,-154.9086c23.28482,-32.28234 78.26204,-44.76894 122.79089,-27.88991z"/>
<path id="svg_5" fill="url(#paint3_radial)" d="m484.48046,2237.81313l-319.39785,-1215.0982l2173.29209,-725.58785l1371.32646,1940.68605l-3225.2207,0z"/>
<path id="svg_6" fill="url(#paint4_radial)" d="m547.5287,2132.73345l-319.39798,-1215.0982l2173.29007,-725.58785l1371.32646,1940.68605l-3225.21855,0z"/>
<ellipse id="svg_7" fill="url(#paint5_radial)" ry="668.30572" rx="728.49213" cy="646.03415" cx="1234.93732"/>
<path id="svg_8" fill="url(#paint6_radial)" d="m2824.13444,684.91842l-1735.35896,1585.86861l-837.3177,-2104.40458l1818.07193,-1439.64029l754.60472,1958.17626z" opacity="0.5"/>
</g>
</g>
</svg>
\ No newline at end of file
<script setup lang="ts">
import { ref, onMounted, defineAsyncComponent } from 'vue';
import { useUserStore, UsedWallet } from '@/stores/user.store';
import { useSettingsStore, UsedWallet } from '@/stores/settings.store';
import AppHeader from '@/components/AppHeader.vue';
const WalletOnboarding = defineAsyncComponent(() =>
import('@/components/WalletOnboarding.vue')
);
const WalletOnboarding = defineAsyncComponent(() => import('@/components/onboarding/index'));
const hasUser = ref(true);
const userStore = useUserStore();
const settingsStore = useSettingsStore();
onMounted(() => {
userStore.loadSettings();
hasUser.value = userStore.settings.account !== undefined;
settingsStore.loadSettings();
hasUser.value = settingsStore.settings.account !== undefined;
});
const complete = (data: { account: string; wallet: UsedWallet }) => {
hasUser.value = true;
userStore.settings.account = data.account;
userStore.settings.wallet = data.wallet;
userStore.saveSettings();
settingsStore.setSettings({
account: data.account,
wallet: data.wallet
});
};
</script>
<template>
<div id="shadcn-root" class="dark">
<main>
<RouterView />
</main>
<aside v-if="userStore.isLoaded && !hasUser" class="fixed inset-0 flex items-center justify-center z-20">
<WalletOnboarding @complete="complete" />
</aside>
<div id="app-main">
<AppHeader/>
<main class="mt-[65px]">
<RouterView />
</main>
<aside v-if="settingsStore.isLoaded && !hasUser" class="fixed inset-0 flex items-center justify-center z-20">
<WalletOnboarding @complete="complete" />
</aside>
</div>
</div>
</template>
<style scoped>
#app-main {
overflow-y: auto;
height: 100%;
width: 100%;
background: url('/bg.svg') no-repeat center center fixed;
background-size: cover;
}
#shadcn-root {
background-color: hsl(var(--background));
color: hsl(var(--foreground));
height: 100vh;
width: 100%;
overflow: hidden;
font-family: Arial, sans-serif;
}
</style>
<script setup lang="ts">
import { useSettingsStore, getWalletIcon } from '@/stores/settings.store';
import { mdiLogoutVariant } from '@mdi/js';
import { computed } from 'vue';
import { Button } from '@/components/ui/button';
const settingsStore = useSettingsStore();
const hasUser = computed(() => settingsStore.settings.account !== undefined);
const logout = () => {
settingsStore.resetSettings();
window.location.reload();
};
</script>
<template>
<header class="fixed top-0 left-0 z-10 bg-black/60 backdrop-blur-sm w-full">
<nav class="flex items-center relative sm:justify-center p-4 w-full h-[65px] border-b-[1px] border-white/25">
<div class="hidden sm:inline absolute top-[14px] left-[30px]" v-if="hasUser">
<Button variant="outline" class="cursor-default" v-if="settingsStore.isLoaded && hasUser">
<span class="font-bold">@{{ settingsStore.settings.account }}</span>
</Button>
</div>
<div class="flex items-center space-x-4">
<img src="/icon.svg" class="h-8 w-8" />
<h1 class="hidden sm:inline text-2xl font-bold">Hive Bridge</h1>
<Button variant="outline" class="absolute top-[14px] left-[45px] inline-flex sm:hidden" v-if="settingsStore.isLoaded && hasUser">
<h1 v-if="hasUser" class="inline sm:hidden text-lg sm:text-xl font-bold">@{{ settingsStore.settings.account }}</h1>
</Button>
</div>
<div class="absolute top-[14px] right-[30px]">
<Button variant="outline" v-if="settingsStore.isLoaded && hasUser" @click="logout">
<img v-if="hasUser" :src="getWalletIcon(settingsStore.settings.wallet!)" class="h-6 w-6" />
<span class="hidden sm:inline font-bold">Disconnect</span>
<svg class="inline sm:hidden" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path style="fill: hsl(var(--foreground))" :d="mdiLogoutVariant"/></svg>
</Button>
</div>
</nav>
</header>
</template>
\ No newline at end of file
......@@ -2,6 +2,7 @@
import { ref, onMounted, computed } from 'vue';
import { useMetamaskStore } from '@/stores/metamask.store';
import { Button } from '@/components/ui/button';
import { useSettingsStore } from '@/stores/settings.store';
const walletStore = useMetamaskStore();
......@@ -25,6 +26,8 @@ const safeCall = async(storeFn: (...args: any) => any) => {
}
};
const settingsStore = useSettingsStore();
const connect = safeCall.bind(undefined, () => walletStore.connect());
const install = safeCall.bind(undefined, () => walletStore.install());
const call = (method: string, params?: any) => safeCall(() => walletStore.call(method, params));
......@@ -49,6 +52,7 @@ onMounted(() => {
<Button :disabled="performingOperation" @click="connect">Reconnect</Button>
<Button :disabled="performingOperation" @click="install">{{ isInstalled ? "Reinstall" : "Install" }}</Button>
<Button :disabled="performingOperation" @click="getPublicKeys" v-if="isInstalled">getPublicKeys</Button>
<Button @click="settingsStore.resetSettings">logout</Button>
</div>
<div v-else-if="metamaskFound">
<Button :disabled="performingOperation" @click="connect">Connect</Button>
......
......@@ -3,7 +3,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
import OnboardingButton from "@/components/onboarding/OnboardingWalletButton.vue";
import { onMounted, ref } from 'vue';
import { useMetamaskStore } from "@/stores/metamask.store";
import { getWalletIcon, UsedWallet } from "@/stores/user.store";
import { getWalletIcon, UsedWallet } from "@/stores/settings.store";
const hasMetamask = ref(false);
const hasKeychain = ref(false);
......
<script setup lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { getWalletIcon, stringifyWalletName, UsedWallet } from "@/stores/user.store";
import { getWalletIcon, stringifyWalletName, UsedWallet } from "@/stores/settings.store";
import { mdiClose } from "@mdi/js";
const emit = defineEmits(["close"]);
......
<script setup lang="ts">
import { UsedWallet } from '@/stores/user.store';
import SelectWallet from './onboarding/SelectWallet.vue';
import { UsedWallet } from '@/stores/settings.store';
import { ref } from 'vue';
import PeakVaultConnect from './onboarding/wallets/peakvault/PeakVaultConnect.vue';
import KeychainConnect from './onboarding/wallets/keychain/KeychainConnect.vue';
import MetamaskConnect from './onboarding/wallets/metamask/MetamaskConnect.vue';
import ThankYou from './onboarding/ThankYou.vue';
import SelectWallet from '@/components/onboarding/SelectWallet.vue';
import PeakVaultConnect from '@/components/onboarding/wallets/peakvault/PeakVaultConnect.vue';
import KeychainConnect from '@/components/onboarding/wallets/keychain/KeychainConnect.vue';
import MetamaskConnect from '@/components/onboarding/wallets/metamask/MetamaskConnect.vue';
import ThankYou from '@/components/onboarding/ThankYou.vue';
const emit = defineEmits(["complete"]);
......
export { default } from '@/components/onboarding/WalletOnboarding.vue';
\ No newline at end of file
......@@ -5,7 +5,7 @@ import step1 from "@/assets/icons/wallets/keychain/step1.webp";
import { ref } from 'vue';
import { mdiClose } from '@mdi/js';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { UsedWallet, getWalletIcon } from '@/stores/user.store';
import { UsedWallet, getWalletIcon } from '@/stores/settings.store';
const emit = defineEmits(["setaccount", "close"]);
......
......@@ -5,7 +5,7 @@ import { ref, onMounted } from 'vue';
import step1 from "@/assets/icons/wallets/metamask/step1.webp";
import step2 from "@/assets/icons/wallets/metamask/step2.webp";
import { mdiClose, mdiContentCopy, mdiCheck } from '@mdi/js';
import { UsedWallet, getWalletIcon } from '@/stores/user.store';
import { UsedWallet, getWalletIcon } from '@/stores/settings.store';
import { useMetamaskStore } from "@/stores/metamask.store";
import { Combobox, ComboboxAnchor, ComboboxTrigger, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/components/ui/combobox';
import { Check, Search } from 'lucide-vue-next';
......
......@@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
import step1 from "@/assets/icons/wallets/peakvault/step1.webp";
import { ref } from 'vue';
import { mdiClose } from '@mdi/js';
import { UsedWallet, getWalletIcon } from '@/stores/user.store';
import { UsedWallet, getWalletIcon } from '@/stores/settings.store';
const emit = defineEmits(["setaccount", "close"]);
......
<script setup lang="ts">
import MetamaskExample from '@/components/MetamaskExample.vue'
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card'
</script>
<template>
<MetamaskExample />
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 p-8">
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
<Card class="bg-black/40 backdrop-blur-sm">
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
Card Content
</CardContent>
<CardFooter>
Card Footer
</CardFooter>
</Card>
</div>
</template>
\ No newline at end of file
import { defineStore } from "pinia"
import { connectMetamask, type MetamaskWallet } from "../utils/wallet/metamask"
export const useWalletStore = defineStore('wallet', {
state: () => ({
metamask: undefined as undefined | MetamaskWallet,
performingOperation: false
}),
getters: {
isConnected: state => !!state.metamask,
isFlask: state => state.metamask?.isFlaskDetected,
isInstalled: state => state.metamask?.isInstalled
},
actions: {
async call(method: string, params: any) {
try {
this.performingOperation = true;
if (!this.metamask)
throw new Error('Call: Metamask not connected');
return await this.metamask.invokeSnap(method, params);
} finally {
this.performingOperation = false;
}
},
async connect() {
try {
this.performingOperation = true;
if (!this.metamask)
this.metamask = await connectMetamask();
} finally {
this.performingOperation = false;
}
},
async install() {
try {
this.performingOperation = true;
if (!this.metamask)
throw new Error('Install: Metamask not connected');
await this.metamask.installSnap();
} finally {
this.performingOperation = false;
}
}
}
})
......@@ -36,7 +36,7 @@ const settings = {
account: undefined as string | undefined,
};
export const useUserStore = defineStore('user', {
export const useSettingsStore = defineStore('settings', {
state: () => ({
isLoaded: false,
settings
......@@ -46,6 +46,10 @@ export const useUserStore = defineStore('user', {
wallet: state => state.settings.wallet,
},
actions: {
// Used for logout
resetSettings() {
this.setSettings({} as typeof settings);
},
loadSettings() {
const localSettings = localStorage.getItem('hivebridge_settings');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment