Skip to content

Commit e6371c7

Browse files
ManUtopiKatinux
andauthored
feat(composable): add openInPopup(route, { width, height }) (#336)
Co-authored-by: Sébastien Chopin <[email protected]> Co-authored-by: Sébastien Chopin <[email protected]>
1 parent 6c5c4cd commit e6371c7

File tree

5 files changed

+59
-2
lines changed

5 files changed

+59
-2
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Nuxt Auth Utils automatically adds some plugins to fetch the current user sessio
6262

6363
```vue
6464
<script setup>
65-
const { loggedIn, user, session, fetch, clear } = useUserSession()
65+
const { loggedIn, user, session, fetch, clear, openInPopup } = useUserSession()
6666
</script>
6767
6868
<template>
@@ -74,6 +74,8 @@ const { loggedIn, user, session, fetch, clear } = useUserSession()
7474
<div v-else>
7575
<h1>Not logged in</h1>
7676
<a href="/auth/github">Login with GitHub</a>
77+
<!-- or open the OAuth route in a popup -->
78+
<button @click="openInPopup('/auth/github')">Login with GitHub</button>
7779
</div>
7880
</template>
7981
```
@@ -106,6 +108,10 @@ interface UserSessionComposable {
106108
* Clear the user session and remove the session cookie.
107109
*/
108110
clear: () => Promise<void>
111+
/**
112+
* Open the OAuth route in a popup that auto-closes when successful.
113+
*/
114+
openInPopup: (route: string, size?: { width?: number, height?: number }) => void
109115
}
110116
```
111117

playground/app.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
2-
const { user } = useUserSession()
2+
const { user, openInPopup } = useUserSession()
33
4+
const inPopup = ref(false)
45
const providers = computed(() =>
56
[
67
{
@@ -205,6 +206,8 @@ const providers = computed(() =>
205206
...p,
206207
prefetch: false,
207208
external: true,
209+
to: inPopup.value ? '#' : p.to,
210+
click: inPopup.value ? () => openInPopup(p.to) : void 0,
208211
})),
209212
)
210213
</script>
@@ -259,6 +262,14 @@ const providers = computed(() =>
259262
</UHeader>
260263
<UMain>
261264
<UContainer>
265+
<div class="text-xs mt-4">
266+
Popup mode <UToggle
267+
v-model="inPopup"
268+
size="xs"
269+
name="open-in-popup"
270+
label="Open in popup"
271+
/>
272+
</div>
262273
<NuxtPage />
263274
</UContainer>
264275
</UMain>

src/runtime/app/composables/session.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,41 @@ export function useUserSession(): UserSessionComposable {
3838
}
3939
}
4040

41+
const popupListener = (e: StorageEvent) => {
42+
if (e.key === 'temp-nuxt-auth-utils-popup') {
43+
fetch()
44+
window.removeEventListener('storage', popupListener)
45+
}
46+
}
47+
const openInPopup = (route: string, size: { width?: number, height?: number } = {}) => {
48+
// Set a local storage item to tell the popup that we pending auth
49+
localStorage.setItem('temp-nuxt-auth-utils-popup', 'true')
50+
51+
const width = size.width ?? 960
52+
const height = size.height ?? 600
53+
const top = (window.top?.outerHeight ?? 0) / 2
54+
+ (window.top?.screenY ?? 0)
55+
- height / 2
56+
const left = (window.top?.outerWidth ?? 0) / 2
57+
+ (window.top?.screenX ?? 0)
58+
- width / 2
59+
60+
window.open(
61+
route,
62+
'nuxt-auth-utils-popup',
63+
`width=${width}, height=${height}, top=${top}, left=${left}, toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no`,
64+
)
65+
66+
window.addEventListener('storage', popupListener)
67+
}
68+
4169
return {
4270
ready: computed(() => authReadyState.value),
4371
loggedIn: computed(() => Boolean(sessionState.value.user)),
4472
user: computed(() => sessionState.value.user || null),
4573
session: sessionState,
4674
fetch,
75+
openInPopup,
4776
clear,
4877
}
4978
}

src/runtime/app/plugins/session.client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,11 @@ export default defineNuxtPlugin(async (nuxtApp) => {
1212
await useUserSession().fetch()
1313
})
1414
}
15+
16+
if (localStorage.getItem('temp-nuxt-auth-utils-popup')) {
17+
// There is a local storage item. That's mean we are coming back in the popup
18+
localStorage.removeItem('temp-nuxt-auth-utils-popup')
19+
const error = useError()
20+
if (!error.value) window.close()
21+
}
1522
})

src/runtime/types/session.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ export interface UserSessionComposable {
5050
* Clear the user session and remove the session cookie.
5151
*/
5252
clear: () => Promise<void>
53+
/**
54+
* Open the OAuth route in a popup that auto-closes when successful.
55+
*/
56+
openInPopup: (route: string, size?: { width?: number, height?: number }) => void
5357
}

0 commit comments

Comments
 (0)