Files
xianyan/lib/core/router/editor_router.dart
Developer 5a083bdbab feat: 新增多模块后端管理、数据同步工具与鸿蒙路由适配
本次提交新增了以下核心内容:
1. 后端管理模块:包含字体同步、插件元数据、插件用户设置、稍后读消息/共享列表的控制器、模型、验证器与多语言配置
2. Flutter数据同步模块:统一的事件总线与兼容层,替代分散的StreamController
3. 鸿蒙端路由适配:完整的路由定义、构建器与占位组件
4. 后端API接口:字体同步与插件更新的服务端API,支持自动建表与跨域请求
5. 鸿蒙权限校验脚本:用于校验module.json5与string.json的权限声明一致性
2026-06-01 05:50:13 +08:00

170 lines
4.3 KiB
Dart
Raw Permalink 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-04-25
// 更新时间: 2026-06-18
// 作用: 统一管理编辑器内所有页面跳转和弹窗,基于 go_router + Navigator
// 上次更新: 重构为从 route_registry 统一生成 GoRoute保留 EditorNav 扩展
// ============================================================
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:xianyan/editor/services/core/model_catalog_service.dart';
import 'app_routes.dart';
import 'route_def.dart';
import 'route_builders.dart';
class EditorRoutes {
EditorRoutes._();
static const String imagePreview = '/editor/preview';
static const String imageCrop = '/editor/crop';
static const String draftList = '/editor/drafts';
static const String imageGallery = '/editor/gallery';
static const String model3dPreview = '/editor/3d-preview';
}
List<GoRoute> buildEditorRoutes(GlobalKey<NavigatorState> rootNavigatorKey) =>
buildModuleGoRoutes(RouteModule.editor, rootNavigatorKey);
extension EditorNav on BuildContext {
void goToImagePreview({
required ImageProvider provider,
required String heroTag,
}) {
push(
Uri(
path: EditorRoutes.imagePreview,
queryParameters: {'heroTag': heroTag},
).toString(),
extra: ImagePreviewExtra(provider: provider),
);
}
void goToImagePreviewBytes(Uint8List bytes) {
push(
Uri(path: EditorRoutes.imagePreview).toString(),
extra: ImagePreviewExtra(bytes: bytes),
);
}
Future<Uint8List?> goToImageCrop(Uint8List bytes) async {
final result = await push<Uint8List>(
Uri(path: EditorRoutes.imageCrop).toString(),
extra: ImageCropExtra(bytes: bytes),
);
return result;
}
void goToDraftList() {
push(EditorRoutes.draftList);
}
void goToModel3DPreview(Model3DItem model) {
push(Uri(path: EditorRoutes.model3dPreview).toString(), extra: model);
}
void goToImageGallery({
required List<ImageProvider> images,
int initialIndex = 0,
}) {
push(
Uri(path: EditorRoutes.imageGallery).toString(),
extra: ImageGalleryExtra(images: images, initialIndex: initialIndex),
);
}
void replaceWithEditor(Uint8List bytes, {String? initialText}) {
pushReplacement(
Uri(
path: AppRoutes.editor,
queryParameters: {if (initialText != null) 'text': initialText},
).toString(),
extra: EditorReplaceExtra(bytes: bytes),
);
}
}
Future<T?> showEditorDialog<T>({
required BuildContext context,
required String title,
required Widget content,
required List<CupertinoDialogAction> actions,
}) {
return showCupertinoDialog<T>(
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(title),
content: content,
actions: actions,
),
);
}
Future<String?> showEditorChoice({
required BuildContext context,
required String title,
required String message,
required List<(String label, String value)> choices,
String cancelLabel = '取消',
}) {
return showCupertinoDialog<String>(
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(title),
content: Text(message),
actions: [
...choices.map(
(c) => CupertinoDialogAction(
child: Text(c.$1),
onPressed: () => context.pop(c.$2),
),
),
CupertinoDialogAction(
isDestructiveAction: true,
child: Text(cancelLabel),
onPressed: () => context.pop(),
),
],
),
);
}
Future<T?> showEditorModalPopup<T>({
required BuildContext context,
required WidgetBuilder builder,
}) {
return showCupertinoModalPopup<T>(
context: context,
builder: (modalContext) => builder(modalContext),
);
}
class ImagePreviewExtra {
final ImageProvider? provider;
final Uint8List? bytes;
ImagePreviewExtra({this.provider, this.bytes});
}
class ImageCropExtra {
final Uint8List bytes;
ImageCropExtra({required this.bytes});
}
class ImageGalleryExtra {
final List<ImageProvider> images;
final int initialIndex;
ImageGalleryExtra({required this.images, required this.initialIndex});
}
class EditorReplaceExtra {
final Uint8List bytes;
EditorReplaceExtra({required this.bytes});
}