Skip to content

Commit 1df4a41

Browse files
committed
Refactor AuthMenuItems into its own AuthProvider so it has full control
1 parent cb8c9bc commit 1df4a41

4 files changed

Lines changed: 70 additions & 26 deletions

File tree

llms/extensions/github_auth/ui/index.mjs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { ref } from "vue"
1+
import { ref, computed, inject } from "vue"
2+
3+
let ext
24

35
const SignIn = {
46
template: `
@@ -55,12 +57,58 @@ const SignIn = {
5557
}
5658
}
5759

60+
const AuthMenuItems = {
61+
template: `
62+
<div class="px-4 py-2 text-sm border-b border-[var(--user-border)]">
63+
<div class="font-medium whitespace-nowrap overflow-hidden text-ellipsis">{{ auth.displayName || auth.userName }}</div>
64+
<div class="text-xs whitespace-nowrap overflow-hidden text-ellipsis">{{ auth.email }}</div>
65+
</div>
66+
67+
<button type="button"
68+
@click="handleLogout"
69+
class="w-full text-left px-4 py-2 text-sm flex items-center whitespace-nowrap hover:bg-[var(--background)]/50">
70+
<svg class="w-4 h-4 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
71+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
72+
</svg>
73+
Sign Out
74+
</button>
75+
`,
76+
emits: ['done'],
77+
props: { auth: Object },
78+
setup(props, { emit }) {
79+
const ctx = inject('ctx')
80+
const showComponents = computed(() => {
81+
const args = { auth: props.auth }
82+
return Object.values(ctx.userMenuItemComponents).filter(def => def.show(args)).map(def => def.component)
83+
})
84+
85+
async function handleLogout() {
86+
emit('done')
87+
await ctx.ai.signOut()
88+
// Reload the page to show sign-in screen
89+
window.location.reload()
90+
}
91+
92+
return {
93+
showComponents,
94+
handleLogout,
95+
}
96+
}
97+
}
5898

5999
export default {
60100
install(ctx) {
61-
// Override SignIn component
101+
ext = ctx.scope("credentials")
102+
103+
ctx.setUserMenuItems({
104+
auth: {
105+
component: AuthMenuItems,
106+
show: ({ auth }) => !!auth?.userId
107+
}
108+
})
109+
62110
ctx.components({
63111
SignIn,
64112
})
65113
}
66-
}
114+
}

llms/ui/app.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@
626626
.-my-1\.5 {
627627
margin-block: calc(var(--spacing) * -1.5);
628628
}
629+
.my-1 {
630+
margin-block: calc(var(--spacing) * 1);
631+
}
629632
.my-2 {
630633
margin-block: calc(var(--spacing) * 2);
631634
}

llms/ui/ctx.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export class AppContext {
153153
this.updateThreadFilters = []
154154
this.threadHeaderComponents = {}
155155
this.threadFooterComponents = {}
156+
this.userMenuItemComponents = {}
156157
this.top = {}
157158
this.left = {}
158159
this.leftTop = {}
@@ -370,6 +371,9 @@ export class AppContext {
370371
setThreadFooters(components) {
371372
Object.assign(this.threadFooterComponents, components)
372373
}
374+
setUserMenuItems(components) {
375+
Object.assign(this.userMenuItemComponents, components)
376+
}
373377

374378
async createJsonResult(res) {
375379
return this.ai.createJsonResult(res)

llms/ui/modules/layout.mjs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const Welcome = {
2929

3030
const Avatar = {
3131
template: `
32-
<div v-if="$ai.auth?.profileUrl" class="relative" ref="avatarContainer">
32+
<div v-if="$ai.auth?.profileUrl && showComponents.length" class="relative" ref="avatarContainer">
3333
<img
3434
@click.stop="toggleMenu"
3535
:src="$ai.auth.profileUrl"
@@ -39,21 +39,12 @@ const Avatar = {
3939
<div
4040
v-if="showMenu"
4141
@click.stop
42-
class="absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 z-50 border" :class="[$styles.messageAssistant]"
43-
>
44-
<div class="px-4 py-2 text-sm border-b border-[var(--user-border)]">
45-
<div class="font-medium whitespace-nowrap overflow-hidden text-ellipsis">{{ $ai.auth.displayName || $ai.auth.userName }}</div>
46-
<div class="text-xs whitespace-nowrap overflow-hidden text-ellipsis">{{ $ai.auth.email }}</div>
42+
class="absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 z-50 border" :class="[$styles.messageAssistant]">
43+
44+
<div v-for="component in showComponents">
45+
<component :is="component" :auth="$ai.auth" @done="showMenu = false" />
4746
</div>
48-
<button type="button"
49-
@click="handleLogout"
50-
class="w-full text-left px-4 py-2 text-sm flex items-center whitespace-nowrap hover:bg-[var(--background)]/50"
51-
>
52-
<svg class="w-4 h-4 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
53-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
54-
</svg>
55-
Sign Out
56-
</button>
47+
5748
</div>
5849
</div>
5950
`,
@@ -79,20 +70,18 @@ const Avatar = {
7970
showMenu.value = !showMenu.value
8071
}
8172

82-
async function handleLogout() {
83-
showMenu.value = false
84-
await ai.signOut()
85-
// Reload the page to show sign-in screen
86-
window.location.reload()
87-
}
88-
8973
// Close menu when clicking outside
9074
const handleClickOutside = (event) => {
9175
if (showMenu.value && avatarContainer.value && !avatarContainer.value.contains(event.target)) {
9276
showMenu.value = false
9377
}
9478
}
9579

80+
const showComponents = computed(() => {
81+
const args = { auth: ai.auth }
82+
return Object.values(ctx.userMenuItemComponents).filter(def => def.show(args)).map(def => def.component)
83+
})
84+
9685
onMounted(() => {
9786
document.addEventListener('click', handleClickOutside)
9887
})
@@ -103,10 +92,10 @@ const Avatar = {
10392

10493
return {
10594
authTitle,
106-
handleLogout,
10795
showMenu,
10896
toggleMenu,
10997
avatarContainer,
98+
showComponents,
11099
}
111100
}
112101
}

0 commit comments

Comments
 (0)