-
Notifications
You must be signed in to change notification settings - Fork 6
/
App.vue
238 lines (225 loc) · 8.86 KB
/
App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<script setup lang="ts">
import { onMounted, ref, watchEffect } from 'vue';
import { CogIcon, CollectionIcon, SparklesIcon, ViewGridIcon } from '@heroicons/vue/outline';
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
import { toSvg } from 'jdenticon';
import { chiaState } from './state/chia';
import { IpcService } from './helpers/ipc-service';
import { useRouter } from 'vue-router';
import { useIntervalFn } from '@vueuse/core';
const router = useRouter();
onMounted(() => {
router.push('/');
});
const navigation = [
{ name: 'My NFTs', to: '/nfts', icon: ViewGridIcon },
{ name: 'My Collections', to: '/collections', icon: CollectionIcon },
{ name: 'Single Mint', to: '/minting', icon: SparklesIcon },
// { name: 'Bulk Mint (soon)', to: '/bulk', icon: CollectionIcon },
];
const secondaryNavigation = [{ name: 'Settings', to: '/settings', icon: CogIcon }];
const fingerprints = ref<string[]>([]);
const loginInProgress = ref(true);
const loginError = ref<any>(undefined);
const svgString = ref('');
watchEffect(() => {
if (chiaState.activeFingerprint) {
svgString.value = toSvg(chiaState.activeFingerprint, 36);
} else {
svgString.value = '';
}
});
const ipc = new IpcService();
const getSyncStatus = async () => {
const { synced, syncing, network_name } = await ipc.send('get_sync_status');
chiaState.synced = synced;
chiaState.syncing = syncing;
chiaState.networkName = network_name;
};
const getFingerprints = async () => {
const response = await ipc.send<{ fingerprints: string[]; fingerprint: string }>('get_public_keys');
fingerprints.value = response.fingerprints;
chiaState.activeFingerprint = response.fingerprint;
};
const init = async () => {
try {
await getSyncStatus();
await getFingerprints();
} catch (e) {
loginError.value = e;
}
loginInProgress.value = false;
useIntervalFn(async () => {
try {
await getSyncStatus();
if (loginError.value) {
loginError.value = undefined;
await getFingerprints();
}
} catch (e) {
loginError.value = e;
chiaState.synced = false;
chiaState.syncing = false;
fingerprints.value = [];
chiaState.activeFingerprint = undefined;
}
}, 5000);
};
init();
const login = async (fingerprint: string) => {
loginInProgress.value = true;
const response = await ipc.send<{ fingerprints: string[]; fingerprint: string }>('log_in', {
fingerprint,
});
chiaState.activeFingerprint = response.fingerprint;
const { synced, syncing } = await ipc.send('get_sync_status');
chiaState.synced = synced;
chiaState.syncing = syncing;
setTimeout(async () => {
const { synced, syncing } = await ipc.send('get_sync_status');
chiaState.synced = synced;
chiaState.syncing = syncing;
}, 1000);
loginInProgress.value = false;
};
</script>
<template>
<div class="h-full flex">
<!-- Static sidebar for desktop -->
<div class="flex flex-shrink-0">
<div class="flex flex-col w-64">
<!-- Sidebar component, swap this element with another sidebar if you like -->
<div class="flex-1 flex flex-col min-h-0 border-r border-gray-200 bg-gray-100">
<div class="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
<div class="flex items-center flex-shrink-0 px-4">
<img class="h-8 w-auto" src="/mintgarden-logo.svg" alt="Workflow" />
</div>
<nav class="mt-5 flex-1" aria-label="Sidebar">
<div class="px-2 space-y-1">
<router-link
custom
v-slot="{ href, navigate, isActive }"
v-for="item in navigation"
:key="item.name"
:to="item.to"
>
<a
:href="href"
@click="navigate"
:class="[
isActive ? 'bg-gray-200 text-gray-900' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900',
'group flex items-center px-2 py-2 text-sm font-medium rounded-md',
]"
:aria-current="isActive ? 'page' : undefined"
>
<component
:is="item.icon"
:class="[
isActive ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500',
'mr-3 flex-shrink-0 h-6 w-6',
]"
aria-hidden="true"
/>
{{ item.name }}
</a>
</router-link>
</div>
<hr class="border-t border-gray-200 my-5" aria-hidden="true" />
<div class="flex-1 px-2 space-y-1">
<router-link
custom
v-slot="{ href, navigate, isActive }"
v-for="item in secondaryNavigation"
:key="item.name"
:to="item.to"
>
<a
:href="href"
@click="navigate"
:class="[
isActive ? 'bg-gray-200 text-gray-900' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900',
'group flex items-center px-2 py-2 text-sm font-medium rounded-md',
]"
:aria-current="isActive ? 'page' : undefined"
>
<component
:is="item.icon"
:class="[
isActive ? 'text-gray-500' : 'text-gray-400 group-hover:text-gray-500',
'mr-3 flex-shrink-0 h-6 w-6',
]"
aria-hidden="true"
/>
{{ item.name }}
</a>
</router-link>
</div>
</nav>
</div>
<div class="flex-shrink-0 flex border-t border-gray-200 p-4">
<Menu as="div" class="relative inline-block text-left">
<div class="flex items-center mb-4 gap-3">
<div class="flex h-9 w-9 items-center justify-center">
<span class="flex h-3 w-3">
<span
class="relative inline-flex rounded-full h-3 w-3"
:class="chiaState.synced ? 'bg-emerald-500' : chiaState.syncing ? 'bg-orange-500' : 'bg-red-500'"
></span>
</span>
</div>
<span class="text-gray-900 text-sm">
{{ chiaState.synced ? 'Synced' : chiaState.syncing ? 'Syncing' : 'Not synced' }}
</span>
</div>
<div>
<MenuButton class="flex-shrink-0 w-full group block">
<div v-if="loginInProgress" class="text-sm font-medium text-gray-700">Logging in...</div>
<div v-else class="flex items-center">
<div v-html="svgString"></div>
<div class="ml-3">
<p class="text-sm font-medium text-gray-700 group-hover:text-gray-900">
{{ chiaState.activeFingerprint || 'Wallet Disconnected' }}
</p>
<p
v-if="fingerprints?.length > 0"
class="text-xs text-left font-medium text-gray-500 group-hover:text-gray-700"
>
Change key
</p>
</div>
</div>
</MenuButton>
</div>
<transition
enter-active-class="transition ease-out duration-100"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<MenuItems
class="origin-top-left bottom-full mb-2 absolute left-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="py-1">
<MenuItem v-for="fingerprint in fingerprints" v-slot="{ active }">
<a
href="#"
@click.prevent="login(fingerprint)"
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']"
>{{ fingerprint }}</a
>
</MenuItem>
</div>
</MenuItems>
</transition>
</Menu>
</div>
</div>
</div>
</div>
<div class="flex-1 overflow-auto min-w-min">
<router-view></router-view>
</div>
</div>
</template>