Files
xianyan/lib/core/providers/split_view_provider.dart
Developer adfa0af825 chore: 汇总2026-05-30全量更新
### 详细变更:
1.  **文档与配置**:更新AGENTS.md添加命令超时约束,升级Rive依赖至0.14.7并替换平台插件引用
2.  **UI优化**:重构AppInfo页面布局、移除图表冗余配置、锁定部分系统设置项
3.  **功能增强**:
    - 新增工具面板拖拽状态管理与介绍弹窗
    - 新增进度页面编辑/重排/清空用户进度功能
    - 新增摇一摇路由作用域拦截逻辑
4.  **体验优化**:
    - 统一外部链接跳转弹窗,添加文件打开确认逻辑
    - 修复设备卡片IP溢出、Android权限声明问题
    - 后台任务初始化增加协议校验
5.  **代码重构**:拆分工具面板配置、拖拽逻辑与动画参数,优化状态管理代码
6.  **工具脚本**:新增协议文件上传脚本
2026-05-30 05:29:50 +08:00

167 lines
5.0 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 — 宽屏分屏状态管理
/// 创建时间: 2026-05-29
/// 更新时间: 2026-05-29
/// 作用: 管理分屏比例、右侧面板内容、导航栏位置、分屏开关
/// 上次更新: 新增三栏布局状态(thirdPanelContent/thirdPanelArgs/setThirdPanel)
/// ============================================================
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:xianyan/core/storage/kv_storage.dart';
part 'split_view_provider.freezed.dart';
/// 导航栏停靠位置
enum NavBarPosition {
left,
right,
top,
bottom;
String get label => switch (this) {
left => '左侧',
right => '右侧',
top => '顶部',
bottom => '底部',
};
String get emoji => switch (this) {
left => '⬅️',
right => '➡️',
top => '⬆️',
bottom => '⬇️',
};
}
/// 分屏比例选项
class SplitRatioOption {
const SplitRatioOption(this.value, this.label);
final double value;
final String label;
static const List<SplitRatioOption> options = [
SplitRatioOption(0.30, '30:70'),
SplitRatioOption(0.35, '35:65'),
SplitRatioOption(0.40, '40:60'),
SplitRatioOption(0.45, '45:55'),
SplitRatioOption(0.50, '50:50'),
SplitRatioOption(0.55, '55:45'),
SplitRatioOption(0.60, '60:40'),
];
static SplitRatioOption? findByValue(double v) =>
options.where((o) => o.value == v).firstOrNull;
static int indexOfValue(double v) {
final idx = options.indexWhere((o) => o.value == v);
return idx >= 0 ? idx : 2;
}
}
const String _kSplitRatio = 'split_view_ratio';
const String _kNavBarPosition = 'nav_bar_position';
const String _kSplitViewEnabled = 'split_view_enabled';
/// 三栏布局断点:宽度 >= 1400px 进入三栏模式
const double kTripleColumnBreakpoint = 1400.0;
/// 分屏视图状态freezed不可变数据类
@freezed
sealed class SplitViewState with _$SplitViewState {
const SplitViewState._();
const factory SplitViewState({
@Default(0.4) double splitRatio,
String? rightPanelContent,
Map<String, dynamic>? rightPanelArgs,
@Default(NavBarPosition.left) NavBarPosition navBarPosition,
@Default(true) bool splitViewEnabled,
String? homeRightPanel,
String? discoverRightPanel,
String? profileRightPanel,
@Default(0) int currentTab,
String? thirdPanelContent,
Map<String, dynamic>? thirdPanelArgs,
}) = _SplitViewState;
String? get activeRightPanel => switch (currentTab) {
0 => homeRightPanel,
1 => discoverRightPanel,
2 => profileRightPanel,
_ => null,
};
}
/// 分屏视图状态管理Notifier
class SplitViewNotifier extends Notifier<SplitViewState> {
@override
SplitViewState build() {
final savedIndex = KvStorage.getInt(_kNavBarPosition) ?? 0;
const positions = NavBarPosition.values;
return SplitViewState(
splitRatio: KvStorage.getDouble(_kSplitRatio) ?? 0.4,
navBarPosition: (savedIndex >= 0 && savedIndex < positions.length)
? positions[savedIndex]
: NavBarPosition.left,
splitViewEnabled: KvStorage.getBool(_kSplitViewEnabled) ?? true,
);
}
void setSplitRatio(double value) {
KvStorage.setDouble(_kSplitRatio, value);
state = state.copyWith(splitRatio: value);
}
void setRightPanelContent(String? content, {Map<String, dynamic>? args}) {
state = state.copyWith(rightPanelContent: content, rightPanelArgs: args);
}
void setNavBarPosition(NavBarPosition position) {
KvStorage.setInt(_kNavBarPosition, position.index);
state = state.copyWith(navBarPosition: position);
}
void setSplitViewEnabled(bool enabled) {
KvStorage.setBool(_kSplitViewEnabled, enabled);
state = state.copyWith(splitViewEnabled: enabled);
}
void setHomeRightPanel(String? panelId, {Map<String, dynamic>? args}) {
state = state.copyWith(homeRightPanel: panelId, rightPanelArgs: args);
}
void setDiscoverRightPanel(String? panelId, {Map<String, dynamic>? args}) {
state = state.copyWith(discoverRightPanel: panelId, rightPanelArgs: args);
}
void setProfileRightPanel(String? panelId, {Map<String, dynamic>? args}) {
state = state.copyWith(profileRightPanel: panelId, rightPanelArgs: args);
}
void setCurrentTab(int index) {
state = state.copyWith(currentTab: index);
}
/// 设置第三栏面板内容
void setThirdPanel(String? panelId, {Map<String, dynamic>? args}) {
state = state.copyWith(thirdPanelContent: panelId, thirdPanelArgs: args);
}
void clearActivePanel() {
final tab = state.currentTab;
switch (tab) {
case 0:
state = state.copyWith(homeRightPanel: null);
case 1:
state = state.copyWith(discoverRightPanel: null);
case 2:
state = state.copyWith(profileRightPanel: null);
}
}
}
/// 分屏视图Provider
final splitViewProvider = NotifierProvider<SplitViewNotifier, SplitViewState>(
SplitViewNotifier.new,
);