This commit is contained in:
imeepos 2025-11-12 16:55:02 +08:00
parent 12a1df8481
commit 293e7a8427
7 changed files with 64 additions and 17 deletions

View File

@ -1,19 +1,19 @@
import { PageLayout } from '@/components/bestai/layout';
import { getTemplateGenerations, TemplateGeneration } from '@/lib/api/template-generations';
import { router } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
ActivityIndicator,
Image,
Platform,
RefreshControl,
ScrollView,
StyleSheet,
Text,
View,
RefreshControl,
Platform,
TouchableOpacity
TouchableOpacity,
View
} from 'react-native';
import { getTemplateGenerations, TemplateGeneration } from '@/lib/api/template-generations';
import { router } from 'expo-router';
const LAYOUT_CONFIG = {
VIDEO_HEIGHT: 280,
@ -392,8 +392,8 @@ export default function HistoryScreen() {
const styles = StyleSheet.create({
scrollContent: {
paddingTop: 24,
paddingBottom: 48,
paddingTop: 14,
paddingBottom: 14,
},
heading: {
fontSize: 24,

View File

@ -5,7 +5,6 @@ import { useRouter } from 'expo-router';
import React, { useCallback, useMemo, useState } from 'react';
import {
ActivityIndicator,
Alert,
ScrollView,
StyleSheet,
Text,
@ -14,6 +13,7 @@ import {
View
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Alert } from '@/utils/alert';
type PurchaseTab = 'subscription' | 'pack';

View File

@ -19,7 +19,8 @@ export const Header = memo(function Header({ title = 'BESTAI' }: HeaderProps) {
const styles = StyleSheet.create({
container: {
alignItems: 'center',
marginBottom: 28,
marginBottom: 14,
marginTop: 14
},
logo: {
width: 89,

View File

@ -130,7 +130,8 @@ const styles = {
flexDirection: 'row' as const,
alignItems: 'center' as const,
justifyContent: 'space-between' as const,
marginBottom: 28,
marginBottom: 14,
marginTop: 14
},
settingsButton: {
width: 44,

View File

@ -1,13 +1,14 @@
import React, { useState, useMemo } from 'react';
import { View, useWindowDimensions, type ImageSourcePropType, StyleSheet } from 'react-native';
import React, { useMemo, useState } from 'react';
import { StyleSheet, View, useWindowDimensions, type ImageSourcePropType } from 'react-native';
import { PageLayout } from '@/components/bestai/layout';
import { useAuth } from '@/hooks/use-auth';
import { useBalance } from '@/hooks/use-balance';
import { useProfileData } from '@/hooks/use-profile-data';
import { createStats, deriveAvatarSource, deriveDisplayName } from '@/utils/profile-data';
import { PROFILE_THEME } from '@/theme/profile';
import { createStats, deriveAvatarSource, deriveDisplayName } from '@/utils/profile-data';
import { ContentGallery } from './content-gallery';
import { ContentSkeleton } from './content-skeleton';
import { ContentTabs } from './content-tabs';
import { Divider } from './divider';
import { ProfileEditModal } from './profile-edit-modal';
@ -16,7 +17,6 @@ import { ProfileErrorState } from './profile-error-state';
import { ProfileHeader } from './profile-header';
import { ProfileIdentity } from './profile-identity';
import { ProfileLoadingState } from './profile-loading-state';
import { ContentSkeleton } from './content-skeleton';
type TabKey = 'all' | 'image' | 'video';
type BillingMode = 'monthly' | 'lifetime';

View File

@ -1,8 +1,9 @@
import { useState, useEffect, useRef, useMemo } from 'react';
import { Alert, Linking } from 'react-native';
import { Linking } from 'react-native';
import { useRouter } from 'expo-router';
import { authClient, useSession } from '@/lib/auth/client';
import { getStripePlans, getPlanNames } from '@/lib/api/pricing';
import { Alert } from '@/utils/alert';
import type {
StripePricingTableResponse,
CreditPlan,

44
utils/alert.ts Normal file
View File

@ -0,0 +1,44 @@
import { Alert as RNAlert, Platform } from 'react-native';
interface AlertButton {
text: string;
onPress?: () => void;
style?: 'default' | 'cancel' | 'destructive';
}
class PlatformAlert {
alert(title: string, message?: string, buttons?: AlertButton[]) {
if (Platform.OS === 'web') {
this.webAlert(title, message, buttons);
} else {
RNAlert.alert(title, message, buttons);
}
}
private webAlert(title: string, message?: string, buttons?: AlertButton[]) {
const fullMessage = message ? `${title}\n\n${message}` : title;
if (!buttons || buttons.length === 0) {
window.alert(fullMessage);
return;
}
if (buttons.length === 1) {
window.alert(fullMessage);
buttons[0].onPress?.();
return;
}
const confirmed = window.confirm(fullMessage);
if (confirmed) {
const confirmButton = buttons.find(btn => btn.style !== 'cancel');
confirmButton?.onPress?.();
} else {
const cancelButton = buttons.find(btn => btn.style === 'cancel');
cancelButton?.onPress?.();
}
}
}
export const Alert = new PlatformAlert();