feat: add subscription management for tauri platforms (#1499)
This commit is contained in:
@@ -43,10 +43,11 @@
|
||||
"@ducanh2912/next-pwa": "^10.2.9",
|
||||
"@fabianlars/tauri-plugin-oauth": "2",
|
||||
"@opennextjs/cloudflare": "^1.3.1",
|
||||
"@stripe/react-stripe-js": "^3.7.0",
|
||||
"@stripe/stripe-js": "^7.4.0",
|
||||
"@supabase/auth-ui-react": "^0.4.7",
|
||||
"@supabase/auth-ui-shared": "^0.1.8",
|
||||
"@supabase/supabase-js": "^2.49.10",
|
||||
"@supabase/supabase-js": "^2.50.2",
|
||||
"@tauri-apps/api": "2.6.0",
|
||||
"@tauri-apps/plugin-cli": "^2.3.0",
|
||||
"@tauri-apps/plugin-deep-link": "^2.3.0",
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "فشل تنزيل الكتاب: {{title}}",
|
||||
"Upload Book": "تحميل الكتاب",
|
||||
"Auto Upload Books to Cloud": "تحميل الكتب تلقائيًا إلى السحابة",
|
||||
"{{percentage}}% of Cloud Storage Used.": "تم استخدام {{percentage}}% من مساحة التخزين السحابية.",
|
||||
"Storage": "التخزين",
|
||||
"Book deleted: {{title}}": "تم حذف الكتاب: {{title}}",
|
||||
"Failed to delete book: {{title}}": "فشل حذف الكتاب: {{title}}",
|
||||
"Check Updates on Start": "التحقق من التحديثات عند البدء",
|
||||
@@ -406,7 +404,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "ساعات تحويل النص إلى كلام غير محدودة",
|
||||
"DeepL Free Access (10K characters/day)": "وصول مجاني إلى DeepL (10 آلاف حرف يوميًا)",
|
||||
"AI Translations (per day)": "ترجمات بالذكاء الاصطناعي (يوميًا)",
|
||||
"Cloud Storage": "تخزين سحابي",
|
||||
"Plus Plan": "خطة Plus",
|
||||
"Includes All Free Plan Benefits": "تتضمن جميع مزايا الخطة المجانية",
|
||||
"Basic AI Translations": "ترجمات أساسية بالذكاء الاصطناعي",
|
||||
@@ -415,5 +412,8 @@
|
||||
"Pro Plan": "خطة Pro",
|
||||
"Includes All Plus Plan Benefits": "تتضمن جميع مزايا خطة Plus",
|
||||
"More AI Translations": "المزيد من الترجمات بالذكاء الاصطناعي",
|
||||
"DeepL Pro Access (200K characters/day)": "وصول احترافي إلى DeepL (200 ألف حرف يوميًا)"
|
||||
"DeepL Pro Access (200K characters/day)": "وصول احترافي إلى DeepL (200 ألف حرف يوميًا)",
|
||||
"Complete Your Subscription": "أكمل اشتراكك",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "تم استخدام {{percentage}}% من مساحة المزامنة السحابية.",
|
||||
"Cloud Sync Storage": "مساحة المزامنة السحابية"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Fehler beim Herunterladen des Buches: {{title}}",
|
||||
"Upload Book": "Buch hochladen",
|
||||
"Auto Upload Books to Cloud": "Bücher automatisch hochladen",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% des Cloud-Speichers verwendet.",
|
||||
"Storage": "Speicher",
|
||||
"Book deleted: {{title}}": "Buch gelöscht: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Fehler beim Löschen des Buches: {{title}}",
|
||||
"Check Updates on Start": "Aktualisierungen beim Start prüfen",
|
||||
@@ -390,7 +388,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Unbegrenzte Text-to-Speech-Stunden",
|
||||
"DeepL Free Access (10K characters/day)": "Kostenfreier DeepL-Zugang (10.000 Zeichen/Tag)",
|
||||
"AI Translations (per day)": "KI-Übersetzungen (pro Tag)",
|
||||
"Cloud Storage": "Cloud-Speicher",
|
||||
"Plus Plan": "Plus-Tarif",
|
||||
"Includes All Free Plan Benefits": "Enthält alle Vorteile des Gratis-Tarifs",
|
||||
"Basic AI Translations": "Basis-KI-Übersetzungen",
|
||||
@@ -399,5 +396,8 @@
|
||||
"Pro Plan": "Pro-Tarif",
|
||||
"Includes All Plus Plan Benefits": "Enthält alle Vorteile des Plus-Tarifs",
|
||||
"More AI Translations": "Mehr KI-Übersetzungen",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro-Zugang (200.000 Zeichen/Tag)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro-Zugang (200.000 Zeichen/Tag)",
|
||||
"Complete Your Subscription": "Abschließen Sie Ihr Abonnement",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% des Cloud-Synchronisierungsspeichers verwendet.",
|
||||
"Cloud Sync Storage": "Cloud-Speicher"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Αποτυχία λήψης βιβλίου: {{title}}",
|
||||
"Upload Book": "Ανέβασμα βιβλίου",
|
||||
"Auto Upload Books to Cloud": "Αυτόματη αποθήκευση στο cloud",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% της αποθήκευσης στο cloud χρησιμοποιήθηκε.",
|
||||
"Storage": "Αποθήκευση",
|
||||
"Book deleted: {{title}}": "Το βιβλίο με τίτλο {{title}} διαγράφηκε",
|
||||
"Failed to delete book: {{title}}": "Αποτυχία διαγραφής βιβλίου: {{title}}",
|
||||
"Check Updates on Start": "Αυτόματος έλεγχος ενημερώσεων",
|
||||
@@ -390,7 +388,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Απεριόριστες ώρες μετατροπής κειμένου σε ομιλία",
|
||||
"DeepL Free Access (10K characters/day)": "Δωρεάν πρόσβαση στο DeepL (10.000 χαρακτήρες/ημέρα)",
|
||||
"AI Translations (per day)": "Μεταφράσεις AI (ανά ημέρα)",
|
||||
"Cloud Storage": "Αποθήκευση στο cloud",
|
||||
"Plus Plan": "Πρόγραμμα Plus",
|
||||
"Includes All Free Plan Benefits": "Περιλαμβάνει όλα τα οφέλη του δωρεάν προγράμματος",
|
||||
"Basic AI Translations": "Βασικές μεταφράσεις AI",
|
||||
@@ -399,5 +396,8 @@
|
||||
"Pro Plan": "Πρόγραμμα Pro",
|
||||
"Includes All Plus Plan Benefits": "Περιλαμβάνει όλα τα οφέλη του Plus προγράμματος",
|
||||
"More AI Translations": "Περισσότερες μεταφράσεις AI",
|
||||
"DeepL Pro Access (200K characters/day)": "Pro πρόσβαση στο DeepL (200.000 χαρακτήρες/ημέρα)"
|
||||
"DeepL Pro Access (200K characters/day)": "Pro πρόσβαση στο DeepL (200.000 χαρακτήρες/ημέρα)",
|
||||
"Complete Your Subscription": "Ολοκληρώστε τη συνδρομή σας",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% του χώρου συγχρονισμού στο cloud χρησιμοποιήθηκε.",
|
||||
"Cloud Sync Storage": "Χώρος συγχρονισμού cloud"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Error al descargar libro: {{title}}",
|
||||
"Upload Book": "Subir libro",
|
||||
"Auto Upload Books to Cloud": "Subir libros automáticamente a la nube",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% del almacenamiento en la nube utilizado.",
|
||||
"Storage": "Almacenamiento",
|
||||
"Book deleted: {{title}}": "Libro eliminado: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Error al eliminar libro: {{title}}",
|
||||
"Check Updates on Start": "Comprobar actualizaciones al iniciar",
|
||||
@@ -393,7 +391,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Horas ilimitadas de texto a voz",
|
||||
"DeepL Free Access (10K characters/day)": "Acceso gratuito a DeepL (10.000 caracteres/día)",
|
||||
"AI Translations (per day)": "Traducciones con IA (por día)",
|
||||
"Cloud Storage": "Almacenamiento en la nube",
|
||||
"Plus Plan": "Plan Plus",
|
||||
"Includes All Free Plan Benefits": "Incluye todos los beneficios del plan gratuito",
|
||||
"Basic AI Translations": "Traducciones básicas con IA",
|
||||
@@ -403,5 +400,8 @@
|
||||
"Includes All Plus Plan Benefits": "Incluye todos los beneficios del plan Plus",
|
||||
"More AI Translations": "Más traducciones con IA",
|
||||
"DeepL Pro Access (200K characters/day)": "Acceso Pro a DeepL (200.000 caracteres/día)",
|
||||
"Your payment is being processed. This usually takes a few moments.": "Tu pago se está procesando. Normalmente tarda unos momentos."
|
||||
"Your payment is being processed. This usually takes a few moments.": "Tu pago se está procesando. Normalmente tarda unos momentos.",
|
||||
"Complete Your Subscription": "Completa tu suscripción",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% del espacio de sincronización en la nube utilizado.",
|
||||
"Cloud Sync Storage": "Almacenamiento en la nube"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Échec du téléchargement du livre : {{title}}",
|
||||
"Upload Book": "Télécharger un livre",
|
||||
"Auto Upload Books to Cloud": "Télécharger automatiquement les livres dans le cloud",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% de l'espace de stockage dans le cloud utilisé.",
|
||||
"Storage": "Stockage",
|
||||
"Book deleted: {{title}}": "Livre supprimé : {{title}}",
|
||||
"Failed to delete book: {{title}}": "Échec de la suppression du livre : {{title}}",
|
||||
"Check Updates on Start": "Vérifier les mises à jour au démarrage",
|
||||
@@ -394,7 +392,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Heures illimitées de synthèse vocale",
|
||||
"DeepL Free Access (10K characters/day)": "Accès gratuit à DeepL (10 000 caractères/jour)",
|
||||
"AI Translations (per day)": "Traductions IA (par jour)",
|
||||
"Cloud Storage": "Stockage cloud",
|
||||
"Plus Plan": "Abonnement Plus",
|
||||
"Includes All Free Plan Benefits": "Inclut tous les avantages de l’abonnement gratuit",
|
||||
"Basic AI Translations": "Traductions IA de base",
|
||||
@@ -403,5 +400,8 @@
|
||||
"Pro Plan": "Abonnement Pro",
|
||||
"Includes All Plus Plan Benefits": "Inclut tous les avantages de l’abonnement Plus",
|
||||
"More AI Translations": "Plus de traductions IA",
|
||||
"DeepL Pro Access (200K characters/day)": "Accès Pro à DeepL (200 000 caractères/jour)"
|
||||
"DeepL Pro Access (200K characters/day)": "Accès Pro à DeepL (200 000 caractères/jour)",
|
||||
"Complete Your Subscription": "Complétez votre abonnement",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% de l’espace de synchronisation cloud utilisé.",
|
||||
"Cloud Sync Storage": "Stockage de synchronisation cloud"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "पुस्तक डाउनलोड करने में विफल: {{title}}",
|
||||
"Upload Book": "पुस्तक अपलोड करें",
|
||||
"Auto Upload Books to Cloud": "पुस्तकें बादल में स्वचालित रूप से अपलोड करें",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% क्लाउड स्टोरेज का उपयोग किया गया है।",
|
||||
"Storage": "स्टोरेज",
|
||||
"Book deleted: {{title}}": "पुस्तक हटाई गई: {{title}}",
|
||||
"Failed to delete book: {{title}}": "पुस्तक हटाने में विफल: {{title}}",
|
||||
"Check Updates on Start": "शुरू में अपडेट जांचें",
|
||||
@@ -390,7 +388,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "अनलिमिटेड पाठ-पाठ ध्वनि घंटे",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL मुफ्त एक्सेस (10,000 अक्षर/दिन)",
|
||||
"AI Translations (per day)": "AI अनुवाद (प्रतिदिन)",
|
||||
"Cloud Storage": "क्लाउड स्टोरेज",
|
||||
"Plus Plan": "Plus योजना",
|
||||
"Includes All Free Plan Benefits": "सभी मुफ्त योजना के लाभ शामिल हैं",
|
||||
"Basic AI Translations": "मूल AI अनुवाद",
|
||||
@@ -399,5 +396,8 @@
|
||||
"Pro Plan": "Pro योजना",
|
||||
"Includes All Plus Plan Benefits": "सभी Plus योजना के लाभ शामिल हैं",
|
||||
"More AI Translations": "और अधिक AI अनुवाद",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL प्रो एक्सेस (200,000 अक्षर/दिन)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL प्रो एक्सेस (200,000 अक्षर/दिन)",
|
||||
"Complete Your Subscription": "अपनी सदस्यता पूरी करें",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% क्लाउड सिंक स्पेस का उपयोग किया गया है।",
|
||||
"Cloud Sync Storage": "क्लाउड सिंक स्टोरेज"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Gagal mengunduh buku: {{title}}",
|
||||
"Upload Book": "Unggah Buku",
|
||||
"Auto Upload Books to Cloud": "Unggah Buku Otomatis ke Cloud",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% dari Penyimpanan Cloud Digunakan.",
|
||||
"Storage": "Penyimpanan",
|
||||
"Book deleted: {{title}}": "Buku dihapus: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Gagal menghapus buku: {{title}}",
|
||||
"Check Updates on Start": "Periksa Pembaruan saat Memulai",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Jam Text-to-Speech Tanpa Batas",
|
||||
"DeepL Free Access (10K characters/day)": "Akses DeepL Gratis (10.000 karakter/hari)",
|
||||
"AI Translations (per day)": "Terjemahan AI (per hari)",
|
||||
"Cloud Storage": "Penyimpanan Cloud",
|
||||
"Plus Plan": "Paket Plus",
|
||||
"Includes All Free Plan Benefits": "Termasuk Semua Manfaat Paket Gratis",
|
||||
"Basic AI Translations": "Terjemahan AI Dasar",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Paket Pro",
|
||||
"Includes All Plus Plan Benefits": "Termasuk Semua Manfaat Paket Plus",
|
||||
"More AI Translations": "Lebih Banyak Terjemahan AI",
|
||||
"DeepL Pro Access (200K characters/day)": "Akses DeepL Pro (200.000 karakter/hari)"
|
||||
"DeepL Pro Access (200K characters/day)": "Akses DeepL Pro (200.000 karakter/hari)",
|
||||
"Complete Your Subscription": "Selesaikan Langganan Anda",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% ruang sinkronisasi cloud terpakai",
|
||||
"Cloud Sync Storage": "Ruang cloud"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Download libro non riuscito: {{title}}",
|
||||
"Upload Book": "Carica libro",
|
||||
"Auto Upload Books to Cloud": "Carica libri automaticamente su cloud",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% dello spazio di archiviazione cloud utilizzato.",
|
||||
"Storage": "Archiviazione",
|
||||
"Book deleted: {{title}}": "Libro eliminato: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Eliminazione libro non riuscita: {{title}}",
|
||||
"Check Updates on Start": "Controlla aggiornamenti all'avvio",
|
||||
@@ -394,7 +392,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Ore Illimitate di Sintesi Vocale",
|
||||
"DeepL Free Access (10K characters/day)": "Accesso Gratuito a DeepL (10.000 caratteri/giorno)",
|
||||
"AI Translations (per day)": "Traduzioni AI (al giorno)",
|
||||
"Cloud Storage": "Archiviazione Cloud",
|
||||
"Plus Plan": "Piano Plus",
|
||||
"Includes All Free Plan Benefits": "Include Tutti i Vantaggi del Piano Gratuito",
|
||||
"Basic AI Translations": "Traduzioni AI di Base",
|
||||
@@ -403,5 +400,8 @@
|
||||
"Pro Plan": "Piano Pro",
|
||||
"Includes All Plus Plan Benefits": "Include Tutti i Vantaggi del Piano Plus",
|
||||
"More AI Translations": "Più Traduzioni AI",
|
||||
"DeepL Pro Access (200K characters/day)": "Accesso DeepL Pro (200.000 caratteri/giorno)"
|
||||
"DeepL Pro Access (200K characters/day)": "Accesso DeepL Pro (200.000 caratteri/giorno)",
|
||||
"Complete Your Subscription": "Completa l'abbonamento",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% dello spazio cloud usato",
|
||||
"Cloud Sync Storage": "Spazio cloud"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "書籍のダウンロードに失敗しました:{{title}}",
|
||||
"Upload Book": "書籍をアップロード",
|
||||
"Auto Upload Books to Cloud": "書籍を自動的にクラウドにアップロード",
|
||||
"{{percentage}}% of Cloud Storage Used.": "クラウドストレージの{{percentage}}%が使用されています。",
|
||||
"Storage": "ストレージ",
|
||||
"Book deleted: {{title}}": "書籍が削除されました:{{title}}",
|
||||
"Failed to delete book: {{title}}": "書籍の削除に失敗しました:{{title}}",
|
||||
"Check Updates on Start": "開始時に更新を確認",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "無制限の音声読み上げ時間",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL無料アクセス(1日1万文字)",
|
||||
"AI Translations (per day)": "AI翻訳(1日あたり)",
|
||||
"Cloud Storage": "クラウドストレージ",
|
||||
"Plus Plan": "Plusプラン",
|
||||
"Includes All Free Plan Benefits": "無料プランの全特典を含む",
|
||||
"Basic AI Translations": "基本的なAI翻訳",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Proプラン",
|
||||
"Includes All Plus Plan Benefits": "Plusプランの全特典を含む",
|
||||
"More AI Translations": "さらに多くのAI翻訳",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Proアクセス(1日20万文字)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Proアクセス(1日20万文字)",
|
||||
"Complete Your Subscription": "サブスクリプションを完了する",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "クラウド同期スペースの使用量は{{percentage}}%です。",
|
||||
"Cloud Sync Storage": "クラウド同期容量"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "책 다운로드 실패: {{title}}",
|
||||
"Upload Book": "책 업로드",
|
||||
"Auto Upload Books to Cloud": "책 자동으로 클라우드에 업로드",
|
||||
"{{percentage}}% of Cloud Storage Used.": "클라우드 저장소 사용량 {{percentage}}%.",
|
||||
"Storage": "저장소",
|
||||
"Book deleted: {{title}}": "책 삭제됨: {{title}}",
|
||||
"Failed to delete book: {{title}}": "책 삭제 실패: {{title}}",
|
||||
"Check Updates on Start": "시작 시 업데이트 확인",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "무제한 음성 변환 시간",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL 무료 액세스 (일 1만자)",
|
||||
"AI Translations (per day)": "AI 번역 (일 기준)",
|
||||
"Cloud Storage": "클라우드 저장소",
|
||||
"Plus Plan": "Plus 요금제",
|
||||
"Includes All Free Plan Benefits": "무료 요금제의 모든 혜택 포함",
|
||||
"Basic AI Translations": "기본 AI 번역",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Pro 요금제",
|
||||
"Includes All Plus Plan Benefits": "Plus 요금제의 모든 혜택 포함",
|
||||
"More AI Translations": "더 많은 AI 번역",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro 액세스 (일 20만자)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro 액세스 (일 20만자)",
|
||||
"Complete Your Subscription": "구독 완료",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}%의 클라우드 동기화 공간 사용됨.",
|
||||
"Cloud Sync Storage": "클라우드 저장 공간"
|
||||
}
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
"Import Books": "Boeken importeren",
|
||||
"Select Multiple Books": "Meerdere boeken selecteren",
|
||||
"Select Books": "Boeken selecteren",
|
||||
"Storage": "Opslag",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% van cloudopslag gebruikt.",
|
||||
"Logged in as {{userDisplayName}}": "Ingelogd als {{userDisplayName}}",
|
||||
"Logged in": "Ingelogd",
|
||||
"Account": "Account",
|
||||
@@ -388,7 +386,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Onbeperkte tekst-naar-spraak-uren",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL gratis toegang (10.000 tekens/dag)",
|
||||
"AI Translations (per day)": "AI-vertalingen (per dag)",
|
||||
"Cloud Storage": "Cloudopslag",
|
||||
"Plus Plan": "Plus-abonnement",
|
||||
"Includes All Free Plan Benefits": "Bevat alle voordelen van het gratis abonnement",
|
||||
"Basic AI Translations": "Basis AI-vertalingen",
|
||||
@@ -399,5 +396,8 @@
|
||||
"More AI Translations": "Meer AI-vertalingen",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro toegang (200.000 tekens/dag)",
|
||||
"We couldn't process your subscription. Please try again or contact support if the issue persists.": "We konden je abonnement niet verwerken. Probeer het opnieuw of neem contact op met support als het probleem blijft bestaan.",
|
||||
"Thank you for your subscription! Your payment has been processed successfully.": "Bedankt voor je abonnement! Je betaling is succesvol verwerkt."
|
||||
"Thank you for your subscription! Your payment has been processed successfully.": "Bedankt voor je abonnement! Je betaling is succesvol verwerkt.",
|
||||
"Complete Your Subscription": "Voltooi uw abonnement",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% van de cloud-synchronisatie ruimte gebruikt.",
|
||||
"Cloud Sync Storage": "Cloud Sync Opslag"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Nie udało się pobrać książki: {{title}}",
|
||||
"Upload Book": "Prześlij książkę",
|
||||
"Auto Upload Books to Cloud": "Automatycznie przesyłaj książki do chmury",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% przestrzeni dyskowej w chmurze użytej.",
|
||||
"Storage": "Przechowywanie",
|
||||
"Book deleted: {{title}}": "Książka usunięta: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Nie udało się usunąć książki: {{title}}",
|
||||
"Check Updates on Start": "Sprawdź aktualizacje przy starcie",
|
||||
@@ -398,7 +396,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Nieograniczone godziny zamiany tekstu na mowę",
|
||||
"DeepL Free Access (10K characters/day)": "Darmowy dostęp do DeepL (10 tys. znaków/dzień)",
|
||||
"AI Translations (per day)": "Tłumaczenia AI (na dzień)",
|
||||
"Cloud Storage": "Przechowywanie w chmurze",
|
||||
"Plus Plan": "Plan Plus",
|
||||
"Includes All Free Plan Benefits": "Zawiera wszystkie korzyści planu darmowego",
|
||||
"Basic AI Translations": "Podstawowe tłumaczenia AI",
|
||||
@@ -407,5 +404,8 @@
|
||||
"Pro Plan": "Plan Pro",
|
||||
"Includes All Plus Plan Benefits": "Zawiera wszystkie korzyści planu Plus",
|
||||
"More AI Translations": "Więcej tłumaczeń AI",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro (200 tys. znaków/dzień)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro (200 tys. znaków/dzień)",
|
||||
"Complete Your Subscription": "Ukończ subskrypcję",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "Użyto {{percentage}}% przestrzeni synchronizacji w chmurze.",
|
||||
"Cloud Sync Storage": "Miejsce w chmurze"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Falha ao baixar livro: {{title}}",
|
||||
"Upload Book": "Enviar Livro",
|
||||
"Auto Upload Books to Cloud": "Enviar Livros para a Nuvem Automaticamente",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% do Armazenamento na Nuvem Usado.",
|
||||
"Storage": "Armazenamento",
|
||||
"Book deleted: {{title}}": "Livro excluído: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Falha ao excluir livro: {{title}}",
|
||||
"Check Updates on Start": "Verificar Atualizações ao Iniciar",
|
||||
@@ -394,7 +392,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Horas ilimitadas de texto para fala",
|
||||
"DeepL Free Access (10K characters/day)": "Acesso gratuito ao DeepL (10 mil caracteres/dia)",
|
||||
"AI Translations (per day)": "Traduções com IA (por dia)",
|
||||
"Cloud Storage": "Armazenamento na nuvem",
|
||||
"Plus Plan": "Plano Plus",
|
||||
"Includes All Free Plan Benefits": "Inclui todos os benefícios do plano gratuito",
|
||||
"Basic AI Translations": "Traduções básicas com IA",
|
||||
@@ -403,5 +400,8 @@
|
||||
"Pro Plan": "Plano Pro",
|
||||
"Includes All Plus Plan Benefits": "Inclui todos os benefícios do plano Plus",
|
||||
"More AI Translations": "Mais traduções com IA",
|
||||
"DeepL Pro Access (200K characters/day)": "Acesso ao DeepL Pro (200 mil caracteres/dia)"
|
||||
"DeepL Pro Access (200K characters/day)": "Acesso ao DeepL Pro (200 mil caracteres/dia)",
|
||||
"Complete Your Subscription": "Complete sua assinatura",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "{{percentage}}% do espaço de sincronização na nuvem utilizado.",
|
||||
"Cloud Sync Storage": "Armazenamento na Nuvem"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Не удалось скачать книгу: {{title}}",
|
||||
"Upload Book": "Загрузить книгу",
|
||||
"Auto Upload Books to Cloud": "Автоматическая загрузка книг в облако",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% использовано облачного хранилища.",
|
||||
"Storage": "Хранилище",
|
||||
"Book deleted: {{title}}": "Книга удалена: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Не удалось удалить книгу: {{title}}",
|
||||
"Check Updates on Start": "Проверять обновления при запуске",
|
||||
@@ -398,7 +396,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Неограниченные часы озвучивания текста",
|
||||
"DeepL Free Access (10K characters/day)": "Бесплатный доступ к DeepL (10 тыс. символов/день)",
|
||||
"AI Translations (per day)": "Переводы ИИ (в день)",
|
||||
"Cloud Storage": "Облачное хранилище",
|
||||
"Plus Plan": "План Plus",
|
||||
"Includes All Free Plan Benefits": "Включает все преимущества бесплатного плана",
|
||||
"Basic AI Translations": "Базовые переводы ИИ",
|
||||
@@ -407,5 +404,8 @@
|
||||
"Pro Plan": "План Pro",
|
||||
"Includes All Plus Plan Benefits": "Включает все преимущества плана Plus",
|
||||
"More AI Translations": "Больше переводов ИИ",
|
||||
"DeepL Pro Access (200K characters/day)": "Доступ к DeepL Pro (200 тыс. символов/день)"
|
||||
"DeepL Pro Access (200K characters/day)": "Доступ к DeepL Pro (200 тыс. символов/день)",
|
||||
"Complete Your Subscription": "Завершите подписку",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "Использовано {{percentage}}% облачного пространства для синхронизации.",
|
||||
"Cloud Sync Storage": "Облачное хранилище"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Kitap indirilemedi: {{title}}",
|
||||
"Upload Book": "Kitap Yükle",
|
||||
"Auto Upload Books to Cloud": "Kitapları Otomatik Olarak Buluta Yükle",
|
||||
"{{percentage}}% of Cloud Storage Used.": "Bulut Depolamanın %{{percentage}}'si kullanıldı.",
|
||||
"Storage": "Depolama",
|
||||
"Book deleted: {{title}}": "Kitap silindi: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Kitap silinemedi: {{title}}",
|
||||
"Check Updates on Start": "Başlangıçta Güncellemeleri Kontrol Et",
|
||||
@@ -390,7 +388,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Sınırsız Sesli Okuma Süresi",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL Ücretsiz Erişim (Günde 10K karakter)",
|
||||
"AI Translations (per day)": "AI Çevirileri (günlük)",
|
||||
"Cloud Storage": "Bulut Depolama",
|
||||
"Plus Plan": "Plus Plan",
|
||||
"Includes All Free Plan Benefits": "Tüm Ücretsiz Plan Özelliklerini İçerir",
|
||||
"Basic AI Translations": "Temel AI Çevirileri",
|
||||
@@ -399,5 +396,8 @@
|
||||
"Pro Plan": "Pro Plan",
|
||||
"Includes All Plus Plan Benefits": "Tüm Plus Plan Özelliklerini İçerir",
|
||||
"More AI Translations": "Daha Fazla AI Çevirisi",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro Erişim (Günde 200K karakter)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro Erişim (Günde 200K karakter)",
|
||||
"Complete Your Subscription": "Aboneliğinizi Tamamlayın",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "Bulut Senkronizasyon Alanının %{{percentage}}'si Kullanıldı.",
|
||||
"Cloud Sync Storage": "Bulut Senkronizasyon Depolama"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Не вдалося завантажити книгу: {{title}}",
|
||||
"Upload Book": "Завантажити книгу",
|
||||
"Auto Upload Books to Cloud": "Автоматично завантажувати книги в хмару",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% використано хмарного сховища.",
|
||||
"Storage": "Сховище",
|
||||
"Book deleted: {{title}}": "Книгу видалено: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Не вдалося видалити книгу: {{title}}",
|
||||
"Check Updates on Start": "Перевіряти оновлення при запуску",
|
||||
@@ -398,7 +396,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Необмежені години озвучення тексту",
|
||||
"DeepL Free Access (10K characters/day)": "Безкоштовний доступ до DeepL (10 тис. символів/день)",
|
||||
"AI Translations (per day)": "AI-переклади (на день)",
|
||||
"Cloud Storage": "Хмарне сховище",
|
||||
"Plus Plan": "План Plus",
|
||||
"Includes All Free Plan Benefits": "Включає всі переваги Безкоштовного плану",
|
||||
"Basic AI Translations": "Базові AI-переклади",
|
||||
@@ -407,5 +404,8 @@
|
||||
"Pro Plan": "План Pro",
|
||||
"Includes All Plus Plan Benefits": "Включає всі переваги плану Plus",
|
||||
"More AI Translations": "Більше AI-перекладів",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro доступ (200 тис. символів/день)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro доступ (200 тис. символів/день)",
|
||||
"Complete Your Subscription": "Завершіть підписку",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "Використано {{percentage}}% хмарного сховища.",
|
||||
"Cloud Sync Storage": "Облачне хранилище"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "Không thể tải về sách: {{title}}",
|
||||
"Upload Book": "Tải lên sách",
|
||||
"Auto Upload Books to Cloud": "Tự động tải sách lên đám mây",
|
||||
"{{percentage}}% of Cloud Storage Used.": "{{percentage}}% dung lượng lưu trữ đám mây đã sử dụng.",
|
||||
"Storage": "Lưu trữ",
|
||||
"Book deleted: {{title}}": "Sách đã xóa: {{title}}",
|
||||
"Failed to delete book: {{title}}": "Không thể xóa sách: {{title}}",
|
||||
"Check Updates on Start": "Kiểm tra cập nhật khi khởi động",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "Không giới hạn giờ chuyển văn bản thành giọng nói",
|
||||
"DeepL Free Access (10K characters/day)": "Truy cập DeepL miễn phí (10.000 ký tự/ngày)",
|
||||
"AI Translations (per day)": "Dịch AI (mỗi ngày)",
|
||||
"Cloud Storage": "Lưu trữ đám mây",
|
||||
"Plus Plan": "Gói Plus",
|
||||
"Includes All Free Plan Benefits": "Bao gồm tất cả lợi ích của gói miễn phí",
|
||||
"Basic AI Translations": "Dịch AI cơ bản",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Gói Pro",
|
||||
"Includes All Plus Plan Benefits": "Bao gồm tất cả lợi ích của gói Plus",
|
||||
"More AI Translations": "Thêm dịch AI",
|
||||
"DeepL Pro Access (200K characters/day)": "Truy cập DeepL Pro (200.000 ký tự/ngày)"
|
||||
"DeepL Pro Access (200K characters/day)": "Truy cập DeepL Pro (200.000 ký tự/ngày)",
|
||||
"Complete Your Subscription": "Hoàn tất đăng ký của bạn",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "Đã sử dụng {{percentage}}% không gian đồng bộ đám mây.",
|
||||
"Cloud Sync Storage": "Lưu trữ đồng bộ đám mây"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "下载书籍失败:{{title}}",
|
||||
"Upload Book": "上传书籍",
|
||||
"Auto Upload Books to Cloud": "自动上传书籍到云端",
|
||||
"{{percentage}}% of Cloud Storage Used.": "已使用 {{percentage}}% 云存储空间",
|
||||
"Storage": "存储空间",
|
||||
"Book deleted: {{title}}": "书籍已删除:{{title}}",
|
||||
"Failed to delete book: {{title}}": "删除书籍失败:{{title}}",
|
||||
"Check Updates on Start": "启动时检查更新",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "无限文本转语音时长",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL 免费额度(每日1万字符)",
|
||||
"AI Translations (per day)": "AI 翻译(每日)",
|
||||
"Cloud Storage": "云存储",
|
||||
"Plus Plan": "Plus 套餐",
|
||||
"Includes All Free Plan Benefits": "包含所有免费套餐功能",
|
||||
"Basic AI Translations": "基础 AI 翻译",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Pro 套餐",
|
||||
"Includes All Plus Plan Benefits": "包含所有 Plus 套餐功能",
|
||||
"More AI Translations": "更多 AI 翻译",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro(每日20万字符)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro(每日20万字符)",
|
||||
"Complete Your Subscription": "完成您的订阅",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "已使用 {{percentage}}% 的云同步空间。",
|
||||
"Cloud Sync Storage": "云同步空间"
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@
|
||||
"Failed to download book: {{title}}": "書籍下載失敗:{{title}}",
|
||||
"Upload Book": "上傳書籍",
|
||||
"Auto Upload Books to Cloud": "自動上傳書籍到雲端",
|
||||
"{{percentage}}% of Cloud Storage Used.": "已使用 {{percentage}}% 雲存儲空間",
|
||||
"Storage": "存儲空間",
|
||||
"Book deleted: {{title}}": "書籍已刪除:{{title}}",
|
||||
"Failed to delete book: {{title}}": "書籍刪除失敗:{{title}}",
|
||||
"Check Updates on Start": "啟動時檢查更新",
|
||||
@@ -386,7 +384,6 @@
|
||||
"Unlimited Text-to-Speech Hours": "無限文字轉語音時數",
|
||||
"DeepL Free Access (10K characters/day)": "DeepL 免費使用(每日1萬字)",
|
||||
"AI Translations (per day)": "AI 翻譯(每日)",
|
||||
"Cloud Storage": "雲端儲存",
|
||||
"Plus Plan": "Plus 方案",
|
||||
"Includes All Free Plan Benefits": "包含所有免費方案功能",
|
||||
"Basic AI Translations": "基本 AI 翻譯",
|
||||
@@ -395,5 +392,8 @@
|
||||
"Pro Plan": "Pro 方案",
|
||||
"Includes All Plus Plan Benefits": "包含所有 Plus 方案功能",
|
||||
"More AI Translations": "更多 AI 翻譯",
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro(每日20萬字)"
|
||||
"DeepL Pro Access (200K characters/day)": "DeepL Pro(每日20萬字)",
|
||||
"Complete Your Subscription": "完成您的訂閱",
|
||||
"{{percentage}}% of Cloud Sync Space Used.": "已使用 {{percentage}}% 的雲同步空間。",
|
||||
"Cloud Sync Storage": "雲同步空間"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { validateUserAndToken } from '@/utils/access';
|
||||
import { supabase } from '@/utils/supabase';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const { priceId, metadata = {} } = await request.json();
|
||||
const { priceId, embedded = true, metadata = {} } = await request.json();
|
||||
|
||||
const { user, token } = await validateUserAndToken(request.headers.get('authorization'));
|
||||
if (!user || !token) {
|
||||
@@ -42,7 +42,10 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
const stripe = getStripe();
|
||||
const successUrl = `${request.headers.get('origin')}/user/subscription/success?session_id={CHECKOUT_SESSION_ID}`;
|
||||
const returnUrl = `${request.headers.get('origin')}/user`;
|
||||
const session = await stripe.checkout.sessions.create({
|
||||
ui_mode: embedded ? 'embedded' : 'hosted',
|
||||
customer: customerId,
|
||||
mode: 'subscription',
|
||||
payment_method_types: ['card'],
|
||||
@@ -53,11 +56,16 @@ export async function POST(request: NextRequest) {
|
||||
},
|
||||
],
|
||||
metadata: enhancedMetadata,
|
||||
success_url: `${request.headers.get('origin')}/user/subscription/success?session_id={CHECKOUT_SESSION_ID}`,
|
||||
cancel_url: `${request.headers.get('origin')}/user`,
|
||||
success_url: embedded ? undefined : successUrl,
|
||||
cancel_url: embedded ? undefined : returnUrl,
|
||||
redirect_on_completion: embedded ? 'never' : undefined,
|
||||
});
|
||||
|
||||
return NextResponse.json({ sessionId: session.id, url: session.url });
|
||||
return NextResponse.json({
|
||||
url: session.url,
|
||||
sessionId: session.id,
|
||||
clientSecret: session.client_secret,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return NextResponse.json({ error: 'Error creating checkout session' }, { status: 500 });
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
'use client';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import React, { useCallback } from 'react';
|
||||
import { EmbeddedCheckoutProvider, EmbeddedCheckout } from '@stripe/react-stripe-js';
|
||||
import { getStripe } from '@/libs/stripe/client';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
|
||||
interface CheckoutProps {
|
||||
clientSecret: string;
|
||||
sessionId: string;
|
||||
planName?: string;
|
||||
className?: string;
|
||||
onSuccess?: (sessionId: string) => void;
|
||||
}
|
||||
|
||||
const Checkout: React.FC<CheckoutProps> = ({
|
||||
clientSecret,
|
||||
sessionId,
|
||||
planName,
|
||||
onSuccess,
|
||||
className = '',
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const stripe = getStripe();
|
||||
|
||||
const options = {
|
||||
clientSecret,
|
||||
onComplete: useCallback(() => {
|
||||
onSuccess?.(sessionId);
|
||||
}, [onSuccess, sessionId]),
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx('w-full', className)}>
|
||||
<div className='mb-4 flex items-center justify-center'>
|
||||
<h3 className='text-center text-lg font-semibold'>
|
||||
{planName
|
||||
? _('Upgrade to {{plan}}', { plan: _(planName) })
|
||||
: _('Complete Your Subscription')}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className='border-base-300 overflow-hidden rounded-lg border'>
|
||||
<EmbeddedCheckoutProvider stripe={stripe} options={options}>
|
||||
<EmbeddedCheckout />
|
||||
</EmbeddedCheckoutProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkout;
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
import { isWebAppPlatform } from '@/services/environment';
|
||||
import { getPlanDetails } from '../utils/plan';
|
||||
import { AvailablePlan } from '../page';
|
||||
import { UserPlan } from '@/types/user';
|
||||
import { AvailablePlan } from '../page';
|
||||
import PlanNavigation from './PlanNavigation';
|
||||
import PlanCard from './PlanCard';
|
||||
import PlanIndicators from './PlanIndicators';
|
||||
@@ -19,6 +19,7 @@ const PlansComparison: React.FC<PlansComparisonProps> = ({
|
||||
userPlan,
|
||||
onSubscribe,
|
||||
}) => {
|
||||
const { appService } = useEnv();
|
||||
const [currentPlanIndex, setCurrentPlanIndex] = useState(0);
|
||||
const [userPlanIndex, setUserPlanIndex] = useState(0);
|
||||
const plansScrollRef = useRef<HTMLDivElement>(null);
|
||||
@@ -137,7 +138,7 @@ const PlansComparison: React.FC<PlansComparisonProps> = ({
|
||||
<PlanCard
|
||||
key={plan.plan}
|
||||
plan={plan}
|
||||
comingSoon={!isWebAppPlatform()}
|
||||
comingSoon={appService?.isIOSApp}
|
||||
isUserPlan={plan.plan === userPlan}
|
||||
upgradable={index > userPlanIndex}
|
||||
index={index}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
import clsx from 'clsx';
|
||||
import Stripe from 'stripe';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import posthog from 'posthog-js';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
@@ -15,15 +16,18 @@ import { navigateToLibrary } from '@/utils/nav';
|
||||
import { deleteUser } from '@/libs/user';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { getStripe } from '@/libs/stripe/client';
|
||||
import { getAPIBaseUrl } from '@/services/environment';
|
||||
import { getAPIBaseUrl, isTauriAppPlatform, isWebAppPlatform } from '@/services/environment';
|
||||
import { openUrl } from '@tauri-apps/plugin-opener';
|
||||
import { getAccessToken } from '@/utils/access';
|
||||
import { getPlanDetails } from './utils/plan';
|
||||
import { Toast } from '@/components/Toast';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import ProfileHeader from './components/Header';
|
||||
import UserInfo from './components/UserInfo';
|
||||
import UsageStats from './components/UsageStats';
|
||||
import PlansComparison from './components/PlansComparison';
|
||||
import AccountActions from './components/AccountActions';
|
||||
import Checkout from './components/Checkout';
|
||||
|
||||
const WEB_STRIPE_PLANS_URL = `${getAPIBaseUrl()}/stripe/plans`;
|
||||
const WEB_STRIPE_CHECKOUT_URL = `${getAPIBaseUrl()}/stripe/checkout`;
|
||||
@@ -38,6 +42,12 @@ export type AvailablePlan = {
|
||||
product: Stripe.Product;
|
||||
};
|
||||
|
||||
type CheckoutState = {
|
||||
clientSecret: string;
|
||||
sessionId: string;
|
||||
planName: string;
|
||||
};
|
||||
|
||||
const ProfilePage = () => {
|
||||
const _ = useTranslation();
|
||||
const router = useRouter();
|
||||
@@ -45,7 +55,14 @@ const ProfilePage = () => {
|
||||
const { token, user, logout } = useAuth();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [availablePlans, setAvailablePlans] = useState<AvailablePlan[]>([]);
|
||||
const [showEmbeddedCheckout, setShowEmbeddedCheckout] = useState(false);
|
||||
const [checkoutState, setCheckoutState] = useState<CheckoutState>({
|
||||
clientSecret: '',
|
||||
sessionId: '',
|
||||
planName: '',
|
||||
});
|
||||
|
||||
const [mounted, setMounted] = useState(false);
|
||||
useEffect(() => setMounted(true), []);
|
||||
@@ -55,7 +72,11 @@ const ProfilePage = () => {
|
||||
const { quotas, userPlan } = useQuotaStats();
|
||||
|
||||
const handleGoBack = () => {
|
||||
navigateToLibrary(router);
|
||||
if (showEmbeddedCheckout) {
|
||||
setShowEmbeddedCheckout(false);
|
||||
} else {
|
||||
navigateToLibrary(router);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
@@ -86,26 +107,54 @@ const ProfilePage = () => {
|
||||
console.error('Stripe not loaded');
|
||||
return;
|
||||
}
|
||||
const { sessionId, url } = await fetch(WEB_STRIPE_CHECKOUT_URL, {
|
||||
setLoading(true);
|
||||
const isEmbeddedCheckout = isTauriAppPlatform();
|
||||
const { sessionId, clientSecret, url } = await fetch(WEB_STRIPE_CHECKOUT_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({ priceId }),
|
||||
body: JSON.stringify({ priceId, embedded: isEmbeddedCheckout }),
|
||||
}).then((res) => res.json());
|
||||
setLoading(false);
|
||||
|
||||
if (url) {
|
||||
window.location.href = url;
|
||||
} else {
|
||||
const selectedPlan = availablePlans.find((plan) => plan.price_id === priceId)!;
|
||||
const planName = selectedPlan.product.name;
|
||||
if (isEmbeddedCheckout && sessionId && clientSecret) {
|
||||
setShowEmbeddedCheckout(true);
|
||||
setCheckoutState({
|
||||
planName,
|
||||
clientSecret,
|
||||
sessionId,
|
||||
});
|
||||
} else if (url) {
|
||||
if (isWebAppPlatform()) {
|
||||
window.location.href = url;
|
||||
} else if (isTauriAppPlatform()) {
|
||||
await openUrl(url);
|
||||
}
|
||||
} else if (sessionId) {
|
||||
const result = await stripe.redirectToCheckout({ sessionId });
|
||||
|
||||
if (result.error) {
|
||||
console.error(result.error);
|
||||
posthog.capture('checkout_error', {
|
||||
error: 'Failed to redirect to checkout',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error('No sessionId or url returned from checkout API');
|
||||
posthog.capture('checkout_error', {
|
||||
error: 'No sessionId or url returned from checkout API',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleCheckoutSuccess = useCallback((sessionId: string) => {
|
||||
setShowEmbeddedCheckout(false);
|
||||
router.push(`/user/subscription/success?session_id=${sessionId}`);
|
||||
}, []);
|
||||
|
||||
const handleManageSubscription = async () => {
|
||||
const token = await getAccessToken();
|
||||
const response = await fetch(WEB_STRIPE_PORTAL_URL, {
|
||||
@@ -127,7 +176,11 @@ const ProfilePage = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = url;
|
||||
if (isWebAppPlatform()) {
|
||||
window.location.href = url;
|
||||
} else if (isTauriAppPlatform()) {
|
||||
await openUrl(url);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -168,31 +221,47 @@ const ProfilePage = () => {
|
||||
>
|
||||
<ProfileHeader onGoBack={handleGoBack} />
|
||||
<div className='w-full min-w-60 max-w-4xl px-4 py-10'>
|
||||
<div className='bg-base-200 overflow-hidden rounded-lg p-2 shadow-md sm:p-6'>
|
||||
<div className='flex flex-col gap-y-8 p-2 sm:p-6'>
|
||||
<UserInfo
|
||||
avatarUrl={avatarUrl}
|
||||
userFullName={userFullName}
|
||||
userEmail={userEmail}
|
||||
planDetails={planDetails}
|
||||
/>
|
||||
|
||||
<UsageStats quotas={quotas} />
|
||||
|
||||
<PlansComparison
|
||||
availablePlans={availablePlans}
|
||||
userPlan={userPlan}
|
||||
onSubscribe={handleSubscribe}
|
||||
/>
|
||||
|
||||
<AccountActions
|
||||
userPlan={userPlan}
|
||||
onLogout={handleLogout}
|
||||
onConfirmDelete={handleConfirmDelete}
|
||||
onManageSubscription={handleManageSubscription}
|
||||
{loading && (
|
||||
<div className='fixed inset-0 z-50 flex items-center justify-center'>
|
||||
<Spinner loading />
|
||||
</div>
|
||||
)}
|
||||
{showEmbeddedCheckout ? (
|
||||
<div className='bg-base-100 rounded-lg p-4'>
|
||||
<Checkout
|
||||
clientSecret={checkoutState.clientSecret}
|
||||
sessionId={checkoutState.sessionId}
|
||||
planName={checkoutState.planName}
|
||||
onSuccess={handleCheckoutSuccess}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className='bg-base-200 overflow-hidden rounded-lg p-2 shadow-md sm:p-6'>
|
||||
<div className='flex flex-col gap-y-8 p-2 sm:p-6'>
|
||||
<UserInfo
|
||||
avatarUrl={avatarUrl}
|
||||
userFullName={userFullName}
|
||||
userEmail={userEmail}
|
||||
planDetails={planDetails}
|
||||
/>
|
||||
|
||||
<UsageStats quotas={quotas} />
|
||||
|
||||
<PlansComparison
|
||||
availablePlans={availablePlans}
|
||||
userPlan={userPlan}
|
||||
onSubscribe={handleSubscribe}
|
||||
/>
|
||||
|
||||
<AccountActions
|
||||
userPlan={userPlan}
|
||||
onLogout={handleLogout}
|
||||
onConfirmDelete={handleConfirmDelete}
|
||||
onManageSubscription={handleManageSubscription}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Toast />
|
||||
</div>
|
||||
|
||||
@@ -35,8 +35,8 @@ export const getPlanDetails = (
|
||||
_('500 MB Cloud Sync Space'),
|
||||
],
|
||||
limits: {
|
||||
[_('Cloud Sync Storage')]: '500 MB',
|
||||
[_('AI Translations (per day)')]: '10K',
|
||||
[_('Cloud Storage')]: '500 MB',
|
||||
},
|
||||
};
|
||||
case 'plus':
|
||||
@@ -55,8 +55,8 @@ export const getPlanDetails = (
|
||||
_('2 GB Cloud Sync Space'),
|
||||
],
|
||||
limits: {
|
||||
[_('Cloud Sync Storage')]: '2 GB',
|
||||
[_('AI Translations (per day)')]: '50K',
|
||||
[_('Cloud Storage')]: '2 GB',
|
||||
},
|
||||
};
|
||||
case 'pro':
|
||||
@@ -76,8 +76,8 @@ export const getPlanDetails = (
|
||||
_('10 GB Cloud Sync Space'),
|
||||
],
|
||||
limits: {
|
||||
[_('Cloud Sync Storage')]: '10 GB',
|
||||
[_('AI Translations (per day)')]: '200K',
|
||||
[_('Cloud Storage')]: '10 GB',
|
||||
},
|
||||
};
|
||||
default:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import packageJson from '../../package.json';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { checkForAppUpdates } from '@/helpers/updater';
|
||||
import { parseWebViewVersion } from '@/utils/ua';
|
||||
import { getAppVersion } from '@/utils/version';
|
||||
import Dialog from './Dialog';
|
||||
import Link from './Link';
|
||||
|
||||
@@ -83,7 +83,7 @@ export const AboutWindow = () => {
|
||||
<div className='flex select-text flex-col items-center'>
|
||||
<h2 className='mb-2 text-2xl font-bold'>Readest</h2>
|
||||
<p className='text-neutral-content text-center text-sm'>
|
||||
{_('Version {{version}}', { version: packageJson.version })} {`(${browserInfo})`}
|
||||
{_('Version {{version}}', { version: getAppVersion() })} {`(${browserInfo})`}
|
||||
</p>
|
||||
</div>
|
||||
<div className='h-5'>
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IconContext } from 'react-icons';
|
||||
import { AuthProvider } from '@/context/AuthContext';
|
||||
import { EnvProvider } from '@/context/EnvContext';
|
||||
import { CSPostHogProvider } from '@/context/PHContext';
|
||||
import { SyncProvider } from '@/context/SyncContext';
|
||||
import { useDefaultIconSize } from '@/hooks/useResponsiveSize';
|
||||
import { isWebAppPlatform } from '@/services/environment';
|
||||
|
||||
const Providers = ({ children }: { children: React.ReactNode }) => {
|
||||
const iconSize = useDefaultIconSize();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
useEffect(() => setMounted(true), []);
|
||||
return mounted || isWebAppPlatform() ? (
|
||||
return (
|
||||
<CSPostHogProvider>
|
||||
<EnvProvider>
|
||||
<AuthProvider>
|
||||
@@ -23,7 +19,7 @@ const Providers = ({ children }: { children: React.ReactNode }) => {
|
||||
</AuthProvider>
|
||||
</EnvProvider>
|
||||
</CSPostHogProvider>
|
||||
) : null;
|
||||
);
|
||||
};
|
||||
|
||||
export default Providers;
|
||||
|
||||
@@ -10,11 +10,11 @@ import { fetch } from '@tauri-apps/plugin-http';
|
||||
import { useTranslator } from '@/hooks/useTranslator';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { getAppVersion } from '@/utils/version';
|
||||
import { tauriDownload } from '@/utils/transfer';
|
||||
import { installPackage } from '@/utils/bridge';
|
||||
import { getLocale } from '@/utils/misc';
|
||||
import { READEST_UPDATER_FILE, READEST_CHANGELOG_FILE } from '@/services/constants';
|
||||
import packageJson from '../../package.json';
|
||||
import Dialog from '@/components/Dialog';
|
||||
|
||||
interface ReleaseNotes {
|
||||
@@ -68,7 +68,7 @@ export const UpdaterContent = ({ version }: { version?: string }) => {
|
||||
});
|
||||
const { appService } = useEnv();
|
||||
const searchParams = useSearchParams();
|
||||
const currentVersion = packageJson.version;
|
||||
const currentVersion = getAppVersion();
|
||||
const resolvedVersion = version ?? searchParams?.get('version') ?? '';
|
||||
const [update, setUpdate] = useState<GenericUpdate | Update | null>(null);
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
@@ -93,7 +93,7 @@ export const UpdaterContent = ({ version }: { version?: string }) => {
|
||||
const checkAndroidUpdate = async () => {
|
||||
const response = await fetch(READEST_UPDATER_FILE);
|
||||
const data = await response.json();
|
||||
if (semver.gt(data.version, packageJson.version)) {
|
||||
if (semver.gt(data.version, currentVersion)) {
|
||||
const OS_ARCH = osArch();
|
||||
const platformKey = OS_ARCH === 'aarch64' ? 'android-arm64' : 'android-universal';
|
||||
const arch = OS_ARCH === 'aarch64' ? 'arm64' : 'universal';
|
||||
@@ -101,7 +101,7 @@ export const UpdaterContent = ({ version }: { version?: string }) => {
|
||||
const cachePrefix = appService?.fs.getPrefix('Cache');
|
||||
const apkFilePath = `${cachePrefix}/Readest_${data.version}_${arch}.apk`;
|
||||
setUpdate({
|
||||
currentVersion: packageJson.version,
|
||||
currentVersion,
|
||||
version: data.version,
|
||||
date: data.date,
|
||||
body: data.notes,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import posthog from 'posthog-js';
|
||||
import { ReactNode } from 'react';
|
||||
import { ReactNode, useEffect } from 'react';
|
||||
import { PostHogProvider } from 'posthog-js/react';
|
||||
import { TELEMETRY_OPT_OUT_KEY } from '@/utils/telemetry';
|
||||
import { getAppVersion } from '@/utils/version';
|
||||
|
||||
const shouldDisablePostHog = () => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
@@ -27,5 +28,10 @@ if (typeof window !== 'undefined' && process.env['NODE_ENV'] === 'production' &&
|
||||
}
|
||||
}
|
||||
export const CSPostHogProvider = ({ children }: { children: ReactNode }) => {
|
||||
useEffect(() => {
|
||||
posthog.register_for_session({
|
||||
$app_version: getAppVersion(),
|
||||
});
|
||||
}, []);
|
||||
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
|
||||
};
|
||||
|
||||
@@ -5,8 +5,8 @@ import { fetch } from '@tauri-apps/plugin-http';
|
||||
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||
import { TranslationFunc } from '@/hooks/useTranslation';
|
||||
import { setUpdaterWindowVisible } from '@/components/UpdaterWindow';
|
||||
import { getAppVersion } from '@/utils/version';
|
||||
import { CHECK_UPDATE_INTERVAL_SEC, READEST_UPDATER_FILE } from '@/services/constants';
|
||||
import packageJson from '../../package.json';
|
||||
|
||||
const LAST_CHECK_KEY = 'lastAppUpdateCheck';
|
||||
|
||||
@@ -49,7 +49,7 @@ export const checkForAppUpdates = async (
|
||||
try {
|
||||
const response = await fetch(READEST_UPDATER_FILE, { connectTimeout: 5000 });
|
||||
const data = await response.json();
|
||||
const isNewer = semver.gt(data.version, packageJson.version);
|
||||
const isNewer = semver.gt(data.version, getAppVersion());
|
||||
if (isNewer && ('android-arm64' in data.platforms || 'android-universal' in data.platforms)) {
|
||||
setUpdaterWindowVisible(true, data.version);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ export const useQuotaStats = () => {
|
||||
const userPlan = getUserPlan(token);
|
||||
const storagPlan = getStoragePlanData(token);
|
||||
const storageQuota: QuotaType = {
|
||||
name: _('Storage'),
|
||||
tooltip: _('{{percentage}}% of Cloud Storage Used.', {
|
||||
name: _('Cloud Sync Storage'),
|
||||
tooltip: _('{{percentage}}% of Cloud Sync Space Used.', {
|
||||
percentage: Math.round((storagPlan.usage / storagPlan.quota) * 100),
|
||||
}),
|
||||
used: Math.round(storagPlan.usage / 1024 / 1024),
|
||||
|
||||
@@ -41,7 +41,7 @@ export class SyncClient {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
},
|
||||
5000,
|
||||
8000,
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -70,7 +70,7 @@ export class SyncClient {
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
5000,
|
||||
8000,
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getAccessToken } from './access';
|
||||
|
||||
export const fetchWithTimeout = (url: string, options: RequestInit, timeout = 8000) => {
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), timeout);
|
||||
const id = setTimeout(() => controller.abort('Request timed out'), timeout);
|
||||
|
||||
return fetch(url, {
|
||||
...options,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import packageJson from '../../package.json';
|
||||
|
||||
export const getAppVersion = () => {
|
||||
return packageJson.version;
|
||||
};
|
||||
Generated
+47
-20
@@ -53,18 +53,21 @@ importers:
|
||||
'@opennextjs/cloudflare':
|
||||
specifier: ^1.3.1
|
||||
version: 1.3.1(wrangler@4.21.0)
|
||||
'@stripe/react-stripe-js':
|
||||
specifier: ^3.7.0
|
||||
version: 3.7.0(@stripe/stripe-js@7.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@stripe/stripe-js':
|
||||
specifier: ^7.4.0
|
||||
version: 7.4.0
|
||||
'@supabase/auth-ui-react':
|
||||
specifier: ^0.4.7
|
||||
version: 0.4.7(@supabase/supabase-js@2.49.10)
|
||||
version: 0.4.7(@supabase/supabase-js@2.50.2)
|
||||
'@supabase/auth-ui-shared':
|
||||
specifier: ^0.1.8
|
||||
version: 0.1.8(@supabase/supabase-js@2.49.10)
|
||||
version: 0.1.8(@supabase/supabase-js@2.50.2)
|
||||
'@supabase/supabase-js':
|
||||
specifier: ^2.49.10
|
||||
version: 2.49.10
|
||||
specifier: ^2.50.2
|
||||
version: 2.50.2
|
||||
'@tauri-apps/api':
|
||||
specifier: 2.6.0
|
||||
version: 2.6.0
|
||||
@@ -2545,12 +2548,19 @@ packages:
|
||||
'@stitches/core@1.2.8':
|
||||
resolution: {integrity: sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==}
|
||||
|
||||
'@stripe/react-stripe-js@3.7.0':
|
||||
resolution: {integrity: sha512-PYls/2S9l0FF+2n0wHaEJsEU8x7CmBagiH7zYOsxbBlLIHEsqUIQ4MlIAbV9Zg6xwT8jlYdlRIyBTHmO3yM7kQ==}
|
||||
peerDependencies:
|
||||
'@stripe/stripe-js': '>=1.44.1 <8.0.0'
|
||||
react: '>=16.8.0 <20.0.0'
|
||||
react-dom: '>=16.8.0 <20.0.0'
|
||||
|
||||
'@stripe/stripe-js@7.4.0':
|
||||
resolution: {integrity: sha512-lQHQPfXPTBeh0XFjq6PqSBAyR7umwcJbvJhXV77uGCUDD6ymXJU/f2164ydLMLCCceNuPlbV9b+1smx98efwWQ==}
|
||||
engines: {node: '>=12.16'}
|
||||
|
||||
'@supabase/auth-js@2.69.1':
|
||||
resolution: {integrity: sha512-FILtt5WjCNzmReeRLq5wRs3iShwmnWgBvxHfqapC/VoljJl+W8hDAyFmf1NVw3zH+ZjZ05AKxiKxVeb0HNWRMQ==}
|
||||
'@supabase/auth-js@2.70.0':
|
||||
resolution: {integrity: sha512-BaAK/tOAZFJtzF1sE3gJ2FwTjLf4ky3PSvcvLGEgEmO4BSBkwWKu8l67rLLIBZPDnCyV7Owk2uPyKHa0kj5QGg==}
|
||||
|
||||
'@supabase/auth-ui-react@0.4.7':
|
||||
resolution: {integrity: sha512-Lp4FQGFh7BMX1Y/BFaUKidbryL7eskj1fl6Lby7BeHrTctbdvDbCMjVKS8wZ2rxuI8FtPS2iU900fSb70FHknQ==}
|
||||
@@ -2572,14 +2582,14 @@ packages:
|
||||
'@supabase/postgrest-js@1.19.4':
|
||||
resolution: {integrity: sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==}
|
||||
|
||||
'@supabase/realtime-js@2.11.10':
|
||||
resolution: {integrity: sha512-SJKVa7EejnuyfImrbzx+HaD9i6T784khuw1zP+MBD7BmJYChegGxYigPzkKX8CK8nGuDntmeSD3fvriaH0EGZA==}
|
||||
'@supabase/realtime-js@2.11.15':
|
||||
resolution: {integrity: sha512-HQKRnwAqdVqJW/P9TjKVK+/ETpW4yQ8tyDPPtRMKOH4Uh3vQD74vmj353CYs8+YwVBKubeUOOEpI9CT8mT4obw==}
|
||||
|
||||
'@supabase/storage-js@2.7.1':
|
||||
resolution: {integrity: sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==}
|
||||
|
||||
'@supabase/supabase-js@2.49.10':
|
||||
resolution: {integrity: sha512-IRPcIdncuhD2m1eZ2Fkg0S1fq9SXlHfmAetBxPN66kVFtTucR8b01xKuVmKqcIJokB17umMf1bmqyS8yboXGsw==}
|
||||
'@supabase/supabase-js@2.50.2':
|
||||
resolution: {integrity: sha512-+27xlGgw7VyfwXXe+OiDJQosJNS+PPtjj1EnLR4uk+PKKZ91RA0/8NbIQybe6AGPanAaPtgOFFMMCArC6fZ++Q==}
|
||||
|
||||
'@surma/rollup-plugin-off-main-thread@2.2.3':
|
||||
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
|
||||
@@ -4333,6 +4343,11 @@ packages:
|
||||
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
isows@1.0.7:
|
||||
resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==}
|
||||
peerDependencies:
|
||||
ws: '*'
|
||||
|
||||
iterator.prototype@1.1.3:
|
||||
resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -9381,24 +9396,31 @@ snapshots:
|
||||
|
||||
'@stitches/core@1.2.8': {}
|
||||
|
||||
'@stripe/react-stripe-js@3.7.0(@stripe/stripe-js@7.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
'@stripe/stripe-js': 7.4.0
|
||||
prop-types: 15.8.1
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
'@stripe/stripe-js@7.4.0': {}
|
||||
|
||||
'@supabase/auth-js@2.69.1':
|
||||
'@supabase/auth-js@2.70.0':
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
|
||||
'@supabase/auth-ui-react@0.4.7(@supabase/supabase-js@2.49.10)':
|
||||
'@supabase/auth-ui-react@0.4.7(@supabase/supabase-js@2.50.2)':
|
||||
dependencies:
|
||||
'@stitches/core': 1.2.8
|
||||
'@supabase/auth-ui-shared': 0.1.8(@supabase/supabase-js@2.49.10)
|
||||
'@supabase/supabase-js': 2.49.10
|
||||
'@supabase/auth-ui-shared': 0.1.8(@supabase/supabase-js@2.50.2)
|
||||
'@supabase/supabase-js': 2.50.2
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@supabase/auth-ui-shared@0.1.8(@supabase/supabase-js@2.49.10)':
|
||||
'@supabase/auth-ui-shared@0.1.8(@supabase/supabase-js@2.50.2)':
|
||||
dependencies:
|
||||
'@supabase/supabase-js': 2.49.10
|
||||
'@supabase/supabase-js': 2.50.2
|
||||
|
||||
'@supabase/functions-js@2.4.4':
|
||||
dependencies:
|
||||
@@ -9412,11 +9434,12 @@ snapshots:
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
|
||||
'@supabase/realtime-js@2.11.10':
|
||||
'@supabase/realtime-js@2.11.15':
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
'@types/phoenix': 1.6.6
|
||||
'@types/ws': 8.18.1
|
||||
isows: 1.0.7(ws@8.18.2)
|
||||
ws: 8.18.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@@ -9426,13 +9449,13 @@ snapshots:
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
|
||||
'@supabase/supabase-js@2.49.10':
|
||||
'@supabase/supabase-js@2.50.2':
|
||||
dependencies:
|
||||
'@supabase/auth-js': 2.69.1
|
||||
'@supabase/auth-js': 2.70.0
|
||||
'@supabase/functions-js': 2.4.4
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
'@supabase/postgrest-js': 1.19.4
|
||||
'@supabase/realtime-js': 2.11.10
|
||||
'@supabase/realtime-js': 2.11.15
|
||||
'@supabase/storage-js': 2.7.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@@ -11410,6 +11433,10 @@ snapshots:
|
||||
|
||||
isobject@3.0.1: {}
|
||||
|
||||
isows@1.0.7(ws@8.18.2):
|
||||
dependencies:
|
||||
ws: 8.18.2
|
||||
|
||||
iterator.prototype@1.1.3:
|
||||
dependencies:
|
||||
define-properties: 1.2.1
|
||||
|
||||
Reference in New Issue
Block a user