Files
CloudHome-Ops/lib/providers/display_provider.dart

98 lines
3.2 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// 显示方向偏好:跟随系统 / 竖屏 / 横屏。
///
/// 与主题、语言并列,作为「我的」页可手动切换的显示设置;切换后通过
/// [SystemChrome.setPreferredOrientations] 实时生效,并重渲染界面(横屏沿用
/// NavigationRail 布局,竖屏沿用 NavigationBar 布局,二者共用同一套橙白主题,
/// 视觉风格保持一致)。
enum DisplayOrientation {
/// 跟随系统(默认):允许全部四个方向,由设备物理朝向决定。
system,
/// 仅竖屏。
portrait,
/// 仅横屏。
landscape,
}
const String _kDisplayOrientation = 'display_orientation';
/// 将偏好映射为 [SystemChrome] 需要的设备方向列表。
List<DeviceOrientation> deviceOrientationsFor(DisplayOrientation mode) {
switch (mode) {
case DisplayOrientation.portrait:
return const [DeviceOrientation.portraitUp];
case DisplayOrientation.landscape:
return const [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight];
case DisplayOrientation.system:
return const [
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
];
}
}
/// 立即应用显示方向(调用 [SystemChrome.setPreferredOrientations])。
void applyDisplayOrientation(DisplayOrientation mode) {
SystemChrome.setPreferredOrientations(deviceOrientationsFor(mode));
}
/// 从持久化读取已保存偏好;异常或无记录时返回 [DisplayOrientation.system]。
Future<DisplayOrientation> loadSavedOrientation() async {
try {
final prefs = await SharedPreferences.getInstance();
final v = prefs.getString(_kDisplayOrientation);
if (v != null) {
for (final e in DisplayOrientation.values) {
if (e.name == v) return e;
}
}
} catch (_) {
// 忽略:SharedPreferences 不可用时退化为系统。
}
return DisplayOrientation.system;
}
/// 显示方向偏好管理(持久化 + 实时生效)。
class DisplayOrientationNotifier extends Notifier<DisplayOrientation> {
@override
DisplayOrientation build() {
// 首选项在 main 启动期已应用;这里异步回读以保证 UI 选中态与持久值一致。
_load();
return DisplayOrientation.system;
}
Future<void> _load() async {
final saved = await loadSavedOrientation();
if (saved != state) {
state = saved;
applyDisplayOrientation(saved);
}
}
/// 切换显示方向:更新状态、即时生效并持久化。
Future<void> set(DisplayOrientation mode) async {
state = mode;
applyDisplayOrientation(mode);
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_kDisplayOrientation, mode.name);
} catch (_) {
// 忽略持久化失败,运行时仍生效。
}
}
}
/// 显示方向偏好提供者。
final displayOrientationProvider =
NotifierProvider<DisplayOrientationNotifier, DisplayOrientation>(
DisplayOrientationNotifier.new,
);