mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-19 03:47:31 +00:00
Compare commits
7 Commits
export-gen
...
mobile-dvh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bff8eaf99 | ||
|
|
bbf369c25b | ||
|
|
2063b39346 | ||
|
|
30f2fb0e7c | ||
|
|
06caa21a4d | ||
|
|
bdcb8b1137 | ||
|
|
28ab12e666 |
35
browser_tests/tests/mobileViewport.spec.ts
Normal file
35
browser_tests/tests/mobileViewport.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Mobile viewport', () => {
|
||||
test.beforeEach(async ({ comfyPage }) => {
|
||||
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
|
||||
})
|
||||
|
||||
test('@mobile App UI is not hidden under mobile browser UI', async ({
|
||||
comfyPage
|
||||
}) => {
|
||||
const viewportSize = await comfyPage.page.viewportSize()
|
||||
|
||||
// Top menu is visible
|
||||
const topMenu = comfyPage.page.locator('.comfyui-menu')
|
||||
await expect(topMenu).toBeVisible()
|
||||
|
||||
// Top menu is not cut off from the top
|
||||
const topMenuBox = await topMenu.boundingBox()
|
||||
expect(topMenuBox?.y).toBeGreaterThanOrEqual(0)
|
||||
|
||||
// Graph is visible
|
||||
const graphView = comfyPage.page.locator('.lgraphcanvas')
|
||||
await expect(graphView).toBeVisible()
|
||||
|
||||
// Graph is not cut off from the bottom
|
||||
const graphViewBox = await graphView.boundingBox()
|
||||
expect(graphViewBox).not.toBeNull()
|
||||
expect(viewportSize).not.toBeNull()
|
||||
expect(graphViewBox!.y + graphViewBox!.height).toBeLessThanOrEqual(
|
||||
viewportSize!.height
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -2,7 +2,7 @@
|
||||
<router-view />
|
||||
<ProgressSpinner
|
||||
v-if="isLoading"
|
||||
class="absolute inset-0 flex justify-center items-center h-screen"
|
||||
class="absolute inset-0 flex justify-center items-center h-dvh"
|
||||
/>
|
||||
<GlobalDialog />
|
||||
<BlockUI full-screen :blocked="isLoading" />
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
body {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background: var(--bg-color) var(--bg-img);
|
||||
|
||||
@@ -79,6 +79,7 @@ import Divider from 'primevue/divider'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||
import { SignInData, SignUpData } from '@/schemas/signInSchema'
|
||||
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
||||
|
||||
@@ -92,33 +93,32 @@ const { onSuccess } = defineProps<{
|
||||
}>()
|
||||
|
||||
const firebaseAuthStore = useFirebaseAuthStore()
|
||||
const { wrapWithErrorHandlingAsync } = useErrorHandling()
|
||||
|
||||
const isSignIn = ref(true)
|
||||
const toggleState = () => {
|
||||
isSignIn.value = !isSignIn.value
|
||||
}
|
||||
|
||||
const signInWithGoogle = () => {
|
||||
// Implement Google login
|
||||
console.log(isSignIn.value)
|
||||
console.log('Google login clicked')
|
||||
const signInWithGoogle = wrapWithErrorHandlingAsync(async () => {
|
||||
await firebaseAuthStore.loginWithGoogle()
|
||||
onSuccess()
|
||||
}
|
||||
})
|
||||
|
||||
const signInWithGithub = () => {
|
||||
// Implement Github login
|
||||
console.log(isSignIn.value)
|
||||
console.log('Github login clicked')
|
||||
const signInWithGithub = wrapWithErrorHandlingAsync(async () => {
|
||||
await firebaseAuthStore.loginWithGithub()
|
||||
onSuccess()
|
||||
}
|
||||
})
|
||||
|
||||
const signInWithEmail = async (values: SignInData | SignUpData) => {
|
||||
const { email, password } = values
|
||||
if (isSignIn.value) {
|
||||
await firebaseAuthStore.login(email, password)
|
||||
} else {
|
||||
await firebaseAuthStore.register(email, password)
|
||||
const signInWithEmail = wrapWithErrorHandlingAsync(
|
||||
async (values: SignInData | SignUpData) => {
|
||||
const { email, password } = values
|
||||
if (isSignIn.value) {
|
||||
await firebaseAuthStore.login(email, password)
|
||||
} else {
|
||||
await firebaseAuthStore.register(email, password)
|
||||
}
|
||||
onSuccess()
|
||||
}
|
||||
onSuccess()
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import {
|
||||
type Auth,
|
||||
GithubAuthProvider,
|
||||
GoogleAuthProvider,
|
||||
type User,
|
||||
type UserCredential,
|
||||
createUserWithEmailAndPassword,
|
||||
onAuthStateChanged,
|
||||
signInWithEmailAndPassword,
|
||||
signInWithPopup,
|
||||
signOut
|
||||
} from 'firebase/auth'
|
||||
import { defineStore } from 'pinia'
|
||||
@@ -18,6 +21,10 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
const currentUser = ref<User | null>(null)
|
||||
const isInitialized = ref(false)
|
||||
|
||||
// Providers
|
||||
const googleProvider = new GoogleAuthProvider()
|
||||
const githubProvider = new GithubAuthProvider()
|
||||
|
||||
// Getters
|
||||
const isAuthenticated = computed(() => !!currentUser.value)
|
||||
const userEmail = computed(() => currentUser.value?.email)
|
||||
@@ -68,6 +75,16 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
createUserWithEmailAndPassword(authInstance, email, password)
|
||||
)
|
||||
|
||||
const loginWithGoogle = async (): Promise<UserCredential> =>
|
||||
executeAuthAction((authInstance) =>
|
||||
signInWithPopup(authInstance, googleProvider)
|
||||
)
|
||||
|
||||
const loginWithGithub = async (): Promise<UserCredential> =>
|
||||
executeAuthAction((authInstance) =>
|
||||
signInWithPopup(authInstance, githubProvider)
|
||||
)
|
||||
|
||||
const logout = async (): Promise<void> =>
|
||||
executeAuthAction((authInstance) => signOut(authInstance))
|
||||
|
||||
@@ -94,6 +111,8 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
login,
|
||||
register,
|
||||
logout,
|
||||
getIdToken
|
||||
getIdToken,
|
||||
loginWithGoogle,
|
||||
loginWithGithub
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="comfyui-body grid h-screen w-screen overflow-hidden">
|
||||
<div class="comfyui-body grid h-dvh w-screen overflow-hidden">
|
||||
<div id="comfyui-body-top" class="comfyui-body-top">
|
||||
<TopMenubar v-if="useNewMenu === 'Top'" />
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<main class="w-full min-h-screen overflow-hidden relative">
|
||||
<main class="w-full min-h-dvh overflow-hidden relative">
|
||||
<router-view />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,10 @@ vi.mock('firebase/auth', () => ({
|
||||
signInWithEmailAndPassword: vi.fn(),
|
||||
createUserWithEmailAndPassword: vi.fn(),
|
||||
signOut: vi.fn(),
|
||||
onAuthStateChanged: vi.fn()
|
||||
onAuthStateChanged: vi.fn(),
|
||||
signInWithPopup: vi.fn(),
|
||||
GoogleAuthProvider: vi.fn(),
|
||||
GithubAuthProvider: vi.fn()
|
||||
}))
|
||||
|
||||
describe('useFirebaseAuthStore', () => {
|
||||
@@ -272,4 +275,90 @@ describe('useFirebaseAuthStore', () => {
|
||||
expect(tokenAfterLogout).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('social authentication', () => {
|
||||
describe('loginWithGoogle', () => {
|
||||
it('should sign in with Google', async () => {
|
||||
const mockUserCredential = { user: mockUser }
|
||||
vi.mocked(firebaseAuth.signInWithPopup).mockResolvedValue(
|
||||
mockUserCredential as any
|
||||
)
|
||||
|
||||
const result = await store.loginWithGoogle()
|
||||
|
||||
expect(firebaseAuth.signInWithPopup).toHaveBeenCalledWith(
|
||||
mockAuth,
|
||||
expect.any(firebaseAuth.GoogleAuthProvider)
|
||||
)
|
||||
expect(result).toEqual(mockUserCredential)
|
||||
expect(store.loading).toBe(false)
|
||||
expect(store.error).toBe(null)
|
||||
})
|
||||
|
||||
it('should handle Google sign in errors', async () => {
|
||||
const mockError = new Error('Google authentication failed')
|
||||
vi.mocked(firebaseAuth.signInWithPopup).mockRejectedValue(mockError)
|
||||
|
||||
await expect(store.loginWithGoogle()).rejects.toThrow(
|
||||
'Google authentication failed'
|
||||
)
|
||||
|
||||
expect(firebaseAuth.signInWithPopup).toHaveBeenCalledWith(
|
||||
mockAuth,
|
||||
expect.any(firebaseAuth.GoogleAuthProvider)
|
||||
)
|
||||
expect(store.loading).toBe(false)
|
||||
expect(store.error).toBe('Google authentication failed')
|
||||
})
|
||||
})
|
||||
|
||||
describe('loginWithGithub', () => {
|
||||
it('should sign in with Github', async () => {
|
||||
const mockUserCredential = { user: mockUser }
|
||||
vi.mocked(firebaseAuth.signInWithPopup).mockResolvedValue(
|
||||
mockUserCredential as any
|
||||
)
|
||||
|
||||
const result = await store.loginWithGithub()
|
||||
|
||||
expect(firebaseAuth.signInWithPopup).toHaveBeenCalledWith(
|
||||
mockAuth,
|
||||
expect.any(firebaseAuth.GithubAuthProvider)
|
||||
)
|
||||
expect(result).toEqual(mockUserCredential)
|
||||
expect(store.loading).toBe(false)
|
||||
expect(store.error).toBe(null)
|
||||
})
|
||||
|
||||
it('should handle Github sign in errors', async () => {
|
||||
const mockError = new Error('Github authentication failed')
|
||||
vi.mocked(firebaseAuth.signInWithPopup).mockRejectedValue(mockError)
|
||||
|
||||
await expect(store.loginWithGithub()).rejects.toThrow(
|
||||
'Github authentication failed'
|
||||
)
|
||||
|
||||
expect(firebaseAuth.signInWithPopup).toHaveBeenCalledWith(
|
||||
mockAuth,
|
||||
expect.any(firebaseAuth.GithubAuthProvider)
|
||||
)
|
||||
expect(store.loading).toBe(false)
|
||||
expect(store.error).toBe('Github authentication failed')
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle concurrent social login attempts correctly', async () => {
|
||||
const mockUserCredential = { user: mockUser }
|
||||
vi.mocked(firebaseAuth.signInWithPopup).mockResolvedValue(
|
||||
mockUserCredential as any
|
||||
)
|
||||
|
||||
const googleLoginPromise = store.loginWithGoogle()
|
||||
const githubLoginPromise = store.loginWithGithub()
|
||||
|
||||
await Promise.all([googleLoginPromise, githubLoginPromise])
|
||||
|
||||
expect(store.loading).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user