// app_providers.dart — 语言 / 主题 / 套餐视角等基础状态(Riverpod) import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../l10n/app_text.dart'; import '../l10n/strings_en.dart'; import '../l10n/strings_zh.dart'; import 'account_providers.dart'; import 'auth_provider.dart'; /// 当前语言(单显)。设置/账户页段控切换。 final localeProvider = StateProvider((ref) => AppLang.zh); /// 由语言派生的文案资源——UI 一律通过它取文案,不写死字面量。 final appTextProvider = Provider((ref) { final lang = ref.watch(localeProvider); return lang == AppLang.zh ? const StringsZh() : const StringsEn(); }); /// 主题模式。默认跟随系统;设置页可显式切深色。 final themeModeProvider = StateProvider((ref) => ThemeMode.system); /// 是否免费档——派生自真实账户(meProvider.plan == 'free')。 /// 免费版才显示额度卡与免费横幅;加载中默认按免费处理。 final isFreePlanProvider = Provider((ref) { final me = ref.watch(meProvider).valueOrNull; return me?.isFree ?? true; }); /// 账户状态是否还没就绪——连接页据此先转圈再渲染,避免「先闪免费广告再跳会员」。 /// 覆盖两段窗口:① auth 还在从存储读 token(此时 isLoggedIn=false,me 会同步返回 /// 免费默认,故必须看 auth.isLoading);② 已登录但 me 还在拉真实值(此时 me 可能已有 /// 过期免费默认值,故看 me.isLoading 而非 !hasValue)。未登录(确定访客)不转圈。 final meLoadingProvider = Provider((ref) { final auth = ref.watch(authProvider); if (auth.isLoading) return true; if (!auth.isLoggedIn) return false; return ref.watch(meProvider).isLoading; });