Files
xianyan/lib/shared/auth_aware_mixin.dart
Developer f91be94e9c refactor: 完成项目架构重构,统一模块导入路径
- 清理大量废弃的 barrel 导出文件,移除冗余的中间导出层
- 修复所有相对路径导入错误,统一调整为扁平化模块引用
- 更新多平台 pubspec 版本号与依赖库版本
- 补充后端功能问题管理后台与脚本工具
- 调整部分页面的快捷方式文案适配新功能
- 更新部分翻译覆盖率与API文档
2026-06-12 08:53:57 +08:00

107 lines
3.7 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.
/// ============================================================
/// 闲言APP — 认证感知Mixin
/// 创建时间: 2026-05-28
/// 更新时间: 2026-06-12
/// 作用: 统一401认证错误处理监听auth状态变化自动重载数据
/// 上次更新: 从 mixins/ 子目录上移至 shared/ 目录
/// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:xianyan/core/theme/app_theme.dart';
import 'package:xianyan/core/theme/app_spacing.dart';
import 'package:xianyan/core/theme/app_typography.dart';
import 'package:xianyan/core/theme/app_radius.dart';
import 'package:xianyan/core/providers/auth_state.dart';
import 'package:xianyan/core/router/app_nav_extension.dart';
import 'package:xianyan/core/router/app_routes.dart';
mixin AuthAwareMixin<T extends ConsumerStatefulWidget> on ConsumerState<T> {
bool _authInitialized = false;
ProviderSubscription<AuthState>? _authSubscription;
/// 子类重写此方法,在登录状态变化时重新加载数据
void onAuthChanged(bool isLoggedIn);
/// 构建认证错误引导界面
Widget buildAuthErrorView({
String title = '需要登录查看',
String subtitle = '登录后即可查看专属内容',
String actionLabel = '登录',
}) {
final ext = AppTheme.ext(context);
return Center(
child: Padding(
padding: const EdgeInsets.all(AppSpacing.xl),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 64,
height: 64,
decoration: BoxDecoration(
color: ext.accent.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(20),
),
child: const Center(
child: Text('🔒', style: TextStyle(fontSize: 28)),
),
),
const SizedBox(height: AppSpacing.md),
Text(
title,
style: AppTypography.title3.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: AppSpacing.xs),
Text(
subtitle,
style: AppTypography.subhead.copyWith(color: ext.textSecondary),
textAlign: TextAlign.center,
),
const SizedBox(height: AppSpacing.lg),
SizedBox(
width: 200,
child: CupertinoButton(
color: ext.accent,
borderRadius: AppRadius.lgBorder,
padding: const EdgeInsets.symmetric(vertical: AppSpacing.sm),
onPressed: () => context.appPush(AppRoutes.login),
child: Text(
actionLabel,
style: AppTypography.subhead.copyWith(
color: ext.textInverse,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
),
);
}
/// 自动关闭认证监听器子类dispose时无需手动调用
/// 若子类也override dispose必须调用super.dispose()
@override
void dispose() {
_authSubscription?.close();
_authSubscription = null;
super.dispose();
}
/// 初始化认证监听应在initState的addPostFrameCallback中调用
void initAuthListener() {
if (_authInitialized) return;
_authInitialized = true;
_authSubscription = ref.listenManual(authStateProvider, (prev, next) {
if (prev?.isLoggedIn != next.isLoggedIn) {
onAuthChanged(next.isLoggedIn);
}
}, fireImmediately: false);
}
}