Files
xianyan/lib/editor/mixins/editor_import_actions.dart
Developer c44457f94c style: 修复文件头部注释的多余BOM头字符
移除所有文件头部的不可见BOM前缀字符,统一文件头部注释格式,确保跨平台编译一致性
2026-05-27 08:05:47 +08:00

144 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 — 编辑器导入操作 Mixin
// 创建时间: 2026-04-25
// 更新时间: 2026-04-25
// 作用: 图片导入、xycard导入、草稿列表、模板选择、贴纸编辑器入口
// 上次更新: 从 editor_actions_mixin.dart 分流
// ============================================================
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
import 'package:pro_image_editor/pro_image_editor.dart' as pro;
import 'package:pro_image_editor/designs/frosted_glass/frosted_glass.dart';
import 'package:xianyan/core/router/editor_router.dart';
import 'package:xianyan/core/utils/logger.dart' as app_log;
import 'package:xianyan/editor/models/editor_models.dart';
import 'package:xianyan/editor/services/image/image_import_service.dart';
import 'package:xianyan/editor/services/export/xycard_service.dart';
import 'package:xianyan/editor/widgets/panels/template_picker_sheet.dart';
import 'package:xianyan/shared/widgets/containers/bottom_sheet.dart';
import 'package:xianyan/editor/mixins/editor_actions_base.dart';
mixin EditorImportActions on EditorActionsBase {
void openStickerEditor(pro.ProImageEditorState editor) async {
final layer = await editor.openPage<pro.Layer>(
FrostedGlassStickerPage(
configs: editor.configs,
callbacks: editor.callbacks,
),
);
if (layer == null || !mounted) return;
if (layer is! pro.WidgetLayer) {
layer.scale = editor.configs.emojiEditor.initScale;
}
editor.addLayer(layer);
}
void showDraftList() {
context.goToDraftList();
}
void showTemplateSheet() {
AppBottomSheet.showHalf<void>(
context: context,
builder: (_) => TemplatePickerSheet(
onSelect: (template) {
Navigator.of(context).pop();
},
),
);
}
Future<void> importImage() async {
final choice = await showEditorChoice(
context: context,
title: '📥 导入',
message: '选择导入方式',
choices: [('🖼️ 图片', 'image'), ('📦 .xycard 源文件', 'xycard')],
);
if (!mounted || choice == null) return;
if (choice == 'xycard') {
await _importXycard();
} else {
await _importImageFile();
}
}
Future<void> _importImageFile() async {
try {
final bytes = await ImageImportService.showImportSheet(context);
if (bytes == null || !mounted) return;
final processed = await ImageImportService.preprocessImage(bytes);
if (processed == null || !mounted) return;
context.replaceWithEditor(processed);
} catch (e) {
app_log.Log.e('导入图片失败', e);
}
}
Future<void> _importXycard() async {
try {
final canvas = await XycardService.import();
if (canvas == null || !mounted) return;
final imageBytes = await _renderCanvasToBytes(canvas);
if (imageBytes == null || !mounted) return;
context.replaceWithEditor(
imageBytes,
initialText: canvas.textLayers.isNotEmpty
? canvas.textLayers.first.text
: null,
);
} catch (e) {
app_log.Log.e('导入.xycard失败', e);
if (mounted) {
showCupertinoDialog<void>(
context: context,
builder: (_) => CupertinoAlertDialog(
title: const Text('导入失败'),
content: const Text('无法解析.xycard文件请检查文件格式'),
actions: [
CupertinoDialogAction(
child: const Text('确定'),
onPressed: () => Navigator.pop(context),
),
],
),
);
}
}
}
Future<Uint8List?> _renderCanvasToBytes(QuoteCanvasModel canvas) async {
try {
final recorder = ui.PictureRecorder();
final canvasObj = Canvas(recorder);
final w = canvas.canvasWidth;
final h = canvas.canvasHeight;
canvasObj.drawRect(
Rect.fromLTWH(0, 0, w, h),
Paint()..color = canvas.background.solidColor,
);
final picture = recorder.endRecording();
final image = await picture.toImage(w.toInt(), h.toInt());
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
return byteData?.buffer.asUint8List();
} catch (e) {
app_log.Log.e('画布渲染失败', e);
return null;
}
}
}