feat(plan): show life-time plan name in user profile (#2360)
This commit is contained in:
@@ -659,5 +659,6 @@
|
||||
"Squiggly": "متعرج",
|
||||
"Outline": "مخطط",
|
||||
"Save Current Color": "حفظ اللون الحالي",
|
||||
"Quick Colors": "ألوان سريعة"
|
||||
"Quick Colors": "ألوان سريعة",
|
||||
"Highlighter": "محدد النص"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "ঢেউখেলানো দাগ",
|
||||
"Outline": "বাহিরের রেখা",
|
||||
"Save Current Color": "বর্তমান রঙ সংরক্ষণ করুন",
|
||||
"Quick Colors": "দ্রুত রংসমূহ"
|
||||
"Quick Colors": "দ্রুত রংসমূহ",
|
||||
"Highlighter": "হাইলাইটার"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "འཁྱོག་ཐིག",
|
||||
"Outline": "མཐའ་ཐིག",
|
||||
"Save Current Color": "མིག་སྔའི་ཚོན་གཏན་འཁེལ་བྱེད།",
|
||||
"Quick Colors": "མྱུར་ཚོན།"
|
||||
"Quick Colors": "མྱུར་ཚོན།",
|
||||
"Highlighter": "མདོག་ཚད་ཀྱི་བསྡུར་བ།"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "Wellig",
|
||||
"Outline": "Umriss",
|
||||
"Save Current Color": "Aktuelle Farbe speichern",
|
||||
"Quick Colors": "Schnellfarben"
|
||||
"Quick Colors": "Schnellfarben",
|
||||
"Highlighter": "Textmarker"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "Κυματιστό",
|
||||
"Outline": "Περίγραμμα",
|
||||
"Save Current Color": "Αποθήκευση τρέχουσας χρώματος",
|
||||
"Quick Colors": "Γρήγορα χρώματα"
|
||||
"Quick Colors": "Γρήγορα χρώματα",
|
||||
"Highlighter": "Υπογραμμιστής"
|
||||
}
|
||||
|
||||
@@ -647,5 +647,6 @@
|
||||
"Squiggly": "Ondulado",
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Guardar Color Actual",
|
||||
"Quick Colors": "Colores Rápidos"
|
||||
"Quick Colors": "Colores Rápidos",
|
||||
"Highlighter": "Resaltador"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "خطموجدار",
|
||||
"Outline": "خطکشی",
|
||||
"Save Current Color": "ذخیره رنگ فعلی",
|
||||
"Quick Colors": "رنگهای سریع"
|
||||
"Quick Colors": "رنگهای سریع",
|
||||
"Highlighter": "ماژیک هایلایت"
|
||||
}
|
||||
|
||||
@@ -647,5 +647,6 @@
|
||||
"Squiggly": "Ondulé",
|
||||
"Outline": "Contour",
|
||||
"Save Current Color": "Enregistrer la Couleur Actuelle",
|
||||
"Quick Colors": "Couleurs Rapides"
|
||||
"Quick Colors": "Couleurs Rapides",
|
||||
"Highlighter": "Surligneur"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "स्क्विगली",
|
||||
"Outline": "आउटलाइन",
|
||||
"Save Current Color": "वर्तमान रंग सहेजें",
|
||||
"Quick Colors": "त्वरित रंग"
|
||||
"Quick Colors": "त्वरित रंग",
|
||||
"Highlighter": "हाइलाइटर"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "Bergelombang",
|
||||
"Outline": "Garis Besar",
|
||||
"Save Current Color": "Simpan Warna Saat Ini",
|
||||
"Quick Colors": "Warna Cepat"
|
||||
"Quick Colors": "Warna Cepat",
|
||||
"Highlighter": "Penyorot"
|
||||
}
|
||||
|
||||
@@ -647,5 +647,6 @@
|
||||
"Squiggly": "Ondulato",
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Salva Colore Corrente",
|
||||
"Quick Colors": "Colori Veloci"
|
||||
"Quick Colors": "Colori Veloci",
|
||||
"Highlighter": "Evidenziatore"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "波線",
|
||||
"Outline": "アウトライン",
|
||||
"Save Current Color": "現在の色を保存",
|
||||
"Quick Colors": "クイックカラー"
|
||||
"Quick Colors": "クイックカラー",
|
||||
"Highlighter": "蛍光ペン"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "물결선",
|
||||
"Outline": "윤곽선",
|
||||
"Save Current Color": "현재 색상 저장",
|
||||
"Quick Colors": "빠른 색상"
|
||||
"Quick Colors": "빠른 색상",
|
||||
"Highlighter": "형광펜"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "Kronkelig",
|
||||
"Outline": "Omtrek",
|
||||
"Save Current Color": "Huidige kleur opslaan",
|
||||
"Quick Colors": "Snelle kleuren"
|
||||
"Quick Colors": "Snelle kleuren",
|
||||
"Highlighter": "Marker"
|
||||
}
|
||||
|
||||
@@ -651,5 +651,6 @@
|
||||
"Squiggly": "Falista linia",
|
||||
"Outline": "Obrys",
|
||||
"Save Current Color": "Zapisz bieżący kolor",
|
||||
"Quick Colors": "Szybkie kolory"
|
||||
"Quick Colors": "Szybkie kolory",
|
||||
"Highlighter": "Zakreślacz"
|
||||
}
|
||||
|
||||
@@ -647,5 +647,6 @@
|
||||
"Squiggly": "Ondulado",
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Salvar cor atual",
|
||||
"Quick Colors": "Cores rápidas"
|
||||
"Quick Colors": "Cores rápidas",
|
||||
"Highlighter": "Marcador"
|
||||
}
|
||||
|
||||
@@ -651,5 +651,6 @@
|
||||
"Squiggly": "Волнистая линия",
|
||||
"Outline": "Контур",
|
||||
"Save Current Color": "Сохранить текущий цвет",
|
||||
"Quick Colors": "Быстрые цвета"
|
||||
"Quick Colors": "Быстрые цвета",
|
||||
"Highlighter": "Маркер"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "වැලි රේඛාව",
|
||||
"Outline": "පරිසීමාව",
|
||||
"Save Current Color": "දැන් ඇති වර්ණය සුරකින්න",
|
||||
"Quick Colors": "ක්ෂණික වර්ණ"
|
||||
"Quick Colors": "ක්ෂණික වර්ණ",
|
||||
"Highlighter": "ඉස්මතු කරන්නා"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "Vågig linje",
|
||||
"Outline": "Kontur",
|
||||
"Save Current Color": "Spara aktuell färg",
|
||||
"Quick Colors": "Snabba färger"
|
||||
"Quick Colors": "Snabba färger",
|
||||
"Highlighter": "Markeringspenna"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "சுருள் கோடு",
|
||||
"Outline": "வட்டம்",
|
||||
"Save Current Color": "தற்போதைய நிறத்தை சேமிக்கவும்",
|
||||
"Quick Colors": "விரைவு நிறங்கள்"
|
||||
"Quick Colors": "விரைவு நிறங்கள்",
|
||||
"Highlighter": "ஹைலைட்டர்"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "เส้นหยัก",
|
||||
"Outline": "เส้นขอบ",
|
||||
"Save Current Color": "บันทึกสีปัจจุบัน",
|
||||
"Quick Colors": "สีด่วน"
|
||||
"Quick Colors": "สีด่วน",
|
||||
"Highlighter": "ปากกาเน้นข้อความ"
|
||||
}
|
||||
|
||||
@@ -643,5 +643,6 @@
|
||||
"Squiggly": "Dalgalı Çizgi",
|
||||
"Outline": "Kontur",
|
||||
"Save Current Color": "Mevcut Rengi Kaydet",
|
||||
"Quick Colors": "Hızlı Renkler"
|
||||
"Quick Colors": "Hızlı Renkler",
|
||||
"Highlighter": "Vurgulayıcı"
|
||||
}
|
||||
|
||||
@@ -651,5 +651,6 @@
|
||||
"Squiggly": "Хвиляста лінія",
|
||||
"Outline": "Контур",
|
||||
"Save Current Color": "Зберегти поточний колір",
|
||||
"Quick Colors": "Швидкі кольори"
|
||||
"Quick Colors": "Швидкі кольори",
|
||||
"Highlighter": "Маркер"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "Gạch ngoằn ngoèo",
|
||||
"Outline": "Đường viền",
|
||||
"Save Current Color": "Lưu màu hiện tại",
|
||||
"Quick Colors": "Màu nhanh"
|
||||
"Quick Colors": "Màu nhanh",
|
||||
"Highlighter": "Bút đánh dấu"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "波浪线",
|
||||
"Outline": "轮廓",
|
||||
"Save Current Color": "保存当前颜色",
|
||||
"Quick Colors": "快速颜色"
|
||||
"Quick Colors": "快速颜色",
|
||||
"Highlighter": "荧光笔"
|
||||
}
|
||||
|
||||
@@ -639,5 +639,6 @@
|
||||
"Squiggly": "波浪線",
|
||||
"Outline": "輪廓",
|
||||
"Save Current Color": "儲存目前顏色",
|
||||
"Quick Colors": "快速顏色"
|
||||
"Quick Colors": "快速顏色",
|
||||
"Highlighter": "螢光筆"
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { start, cancel, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oau
|
||||
import { openUrl } from '@tauri-apps/plugin-opener';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { handleAuthCallback } from '@/helpers/auth';
|
||||
import { getUserPlan } from '@/utils/access';
|
||||
import { getUserProfilePlan } from '@/utils/access';
|
||||
import { getAppleIdAuth, Scope } from './utils/appleIdAuth';
|
||||
import { authWithCustomTab, authWithSafari } from './utils/nativeAuth';
|
||||
import WindowButtons from '@/components/WindowButtons';
|
||||
@@ -173,7 +173,7 @@ export default function AuthPage() {
|
||||
const type = params.get('type');
|
||||
if (accessToken) {
|
||||
let next = params.get('next') ?? '/';
|
||||
if (getUserPlan(accessToken) === 'free') {
|
||||
if (getUserProfilePlan(accessToken) === 'free') {
|
||||
next = '/user';
|
||||
}
|
||||
handleAuthCallback({ accessToken, refreshToken, type, next, login, navigate: router.push });
|
||||
|
||||
@@ -39,7 +39,7 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
const router = useRouter();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { user } = useAuth();
|
||||
const { userPlan, quotas } = useQuotaStats(true);
|
||||
const { userProfilePlan, quotas } = useQuotaStats(true);
|
||||
const { themeMode, setThemeMode } = useThemeStore();
|
||||
const { settings, setSettingsDialogOpen } = useSettingsStore();
|
||||
const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload);
|
||||
@@ -305,7 +305,7 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
</>
|
||||
)}
|
||||
<hr aria-hidden='true' className='border-base-200 my-1' />
|
||||
{user && userPlan === 'free' && !appService?.isIOSApp && (
|
||||
{user && userProfilePlan === 'free' && (
|
||||
<MenuItem label={_('Upgrade to Readest Premium')} onClick={handleUpgrade} />
|
||||
)}
|
||||
{isWebAppPlatform() && <MenuItem label={_('Download Readest')} onClick={downloadReadest} />}
|
||||
|
||||
@@ -67,7 +67,7 @@ const ProfilePage = () => {
|
||||
|
||||
useTheme({ systemUIVisible: false });
|
||||
|
||||
const { quotas, userPlan = 'free' } = useQuotaStats();
|
||||
const { quotas, userProfilePlan = 'free' } = useQuotaStats();
|
||||
const { handleLogout, handleResetPassword, handleConfirmDelete } = useUserActions();
|
||||
|
||||
const { availablePlans } = useAvailablePlans({
|
||||
@@ -218,8 +218,8 @@ const ProfilePage = () => {
|
||||
const avatarUrl = user?.user_metadata?.['picture'] || user?.user_metadata?.['avatar_url'];
|
||||
const userFullName = user?.user_metadata?.['full_name'] || '-';
|
||||
const userEmail = user?.email || '';
|
||||
const planDetails =
|
||||
getPlanDetails(userPlan, availablePlans) || getPlanDetails('free', availablePlans);
|
||||
const userPlanDetails =
|
||||
getPlanDetails(userProfilePlan, availablePlans) || getPlanDetails('free', availablePlans);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -258,7 +258,7 @@ const ProfilePage = () => {
|
||||
avatarUrl={avatarUrl}
|
||||
userFullName={userFullName}
|
||||
userEmail={userEmail}
|
||||
planDetails={planDetails}
|
||||
planDetails={userPlanDetails}
|
||||
/>
|
||||
|
||||
<UsageStats quotas={quotas} />
|
||||
@@ -267,14 +267,14 @@ const ProfilePage = () => {
|
||||
<div className='flex flex-col gap-y-8 sm:px-6'>
|
||||
<PlansComparison
|
||||
availablePlans={availablePlans}
|
||||
userPlan={userPlan}
|
||||
userPlan={userProfilePlan}
|
||||
onSubscribe={appService.hasIAP ? handleIAPSubscribe : handleStripeSubscribe}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-y-8 px-6'>
|
||||
<AccountActions
|
||||
userPlan={userPlan}
|
||||
userPlan={userProfilePlan}
|
||||
onLogout={handleLogout}
|
||||
onResetPassword={handleResetPassword}
|
||||
onConfirmDelete={handleDeleteWithMessage}
|
||||
|
||||
@@ -61,7 +61,7 @@ const TTSHighlightStyleEditor: React.FC<TTSHighlightStyleEditorProps> = ({
|
||||
value={style}
|
||||
onChange={(e) => onStyleChange(e.target.value as TTSHighlightStyle)}
|
||||
options={[
|
||||
{ value: 'highlight', label: _('Highlight') },
|
||||
{ value: 'highlight', label: _('Highlighter') },
|
||||
{ value: 'underline', label: _('Underline') },
|
||||
{ value: 'strikethrough', label: _('Strikethrough') },
|
||||
{ value: 'squiggly', label: _('Squiggly') },
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import { QuotaType, UserPlan } from '@/types/quota';
|
||||
import { getStoragePlanData, getTranslationPlanData, getUserPlan } from '@/utils/access';
|
||||
import { getStoragePlanData, getTranslationPlanData, getUserProfilePlan } from '@/utils/access';
|
||||
import { useTranslation } from './useTranslation';
|
||||
|
||||
export const useQuotaStats = (briefName = false) => {
|
||||
const _ = useTranslation();
|
||||
const { token, user } = useAuth();
|
||||
const [quotas, setQuotas] = useState<QuotaType[]>([]);
|
||||
const [userPlan, setUserPlan] = useState<UserPlan | undefined>(undefined);
|
||||
const [userProfilePlan, setUserProfilePlan] = useState<UserPlan | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user || !token) return;
|
||||
|
||||
const userPlan = getUserPlan(token);
|
||||
const storagPlan = getStoragePlanData(token);
|
||||
const inGB = storagPlan.quota > 1e9;
|
||||
const storageQuota: QuotaType = {
|
||||
@@ -35,13 +34,13 @@ export const useQuotaStats = (briefName = false) => {
|
||||
total: Math.round(translationPlan.quota / 1024),
|
||||
unit: 'K',
|
||||
};
|
||||
setUserPlan(userPlan);
|
||||
setUserProfilePlan(getUserProfilePlan(token));
|
||||
setQuotas([storageQuota, translationQuota]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [token]);
|
||||
|
||||
return {
|
||||
quotas,
|
||||
userPlan,
|
||||
userProfilePlan,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,7 +2,11 @@ import crypto from 'crypto';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { corsAllMethods, runMiddleware } from '@/utils/cors';
|
||||
import { getCloudflareContext } from '@opennextjs/cloudflare';
|
||||
import { getDailyTranslationPlanData, getUserPlan, validateUserAndToken } from '@/utils/access';
|
||||
import {
|
||||
getDailyTranslationPlanData,
|
||||
getSubscriptionPlan,
|
||||
validateUserAndToken,
|
||||
} from '@/utils/access';
|
||||
import { ErrorCodes } from '@/services/translators';
|
||||
import { UsageStatsManager } from '@/utils/usage';
|
||||
|
||||
@@ -53,7 +57,7 @@ const updateDailyUsage = async (
|
||||
if (!userId || !token) return 0;
|
||||
|
||||
try {
|
||||
const userPlan = getUserPlan(token);
|
||||
const userPlan = getSubscriptionPlan(token);
|
||||
const newUsage = await UsageStatsManager.trackUsage(
|
||||
userId,
|
||||
'translation_chars',
|
||||
@@ -90,7 +94,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
let deeplApiUrl = deepFreeApiUrl;
|
||||
let userPlan = 'free';
|
||||
if (user && token) {
|
||||
userPlan = getUserPlan(token);
|
||||
userPlan = getSubscriptionPlan(token);
|
||||
if (userPlan === 'pro') deeplApiUrl = deeplProApiUrl;
|
||||
}
|
||||
const deeplAuthKey =
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getAPIBaseUrl } from '@/services/environment';
|
||||
import { stubTranslation as _ } from '@/utils/misc';
|
||||
import { ErrorCodes, TranslationProvider } from '../types';
|
||||
import { UserPlan } from '@/types/quota';
|
||||
import { getUserPlan } from '@/utils/access';
|
||||
import { getSubscriptionPlan } from '@/utils/access';
|
||||
import { normalizeToShortLang } from '@/utils/lang';
|
||||
import { DEFAULT_DAILY_TRANSLATION_QUOTA } from '@/services/constants';
|
||||
import { saveDailyUsage } from '../utils';
|
||||
@@ -29,7 +29,7 @@ export const deeplProvider: TranslationProvider = {
|
||||
|
||||
let userPlan: UserPlan = 'free';
|
||||
if (token) {
|
||||
userPlan = getUserPlan(token);
|
||||
userPlan = getSubscriptionPlan(token);
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,23 @@ interface Token {
|
||||
[key: string]: string | number;
|
||||
}
|
||||
|
||||
export const getUserPlan = (token: string): UserPlan => {
|
||||
export const getSubscriptionPlan = (token: string): UserPlan => {
|
||||
const data = jwtDecode<Token>(token) || {};
|
||||
return data['plan'] || 'free';
|
||||
};
|
||||
|
||||
export const getUserProfilePlan = (token: string): UserPlan => {
|
||||
const data = jwtDecode<Token>(token) || {};
|
||||
let plan = data['plan'] || 'free';
|
||||
if (plan === 'free') {
|
||||
const purchasedQuota = data['storage_purchased_bytes'] || 0;
|
||||
if (purchasedQuota > 0) {
|
||||
plan = 'purchase';
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
};
|
||||
|
||||
export const STORAGE_QUOTA_GRACE_BYTES = 10 * 1024 * 1024; // 10 MB grace
|
||||
|
||||
export const getStoragePlanData = (token: string) => {
|
||||
|
||||
Reference in New Issue
Block a user