1
1
<script setup lang="ts">
2
2
import { NAvatar , NDropdown , NEllipsis , NIcon , NSpace } from ' naive-ui' ;
3
+
3
4
import { computed , defineProps , h } from ' vue' ;
4
5
6
+ import { useRouter } from ' vue-router' ;
7
+
8
+ import type { DropdownProps } from ' naive-ui' ;
9
+ import type { Component } from ' vue' ;
10
+
11
+ import type { ArrayElement } from ' ~/utils/typescript.utils' ;
12
+
5
13
import IconAccount from ' ~/components/icons/IconAccount.vue' ;
14
+ import IconAccountAdd from ' ~/components/icons/IconAccountAdd.vue' ;
15
+ import IconCog from ' ~/components/icons/IconCog.vue' ;
16
+ import IconExternalLink from ' ~/components/icons/IconExternalLink.vue' ;
6
17
import IconLogOut from ' ~/components/icons/IconLogOut.vue' ;
7
18
8
19
import { Route } from ' ~/router' ;
9
- import { useUserSettingsStoreRefs } from ' ~/stores/settings.store' ;
20
+ import { TraktService } from ' ~/services/trakt.service' ;
21
+ import { ExternaLinks } from ' ~/settings/external.links' ;
22
+ import { useAuthSettingsStore } from ' ~/stores/settings/auth.store' ;
23
+ import {
24
+ defaultUser ,
25
+ useUserSettingsStore ,
26
+ useUserSettingsStoreRefs ,
27
+ } from ' ~/stores/settings/user.store' ;
10
28
import { Blurs , Colors } from ' ~/styles/colors.style' ;
11
29
import { useI18n } from ' ~/utils' ;
12
30
13
- const i18n = useI18n ( ' route ' ) ;
31
+ import { createTab } from ' ~/utils/browser/browser.utils ' ;
14
32
15
- const { userSetting } = useUserSettingsStoreRefs ();
33
+ const i18n = useI18n (' navbar_settings' );
34
+ const router = useRouter ();
35
+
36
+ const { user, userSetting, userSettings } = useUserSettingsStoreRefs ();
37
+ const { setCurrentUser } = useUserSettingsStore ();
38
+ const { syncRestoreAuth } = useAuthSettingsStore ();
16
39
17
40
const avatar = computed (() => userSetting .value ?.user ?.images ?.avatar ?.full );
18
41
const username = computed (() => userSetting .value ?.user ?.username );
@@ -24,35 +47,105 @@ defineProps({
24
47
},
25
48
});
26
49
27
- const options = [
28
- {
29
- label: ' Logout' ,
30
- key: ' logout' ,
31
- icon : () =>
32
- h (NIcon , null , {
33
- default : () => h (IconLogOut , { size: ' 1.5em' }),
34
- }),
35
- },
50
+ const toOption = (
51
+ key : string ,
52
+ icon : Component | string ,
53
+ label ? : string ,
54
+ ): ArrayElement <DropdownProps [' options' ]> => {
55
+ return {
56
+ label: label ?? i18n (key ),
57
+ key ,
58
+ icon : () => {
59
+ if (typeof icon === ' string' )
60
+ return h (NAvatar , { src: icon , size: 16 , round: true });
61
+ return h (NIcon , null , { default : () => h (icon ) });
62
+ },
63
+ };
64
+ };
65
+
66
+ const baseOptions: DropdownProps [' options' ] = [
67
+ { type: ' divider' , key: ' account-divider' },
68
+ toOption (' settings' , IconCog ),
69
+ { type: ' divider' , key: ' external-links' },
70
+ toOption (' trakt' , IconExternalLink ),
71
+ { type: ' divider' , key: ' session-divider' },
72
+ toOption (' login' , IconAccountAdd ),
73
+ toOption (' logout' , IconLogOut ),
36
74
];
75
+
76
+ const users = computed (() => {
77
+ return Object .entries (userSettings .value ).filter (
78
+ ([key , value ]) => value && key !== username .value && key !== defaultUser ,
79
+ );
80
+ });
81
+
82
+ const options = computed <DropdownProps [' options' ]>(() => {
83
+ if (users .value .length ) {
84
+ return [
85
+ ... users .value .map (([key , value ]) =>
86
+ toOption (` user-${key } ` , value ?.user ?.images ?.avatar ?.full || IconAccount , key ),
87
+ ),
88
+ { type: ' divider' , key: ' users-divider' },
89
+ ... baseOptions ,
90
+ ];
91
+ }
92
+
93
+ return baseOptions ;
94
+ });
95
+
96
+ const login = async () => {
97
+ const response = await TraktService .approve ();
98
+ return createTab ({ url: response .url });
99
+ };
100
+
101
+ const loadUser = async (account : string ) => {
102
+ const auth = await syncRestoreAuth (account );
103
+ return TraktService .importAuthentication (auth );
104
+ };
105
+
106
+ const onSelect: DropdownProps [' onSelect' ] = async (key : string , { label }) => {
107
+ console .info (' Selected:' , key );
108
+ switch (key ) {
109
+ case ' settings' :
110
+ return router .push (Route .Settings );
111
+ case ' trakt' :
112
+ return createTab ({
113
+ url: ExternaLinks .trakt [TraktService .isStaging ? ' staging' : ' production' ],
114
+ });
115
+ case ' login' :
116
+ return login ();
117
+ case ' logout' :
118
+ await TraktService .logout ();
119
+ await setCurrentUser ();
120
+ if (user .value !== defaultUser ) return loadUser (user .value );
121
+ return router .push (Route .Login );
122
+ default :
123
+ if (typeof label === ' string' && key .startsWith (' user-' )) {
124
+ return loadUser (label );
125
+ }
126
+ console .error (' Unknown key:' , key );
127
+ }
128
+ };
37
129
</script >
38
130
39
131
<template >
40
132
<NDropdown
41
133
trigger =" hover"
42
134
:options =" options"
43
135
:to =" parentElement"
44
- placement =" bottom-end "
136
+ placement =" bottom"
45
137
size =" small"
46
138
class =" dropdown"
47
139
:style =" {
48
140
'margin-top': '0.75rem',
49
141
'margin-right': '-0.25rem',
50
142
'text-align': 'left',
51
- 'min-width': 'calc(100vw / 6 - 3px)',
143
+ 'min-width': 'max(calc(100vw / 6), 9rem)',
144
+ 'max-width': '20rem',
52
145
'background-color': Colors.bgBlurBlackHover,
53
146
'backdrop-filter': Blurs.blur,
54
147
}"
55
- @select =" (...args: any[]) => console.info(args) "
148
+ @select =" onSelect "
56
149
>
57
150
<NSpace justify =" space-around" align =" center" :wrap =" false" >
58
151
<NEllipsis
@@ -76,7 +169,7 @@ const options = [
76
169
round
77
170
size =" small"
78
171
color =" transparent"
79
- style =" position : absolute ; top : 3 px ; right : 0.5rem "
172
+ style =" position : absolute ; top : 0.125 rem ; right : 0.5rem ; scale : 0.8 "
80
173
/>
81
174
<NIcon v-else style =" position : absolute ; top : 0.4rem ; right : 0.75rem " size =" 1.5em" >
82
175
<IconAccount />
0 commit comments