332 lines
9.7 KiB
Dart
332 lines
9.7 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
import '../core/constants/app_constants.dart';
|
||
import '../core/theme/app_theme.dart';
|
||
import '../core/utils/logger.dart';
|
||
import 'providers/share_provider.dart';
|
||
import 'widgets/share_test_widget.dart';
|
||
import 'widgets/save_dialog.dart';
|
||
|
||
/// 主应用组件
|
||
/// 负责配置MaterialApp和全局设置
|
||
class AppWidget extends ConsumerWidget {
|
||
const AppWidget({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context, WidgetRef ref) {
|
||
Logger.debug('构建AppWidget');
|
||
|
||
return MaterialApp(
|
||
// 应用基础配置
|
||
title: AppConstants.appName,
|
||
debugShowCheckedModeBanner: false,
|
||
|
||
// 主题配置
|
||
theme: AppTheme.lightTheme,
|
||
darkTheme: AppTheme.darkTheme,
|
||
themeMode: ThemeMode.system,
|
||
|
||
// 本地化配置
|
||
localizationsDelegates: const [
|
||
GlobalMaterialLocalizations.delegate,
|
||
GlobalWidgetsLocalizations.delegate,
|
||
GlobalCupertinoLocalizations.delegate,
|
||
],
|
||
supportedLocales: const [
|
||
Locale('zh', 'CN'), // 简体中文
|
||
Locale('zh', 'TW'), // 繁体中文
|
||
Locale('en', 'US'), // English
|
||
],
|
||
|
||
// 主页配置
|
||
home: const AppHomePage(),
|
||
|
||
// 导航观察者
|
||
navigatorObservers: [
|
||
_AppNavigatorObserver(),
|
||
],
|
||
|
||
// 构建器配置(用于全局错误处理)
|
||
builder: (context, child) {
|
||
// 配置文字缩放因子,确保文字大小一致性
|
||
final mediaQueryData = MediaQuery.of(context);
|
||
final textScaler = MediaQuery.of(context).textScaler;
|
||
final scaleFactor = textScaler.scale(1.0).clamp(0.8, 1.2);
|
||
|
||
return MediaQuery(
|
||
data: mediaQueryData.copyWith(
|
||
textScaler: TextScaler.linear(scaleFactor),
|
||
),
|
||
child: child ?? const SizedBox.shrink(),
|
||
);
|
||
},
|
||
|
||
// 滚动行为配置
|
||
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
||
physics: const ClampingScrollPhysics(),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 应用主页组件
|
||
/// 作为占位符,后续会替换为实际的主页
|
||
class AppHomePage extends ConsumerStatefulWidget {
|
||
const AppHomePage({super.key});
|
||
|
||
@override
|
||
ConsumerState<AppHomePage> createState() => _AppHomePageState();
|
||
}
|
||
|
||
class _AppHomePageState extends ConsumerState<AppHomePage> {
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
Logger.debug('AppHomePage初始化');
|
||
|
||
// 初始化分享接收功能
|
||
_initializeShareReceiving();
|
||
}
|
||
|
||
/// 初始化分享接收功能
|
||
void _initializeShareReceiving() {
|
||
try {
|
||
Logger.info('开始初始化分享接收功能...');
|
||
|
||
// 延迟执行,避免在widget构建期间修改provider
|
||
Future.delayed(Duration.zero, () {
|
||
// 获取分享提供者并初始化分享接收
|
||
final shareNotifier = ref.read(shareProvider.notifier);
|
||
shareNotifier.refreshShareStatus();
|
||
});
|
||
|
||
Logger.info('分享接收功能初始化完成');
|
||
} catch (e) {
|
||
Logger.error('初始化分享接收功能失败', error: e);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final theme = Theme.of(context);
|
||
final shareState = ref.watch(shareProvider);
|
||
|
||
Logger.debug('构建AppHomePage, 分享状态: showShareUI=${shareState.showShareUI}, 文件数量=${shareState.pendingFiles.length}');
|
||
|
||
// 如果有错误,打印错误信息
|
||
if (shareState.error != null) {
|
||
Logger.error('分享状态错误: ${shareState.error}');
|
||
}
|
||
|
||
return Scaffold(
|
||
appBar: AppBar(
|
||
title: const Text('想拍'),
|
||
centerTitle: true,
|
||
elevation: 0,
|
||
),
|
||
body: Stack(
|
||
children: [
|
||
// 主页面内容
|
||
Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
// 应用Logo(占位符)
|
||
Icon(
|
||
Icons.photo_library,
|
||
size: 120,
|
||
color: theme.colorScheme.primary.withOpacity(0.8),
|
||
),
|
||
const SizedBox(height: 32),
|
||
|
||
// 欢迎文字
|
||
Text(
|
||
'欢迎使用想拍',
|
||
style: theme.textTheme.headlineMedium?.copyWith(
|
||
color: theme.colorScheme.onSurface,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 16),
|
||
|
||
// 副标题
|
||
Text(
|
||
'Shoot What Inspires You',
|
||
style: theme.textTheme.bodyLarge?.copyWith(
|
||
color: theme.colorScheme.onSurface.withOpacity(0.7),
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 48),
|
||
|
||
// 功能说明
|
||
Text(
|
||
'从其他应用分享图片到这里,\n开始收集你的灵感吧!',
|
||
style: theme.textTheme.bodyMedium?.copyWith(
|
||
color: theme.colorScheme.onSurface.withOpacity(0.6),
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 32),
|
||
|
||
// 分享测试组件
|
||
const ShareTestWidget(),
|
||
const SizedBox(height: 32),
|
||
|
||
// 开始使用按钮
|
||
ElevatedButton.icon(
|
||
onPressed: () {
|
||
// TODO: 导航到图库页面
|
||
Logger.debug('点击开始使用按钮');
|
||
},
|
||
icon: const Icon(Icons.arrow_forward),
|
||
label: const Text('开始使用'),
|
||
style: ElevatedButton.styleFrom(
|
||
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(25),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
|
||
// 分享保存对话框
|
||
if (shareState.showShareUI && shareState.pendingFiles.isNotEmpty)
|
||
SaveDialog(
|
||
sharedFiles: shareState.pendingFiles,
|
||
onClose: () {
|
||
// 关闭分享界面并清除待处理文件
|
||
ref.read(shareProvider.notifier).clearPendingFiles();
|
||
},
|
||
),
|
||
],
|
||
),
|
||
|
||
// 底部导航栏(占位符)
|
||
bottomNavigationBar: NavigationBar(
|
||
destinations: const [
|
||
NavigationDestination(
|
||
icon: Icon(Icons.photo_library),
|
||
label: '图库',
|
||
),
|
||
NavigationDestination(
|
||
icon: Icon(Icons.folder),
|
||
label: '文件夹',
|
||
),
|
||
NavigationDestination(
|
||
icon: Icon(Icons.label),
|
||
label: '标签',
|
||
),
|
||
NavigationDestination(
|
||
icon: Icon(Icons.settings),
|
||
label: '设置',
|
||
),
|
||
],
|
||
onDestinationSelected: (index) {
|
||
Logger.debug('底部导航选择: $index');
|
||
// TODO: 实现页面切换逻辑
|
||
},
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 导航观察者
|
||
/// 用于记录页面导航事件
|
||
class _AppNavigatorObserver extends NavigatorObserver {
|
||
@override
|
||
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
||
if (route.settings.name != null) {
|
||
Logger.debug('页面进入: ${route.settings.name}');
|
||
}
|
||
}
|
||
|
||
@override
|
||
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
||
if (route.settings.name != null) {
|
||
Logger.debug('页面退出: ${route.settings.name}');
|
||
}
|
||
}
|
||
|
||
@override
|
||
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
||
if (route.settings.name != null) {
|
||
Logger.debug('页面移除: ${route.settings.name}');
|
||
}
|
||
}
|
||
|
||
@override
|
||
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
|
||
if (newRoute?.settings.name != null) {
|
||
Logger.debug('页面替换: ${newRoute!.settings.name}');
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 应用配置混入
|
||
mixin AppConfigMixin {
|
||
/// 获取应用名称
|
||
String get appName => AppConstants.appName;
|
||
|
||
/// 获取应用版本
|
||
String get appVersion => AppConstants.appVersion;
|
||
|
||
/// 获取应用描述
|
||
String get appDescription => AppConstants.appDescription;
|
||
|
||
/// 检查是否为调试模式
|
||
bool get isDebugMode => kDebugMode;
|
||
|
||
/// 检查是否为发布模式
|
||
bool get isReleaseMode => kReleaseMode;
|
||
|
||
/// 获取当前时间戳
|
||
int get currentTimestamp => DateTime.now().millisecondsSinceEpoch;
|
||
|
||
/// 格式化文件大小
|
||
String formatFileSize(int bytes) {
|
||
if (bytes <= 0) return '0 B';
|
||
|
||
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||
int unitIndex = 0;
|
||
double size = bytes.toDouble();
|
||
|
||
while (size >= 1024 && unitIndex < units.length - 1) {
|
||
size /= 1024;
|
||
unitIndex++;
|
||
}
|
||
|
||
return '${size.toStringAsFixed(2)} ${units[unitIndex]}';
|
||
}
|
||
|
||
/// 格式化日期
|
||
String formatDate(DateTime date) {
|
||
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||
}
|
||
|
||
/// 计算时间差(友好显示)
|
||
String formatTimeDifference(DateTime from, DateTime to) {
|
||
final difference = to.difference(from);
|
||
|
||
if (difference.inDays > 0) {
|
||
return '${difference.inDays}天前';
|
||
} else if (difference.inHours > 0) {
|
||
return '${difference.inHours}小时前';
|
||
} else if (difference.inMinutes > 0) {
|
||
return '${difference.inMinutes}分钟前';
|
||
} else {
|
||
return '刚刚';
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 应用混入
|
||
/// 组合所有应用相关的混入
|
||
mixin AppMixin on AppConfigMixin, LoggerMixin {
|
||
// 可以在这里添加更多通用的应用功能
|
||
} |