diff --git a/src/components/dialog/content/SettingDialogContent.vue b/src/components/dialog/content/SettingDialogContent.vue index b6e0e504c..fc22316cd 100644 --- a/src/components/dialog/content/SettingDialogContent.vue +++ b/src/components/dialog/content/SettingDialogContent.vue @@ -67,9 +67,9 @@ import Tabs from 'primevue/tabs' import { computed, watch } from 'vue' import SearchBox from '@/components/common/SearchBox.vue' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useSettingSearch } from '@/composables/setting/useSettingSearch' import { useSettingUI } from '@/composables/setting/useSettingUI' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' import { SettingTreeNode } from '@/stores/settingStore' import { ISettingGroup, SettingParams } from '@/types/settingTypes' import { flattenTree } from '@/utils/treeUtil' @@ -107,7 +107,7 @@ const { getSearchResults } = useSettingSearch() -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() // Sort groups for a category const sortedGroups = (category: SettingTreeNode): ISettingGroup[] => { @@ -140,7 +140,7 @@ watch(activeCategory, (_, oldValue) => { activeCategory.value = oldValue } if (activeCategory.value?.key === 'credits') { - void authService.fetchBalance() + void authActions.fetchBalance() } }) diff --git a/src/components/dialog/content/SignInContent.vue b/src/components/dialog/content/SignInContent.vue index 7de244c60..05303ce69 100644 --- a/src/components/dialog/content/SignInContent.vue +++ b/src/components/dialog/content/SignInContent.vue @@ -101,6 +101,15 @@ {{ t('auth.apiKey.generateKey') }} + + {{ t('toastMessages.useApiKeyTip') }} + @@ -134,12 +143,12 @@ import Button from 'primevue/button' import Divider from 'primevue/divider' import Message from 'primevue/message' -import { onMounted, ref } from 'vue' +import { onMounted, onUnmounted, ref } from 'vue' import { useI18n } from 'vue-i18n' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { COMFY_PLATFORM_BASE_URL } from '@/config/comfyApi' import { SignInData, SignUpData } from '@/schemas/signInSchema' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' import { isInChina } from '@/utils/networkUtil' import ApiKeyForm from './signin/ApiKeyForm.vue' @@ -151,7 +160,7 @@ const { onSuccess } = defineProps<{ }>() const { t } = useI18n() -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const isSecureContext = window.isSecureContext const isSignIn = ref(true) const showApiKeyForm = ref(false) @@ -162,25 +171,25 @@ const toggleState = () => { } const signInWithGoogle = async () => { - if (await authService.signInWithGoogle()) { + if (await authActions.signInWithGoogle()) { onSuccess() } } const signInWithGithub = async () => { - if (await authService.signInWithGithub()) { + if (await authActions.signInWithGithub()) { onSuccess() } } const signInWithEmail = async (values: SignInData) => { - if (await authService.signInWithEmail(values.email, values.password)) { + if (await authActions.signInWithEmail(values.email, values.password)) { onSuccess() } } const signUpWithEmail = async (values: SignUpData) => { - if (await authService.signUpWithEmail(values.email, values.password)) { + if (await authActions.signUpWithEmail(values.email, values.password)) { onSuccess() } } @@ -189,4 +198,8 @@ const userIsInChina = ref(false) onMounted(async () => { userIsInChina.value = await isInChina() }) + +onUnmounted(() => { + authActions.accessError.value = false +}) diff --git a/src/components/dialog/content/TopUpCreditsDialogContent.vue b/src/components/dialog/content/TopUpCreditsDialogContent.vue index 11fd1505b..d15b75289 100644 --- a/src/components/dialog/content/TopUpCreditsDialogContent.vue +++ b/src/components/dialog/content/TopUpCreditsDialogContent.vue @@ -51,7 +51,7 @@ import Button from 'primevue/button' import UserCredit from '@/components/common/UserCredit.vue' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import CreditTopUpOption from './credit/CreditTopUpOption.vue' @@ -65,9 +65,9 @@ const { preselectedAmountOption?: number }>() -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const handleSeeDetails = async () => { - await authService.accessBillingPortal() + await authActions.accessBillingPortal() } diff --git a/src/components/dialog/content/UpdatePasswordContent.vue b/src/components/dialog/content/UpdatePasswordContent.vue index 470a56725..55611c00c 100644 --- a/src/components/dialog/content/UpdatePasswordContent.vue +++ b/src/components/dialog/content/UpdatePasswordContent.vue @@ -23,10 +23,10 @@ import Button from 'primevue/button' import { ref } from 'vue' import PasswordFields from '@/components/dialog/content/signin/PasswordFields.vue' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { updatePasswordSchema } from '@/schemas/signInSchema' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const loading = ref(false) const { onSuccess } = defineProps<{ @@ -37,7 +37,7 @@ const onSubmit = async (event: FormSubmitEvent) => { if (event.valid) { loading.value = true try { - await authService.updatePassword(event.values.password) + await authActions.updatePassword(event.values.password) onSuccess() } finally { loading.value = false diff --git a/src/components/dialog/content/credit/CreditTopUpOption.vue b/src/components/dialog/content/credit/CreditTopUpOption.vue index 1f2719ca1..95ea29fc2 100644 --- a/src/components/dialog/content/credit/CreditTopUpOption.vue +++ b/src/components/dialog/content/credit/CreditTopUpOption.vue @@ -41,9 +41,9 @@ import ProgressSpinner from 'primevue/progressspinner' import Tag from 'primevue/tag' import { onBeforeUnmount, ref } from 'vue' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const { amount, @@ -61,7 +61,7 @@ const loading = ref(false) const handleBuyNow = async () => { loading.value = true - await authService.purchaseCredits(editable ? customAmount.value : amount) + await authActions.purchaseCredits(editable ? customAmount.value : amount) loading.value = false didClickBuyNow.value = true } @@ -69,7 +69,7 @@ const handleBuyNow = async () => { onBeforeUnmount(() => { if (didClickBuyNow.value) { // If clicked buy now, then returned back to the dialog and closed, fetch the balance - void authService.fetchBalance() + void authActions.fetchBalance() } }) diff --git a/src/components/dialog/content/setting/CreditsPanel.vue b/src/components/dialog/content/setting/CreditsPanel.vue index 31aa4c851..ed83ef9c0 100644 --- a/src/components/dialog/content/setting/CreditsPanel.vue +++ b/src/components/dialog/content/setting/CreditsPanel.vue @@ -36,7 +36,7 @@ text size="small" severity="secondary" - @click="() => authService.fetchBalance()" + @click="() => authActions.fetchBalance()" /> @@ -112,8 +112,8 @@ import { computed, ref } from 'vue' import { useI18n } from 'vue-i18n' import UserCredit from '@/components/common/UserCredit.vue' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useDialogService } from '@/services/dialogService' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' import { formatMetronomeCurrency } from '@/utils/formatUtil' @@ -127,7 +127,7 @@ interface CreditHistoryItemData { const { t } = useI18n() const dialogService = useDialogService() const authStore = useFirebaseAuthStore() -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const loading = computed(() => authStore.loading) const balanceLoading = computed(() => authStore.isFetchingBalance) @@ -142,7 +142,7 @@ const handlePurchaseCreditsClick = () => { } const handleCreditsHistoryClick = async () => { - await authService.accessBillingPortal() + await authActions.accessBillingPortal() } const handleMessageSupport = () => { diff --git a/src/components/dialog/content/signin/SignInForm.vue b/src/components/dialog/content/signin/SignInForm.vue index 4881970fd..c9cccff9d 100644 --- a/src/components/dialog/content/signin/SignInForm.vue +++ b/src/components/dialog/content/signin/SignInForm.vue @@ -80,12 +80,12 @@ import ProgressSpinner from 'primevue/progressspinner' import { computed } from 'vue' import { useI18n } from 'vue-i18n' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { type SignInData, signInSchema } from '@/schemas/signInSchema' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' const authStore = useFirebaseAuthStore() -const firebaseAuthService = useFirebaseAuthService() +const firebaseAuthActions = useFirebaseAuthActions() const loading = computed(() => authStore.loading) const { t } = useI18n() @@ -102,6 +102,6 @@ const onSubmit = (event: FormSubmitEvent) => { const handleForgotPassword = async (email: string) => { if (!email) return - await firebaseAuthService.sendPasswordReset(email) + await firebaseAuthActions.sendPasswordReset(email) } diff --git a/src/components/topbar/CurrentUserPopover.vue b/src/components/topbar/CurrentUserPopover.vue index 2eafff868..8f8751526 100644 --- a/src/components/topbar/CurrentUserPopover.vue +++ b/src/components/topbar/CurrentUserPopover.vue @@ -69,11 +69,11 @@ import { onMounted } from 'vue' import UserAvatar from '@/components/common/UserAvatar.vue' import UserCredit from '@/components/common/UserCredit.vue' import { useCurrentUser } from '@/composables/auth/useCurrentUser' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useDialogService } from '@/services/dialogService' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' const { userDisplayName, userEmail, userPhotoUrl } = useCurrentUser() -const authService = useFirebaseAuthService() +const authActions = useFirebaseAuthActions() const dialogService = useDialogService() const handleOpenUserSettings = () => { @@ -89,6 +89,6 @@ const handleOpenApiPricing = () => { } onMounted(() => { - void authService.fetchBalance() + void authActions.fetchBalance() }) diff --git a/src/services/firebaseAuthService.ts b/src/composables/auth/useFirebaseAuthActions.ts similarity index 95% rename from src/services/firebaseAuthService.ts rename to src/composables/auth/useFirebaseAuthActions.ts index d3244f910..466d0ef82 100644 --- a/src/services/firebaseAuthService.ts +++ b/src/composables/auth/useFirebaseAuthActions.ts @@ -1,4 +1,5 @@ import { FirebaseError } from 'firebase/app' +import { ref } from 'vue' import { useErrorHandling } from '@/composables/useErrorHandling' import { t } from '@/i18n' @@ -11,11 +12,13 @@ import { usdToMicros } from '@/utils/formatUtil' * All actions are wrapped with error handling. * @returns {Object} - Object containing all Firebase Auth actions */ -export const useFirebaseAuthService = () => { +export const useFirebaseAuthActions = () => { const authStore = useFirebaseAuthStore() const toastStore = useToastStore() const { wrapWithErrorHandlingAsync, toastErrorHandler } = useErrorHandling() + const accessError = ref(false) + const reportError = (error: unknown) => { // Ref: https://firebase.google.com/docs/auth/admin/errors if ( @@ -26,6 +29,7 @@ export const useFirebaseAuthService = () => { 'auth/unauthorized-continue-uri' ].includes(error.code) ) { + accessError.value = true toastStore.add({ severity: 'error', summary: t('g.error'), @@ -141,6 +145,7 @@ export const useFirebaseAuthService = () => { signInWithGithub, signInWithEmail, signUpWithEmail, - updatePassword + updatePassword, + accessError } } diff --git a/src/composables/useCoreCommands.ts b/src/composables/useCoreCommands.ts index 529babbcb..46070dfe9 100644 --- a/src/composables/useCoreCommands.ts +++ b/src/composables/useCoreCommands.ts @@ -5,6 +5,7 @@ import { LiteGraph } from '@comfyorg/litegraph' +import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { DEFAULT_DARK_COLOR_PALETTE, DEFAULT_LIGHT_COLOR_PALETTE @@ -13,7 +14,6 @@ import { t } from '@/i18n' import { api } from '@/scripts/api' import { app } from '@/scripts/app' import { useDialogService } from '@/services/dialogService' -import { useFirebaseAuthService } from '@/services/firebaseAuthService' import { useLitegraphService } from '@/services/litegraphService' import { useWorkflowService } from '@/services/workflowService' import type { ComfyCommand } from '@/stores/commandStore' @@ -32,7 +32,7 @@ export function useCoreCommands(): ComfyCommand[] { const workflowStore = useWorkflowStore() const dialogService = useDialogService() const colorPaletteStore = useColorPaletteStore() - const firebaseAuthService = useFirebaseAuthService() + const firebaseAuthActions = useFirebaseAuthActions() const toastStore = useToastStore() const getTracker = () => workflowStore.activeWorkflow?.changeTracker @@ -671,7 +671,7 @@ export function useCoreCommands(): ComfyCommand[] { label: 'Sign Out', versionAdded: '1.18.1', function: async () => { - await firebaseAuthService.logout() + await firebaseAuthActions.logout() } } ] diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 79dbbb9d2..3d3232760 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -1259,7 +1259,8 @@ "failedToInitiateCreditPurchase": "Failed to initiate credit purchase: {error}", "failedToAccessBillingPortal": "Failed to access billing portal: {error}", "failedToPurchaseCredits": "Failed to purchase credits: {error}", - "unauthorizedDomain": "Your domain {domain} is not authorized to use this service. Please contact {email} to add your domain to the whitelist." + "unauthorizedDomain": "Your domain {domain} is not authorized to use this service. Please contact {email} to add your domain to the whitelist.", + "useApiKeyTip": "Tip: Can't access normal login? Use the Comfy API Key option." }, "auth": { "apiKey": { diff --git a/src/locales/es/main.json b/src/locales/es/main.json index af040b257..84c0f3993 100644 --- a/src/locales/es/main.json +++ b/src/locales/es/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "No se puede obtener la ruta del archivo del modelo", "unauthorizedDomain": "Tu dominio {domain} no está autorizado para usar este servicio. Por favor, contacta a {email} para agregar tu dominio a la lista blanca.", "updateRequested": "Actualización solicitada", + "useApiKeyTip": "Consejo: ¿No puedes acceder al inicio de sesión normal? Usa la opción de clave API de Comfy.", "userNotAuthenticated": "Usuario no autenticado" }, "userSelect": { diff --git a/src/locales/fr/main.json b/src/locales/fr/main.json index 8da05ca22..68d7c0c1e 100644 --- a/src/locales/fr/main.json +++ b/src/locales/fr/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "Impossible d'obtenir le chemin du fichier modèle", "unauthorizedDomain": "Votre domaine {domain} n'est pas autorisé à utiliser ce service. Veuillez contacter {email} pour ajouter votre domaine à la liste blanche.", "updateRequested": "Mise à jour demandée", + "useApiKeyTip": "Astuce : Vous ne pouvez pas accéder à la connexion normale ? Utilisez l’option Clé API Comfy.", "userNotAuthenticated": "Utilisateur non authentifié" }, "userSelect": { diff --git a/src/locales/ja/main.json b/src/locales/ja/main.json index 641bff5c1..dd37f4003 100644 --- a/src/locales/ja/main.json +++ b/src/locales/ja/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "モデルファイルのパスを取得できません", "unauthorizedDomain": "あなたのドメイン {domain} はこのサービスを利用する権限がありません。ご利用のドメインをホワイトリストに追加するには、{email} までご連絡ください。", "updateRequested": "更新が要求されました", + "useApiKeyTip": "ヒント:通常のログインにアクセスできませんか?Comfy APIキーオプションを使用してください。", "userNotAuthenticated": "ユーザーが認証されていません" }, "userSelect": { diff --git a/src/locales/ko/main.json b/src/locales/ko/main.json index 37cad6083..3fccd2b39 100644 --- a/src/locales/ko/main.json +++ b/src/locales/ko/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "모델 파일 경로를 가져올 수 없습니다", "unauthorizedDomain": "귀하의 도메인 {domain}은(는) 이 서비스를 사용할 수 있는 권한이 없습니다. 도메인을 허용 목록에 추가하려면 {email}로 문의해 주세요.", "updateRequested": "업데이트 요청됨", + "useApiKeyTip": "팁: 일반 로그인을 사용할 수 없나요? Comfy API Key 옵션을 사용하세요.", "userNotAuthenticated": "사용자가 인증되지 않았습니다" }, "userSelect": { diff --git a/src/locales/ru/main.json b/src/locales/ru/main.json index 03d930b78..77817c905 100644 --- a/src/locales/ru/main.json +++ b/src/locales/ru/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "Не удалось получить путь к файлу модели", "unauthorizedDomain": "Ваш домен {domain} не авторизован для использования этого сервиса. Пожалуйста, свяжитесь с {email}, чтобы добавить ваш домен в белый список.", "updateRequested": "Запрошено обновление", + "useApiKeyTip": "Совет: Нет доступа к обычному входу? Используйте опцию Comfy API Key.", "userNotAuthenticated": "Пользователь не аутентифицирован" }, "userSelect": { diff --git a/src/locales/zh/main.json b/src/locales/zh/main.json index a9e8cd7a2..663477217 100644 --- a/src/locales/zh/main.json +++ b/src/locales/zh/main.json @@ -1362,6 +1362,7 @@ "unableToGetModelFilePath": "无法获取模型文件路径", "unauthorizedDomain": "您的域名 {domain} 未被授权使用此服务。请联系 {email} 将您的域名添加到白名单。", "updateRequested": "已请求更新", + "useApiKeyTip": "提示:无法正常登录?请使用 Comfy API Key 选项。", "userNotAuthenticated": "用户未认证" }, "userSelect": {