generated from dellevin/template
首页云备份界面优化一下
This commit is contained in:
@@ -172,7 +172,6 @@ class _GameTabPageState extends State<GameTabPage> {
|
|||||||
final masterContent = Column(
|
final masterContent = Column(
|
||||||
children: [
|
children: [
|
||||||
if (!isWallMode) const GameStatusBar(),
|
if (!isWallMode) const GameStatusBar(),
|
||||||
if (!isWallMode) Divider(height: 0.5, thickness: 0.5, color: colors.outlineVariant),
|
|
||||||
Expanded(child: _buildBody(context)),
|
Expanded(child: _buildBody(context)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ class _MainContentPageState extends State<MainContentPage> {
|
|||||||
void _showCloudSheet(BuildContext context) async {
|
void _showCloudSheet(BuildContext context) async {
|
||||||
final colors = Theme.of(context).colorScheme;
|
final colors = Theme.of(context).colorScheme;
|
||||||
final hasConfig = (await WebDAVService.instance.getConfig()) != null;
|
final hasConfig = (await WebDAVService.instance.getConfig()) != null;
|
||||||
|
Map<String, dynamic>? remoteInfo;
|
||||||
|
if (hasConfig) {
|
||||||
|
remoteInfo = await WebDAVService.instance.getRemoteBackupInfo();
|
||||||
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -171,6 +175,8 @@ class _MainContentPageState extends State<MainContentPage> {
|
|||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
final bc = Theme.of(ctx).colorScheme;
|
final bc = Theme.of(ctx).colorScheme;
|
||||||
|
final modifiedTime = remoteInfo?['modifiedTime'] as DateTime?;
|
||||||
|
final remoteSize = remoteInfo?['size'] as int?;
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 6, 16, 16),
|
padding: const EdgeInsets.fromLTRB(16, 6, 16, 16),
|
||||||
@@ -186,6 +192,25 @@ class _MainContentPageState extends State<MainContentPage> {
|
|||||||
_cloudCard(icon: Icons.cloud_download_outlined, title: '下载数据', desc: hasConfig ? '从云端恢复数据到本地' : '请先配置 WebDAV 服务器', enabled: hasConfig, onTap: hasConfig ? () { Navigator.pop(ctx); _performSync(context, SyncDirection.download); } : null, colors: bc),
|
_cloudCard(icon: Icons.cloud_download_outlined, title: '下载数据', desc: hasConfig ? '从云端恢复数据到本地' : '请先配置 WebDAV 服务器', enabled: hasConfig, onTap: hasConfig ? () { Navigator.pop(ctx); _performSync(context, SyncDirection.download); } : null, colors: bc),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_cloudCard(icon: Icons.settings_outlined, title: 'WebDAV 设置', desc: '配置服务器地址与认证信息', enabled: true, onTap: () { Navigator.pop(ctx); Navigator.push(context, MaterialPageRoute(builder: (_) => const WebDAVSyncPage())); }, colors: bc),
|
_cloudCard(icon: Icons.settings_outlined, title: 'WebDAV 设置', desc: '配置服务器地址与认证信息', enabled: true, onTap: () { Navigator.pop(ctx); Navigator.push(context, MaterialPageRoute(builder: (_) => const WebDAVSyncPage())); }, colors: bc),
|
||||||
|
if (modifiedTime != null || remoteSize != null) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: bc.surfaceContainerHighest,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(children: [
|
||||||
|
Icon(Icons.info_outline, size: 14, color: bc.onSurface.withValues(alpha: 0.3)),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text('云端备份', style: TextStyle(fontSize: 11, color: bc.onSurface.withValues(alpha: 0.4))),
|
||||||
|
const Spacer(),
|
||||||
|
if (modifiedTime != null) Text(_formatDateTime(modifiedTime), style: TextStyle(fontSize: 11, color: bc.onSurface.withValues(alpha: 0.5))),
|
||||||
|
if (modifiedTime != null && remoteSize != null) Text(' · ', style: TextStyle(fontSize: 11, color: bc.onSurface.withValues(alpha: 0.2))),
|
||||||
|
if (remoteSize != null) Text(_formatFileSize(remoteSize), style: TextStyle(fontSize: 11, color: bc.onSurface.withValues(alpha: 0.5))),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
],
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -193,6 +218,22 @@ class _MainContentPageState extends State<MainContentPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _formatDateTime(DateTime dt) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final diff = now.difference(dt);
|
||||||
|
if (diff.inMinutes < 1) return '刚刚';
|
||||||
|
if (diff.inHours < 1) return '${diff.inMinutes}分钟前';
|
||||||
|
if (diff.inDays < 1) return '${diff.inHours}小时前';
|
||||||
|
if (diff.inDays < 7) return '${diff.inDays}天前';
|
||||||
|
return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}';
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatFileSize(int bytes) {
|
||||||
|
if (bytes < 1024) return '$bytes B';
|
||||||
|
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
|
||||||
|
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
|
||||||
|
}
|
||||||
|
|
||||||
Widget _cloudCard({required IconData icon, required String title, required String desc, required bool enabled, required VoidCallback? onTap, required ColorScheme colors}) {
|
Widget _cloudCard({required IconData icon, required String title, required String desc, required bool enabled, required VoidCallback? onTap, required ColorScheme colors}) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ class _MovieTabPageState extends State<MovieTabPage> {
|
|||||||
final masterContent = Column(
|
final masterContent = Column(
|
||||||
children: [
|
children: [
|
||||||
if (!isWallMode) const MovieStatusBar(),
|
if (!isWallMode) const MovieStatusBar(),
|
||||||
if (!isWallMode) Divider(height: 0.5, thickness: 0.5, color: colors.outlineVariant),
|
|
||||||
Expanded(child: _buildBody(context)),
|
Expanded(child: _buildBody(context)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class BookStatusBar extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: colors.surface,
|
color: colors.surface,
|
||||||
border: Border(bottom: BorderSide(color: colors.outline, width: 0.5)),
|
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class GameStatusBar extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: colors.surface,
|
color: colors.surface,
|
||||||
border: Border(bottom: BorderSide(color: colors.outline, width: 0.5)),
|
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class MovieStatusBar extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: colors.surface,
|
color: colors.surface,
|
||||||
border: Border(bottom: BorderSide(color: colors.outline, width: 0.5)),
|
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
|
|||||||
Reference in New Issue
Block a user