Files
photo-live/apps/mobile/lib/pages/share_qr_dialog.dart
T
2026-09-19 01:56:38 +08:00

102 lines
3.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// 分享二维码对话框(P3 计划 Task 4)。
///
/// viewer 链接构造:`{VIEWER_BASE}/a/{publicToken}`([ApiConfig.
/// viewerAlbumUrl],VIEWER_BASE 经 --dart-define 覆盖,dev=模拟器宿主
/// 回环 5175)。QrImageView 渲染链接 + 链接文本可长按选中 + 一键复制。
///
/// 用 [Dialog] 而非 [AlertDialog]:AlertDialog 内容经 IntrinsicWidth
/// 测量,而 QrImageView 内部使用 LayoutBuilder(不支持 intrinsic 计算)
/// 会抛布局断言,普通 Dialog 无此路径。
library;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_flutter/qr_flutter.dart';
import '../core/config.dart';
import '../l10n/app_localizations.dart';
/// 观众分享二维码对话框([publicToken] 来自相册详情)。
class ShareQrDialog extends StatelessWidget {
const ShareQrDialog({required this.publicToken, super.key});
final String publicToken;
Future<void> _copy(BuildContext context, String url) async {
await Clipboard.setData(ClipboardData(text: url));
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context).copiedToClipboard),
),
);
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final theme = Theme.of(context);
final url = ApiConfig.viewerAlbumUrl(publicToken);
return Dialog(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
l10n.shareQrTitle,
style: theme.textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Center(
// 白底保证暗色主题下的扫码对比度。
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(8),
child: QrImageView(
data: url,
version: QrVersions.auto,
size: 216,
backgroundColor: Colors.white,
),
),
),
const SizedBox(height: 12),
SelectableText(
url,
textAlign: TextAlign.center,
style: theme.textTheme.bodySmall,
),
const SizedBox(height: 8),
Text(
l10n.qrHint,
textAlign: TextAlign.center,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton.icon(
onPressed: () => _copy(context, url),
icon: const Icon(Icons.copy_outlined),
label: Text(l10n.copyLink),
),
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(l10n.ok),
),
],
),
],
),
),
);
}
}