优化打包体积

This commit is contained in:
DelLevin-Home
2026-07-04 16:41:34 +08:00
parent d7d2d236c3
commit 337590b374
29 changed files with 54 additions and 3956 deletions

View File

@@ -1,318 +0,0 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:uuid/uuid.dart';
/// 块类型枚举
enum NoteBlockType {
paragraph,
heading1,
heading2,
heading3,
bulletList,
numberedList,
checklist,
quote,
codeBlock,
divider;
String toJson() => name;
static NoteBlockType fromString(String value) {
return NoteBlockType.values.firstWhere(
(t) => t.name == value,
orElse: () => NoteBlockType.paragraph,
);
}
/// 中文标签
String get label {
switch (this) {
case NoteBlockType.paragraph:
return '正文';
case NoteBlockType.heading1:
return '标题1';
case NoteBlockType.heading2:
return '标题2';
case NoteBlockType.heading3:
return '标题3';
case NoteBlockType.bulletList:
return '无序列表';
case NoteBlockType.numberedList:
return '有序列表';
case NoteBlockType.checklist:
return '待办';
case NoteBlockType.quote:
return '引用';
case NoteBlockType.codeBlock:
return '代码块';
case NoteBlockType.divider:
return '分割线';
}
}
}
/// 内联格式类型
enum InlineFormatType {
bold,
italic,
underline,
strikethrough,
inlineCode;
String toJson() => name;
static InlineFormatType fromString(String value) {
return InlineFormatType.values.firstWhere(
(t) => t.name == value,
orElse: () => InlineFormatType.bold,
);
}
}
/// 内联格式区间
class InlineFormatSpan {
final int start;
final int end;
final Set<InlineFormatType> formats;
const InlineFormatSpan({
required this.start,
required this.end,
required this.formats,
});
Map<String, dynamic> toJson() => {
's': start,
'e': end,
'f': formats.map((f) => f.toJson()).toList(),
};
factory InlineFormatSpan.fromJson(Map<String, dynamic> json) {
return InlineFormatSpan(
start: json['s'] as int? ?? 0,
end: json['e'] as int? ?? 0,
formats: (json['f'] as List<dynamic>?)
?.map((f) => InlineFormatType.fromString(f as String))
.toSet() ??
{},
);
}
InlineFormatSpan copyWith(
{int? start, int? end, Set<InlineFormatType>? formats}) {
return InlineFormatSpan(
start: start ?? this.start,
end: end ?? this.end,
formats: formats ?? Set.from(this.formats),
);
}
}
/// 单个内容块
class NoteBlock {
final String id;
final NoteBlockType type;
final String text;
final Map<String, dynamic> metadata;
final List<InlineFormatSpan> formatting;
NoteBlock({
String? id,
this.type = NoteBlockType.paragraph,
this.text = '',
Map<String, dynamic>? metadata,
List<InlineFormatSpan>? formatting,
}) : id = id ?? const Uuid().v4(),
metadata = metadata ?? {},
formatting = formatting ?? [];
Map<String, dynamic> toJson() => {
'id': id,
'type': type.toJson(),
'text': text,
'metadata': metadata,
'formatting': formatting.map((f) => f.toJson()).toList(),
};
factory NoteBlock.fromJson(Map<String, dynamic> json) {
return NoteBlock(
id: json['id'] as String?,
type: NoteBlockType.fromString(json['type'] as String? ?? 'paragraph'),
text: json['text'] as String? ?? '',
metadata: (json['metadata'] as Map<String, dynamic>?) ?? {},
formatting: (json['formatting'] as List<dynamic>?)
?.map(
(f) => InlineFormatSpan.fromJson(f as Map<String, dynamic>))
.toList() ??
[],
);
}
NoteBlock copyWith({
NoteBlockType? type,
String? text,
Map<String, dynamic>? metadata,
List<InlineFormatSpan>? formatting,
}) {
return NoteBlock(
id: id,
type: type ?? this.type,
text: text ?? this.text,
metadata: metadata ?? Map.from(this.metadata),
formatting: formatting ?? List.from(this.formatting),
);
}
/// 深拷贝
NoteBlock deepCopy() {
return NoteBlock(
id: id,
type: type,
text: text,
metadata: Map.from(metadata),
formatting: formatting
.map((f) => InlineFormatSpan(
start: f.start,
end: f.end,
formats: Set.from(f.formats),
))
.toList(),
);
}
}
/// Note Plus 文档
///
/// 仿 AppFlowy 的 View 模型:
/// - parentId 指向父文档 ID空字符串 = 根级文档)
/// - 每个文档既是页面也是容器,支持无限嵌套
class NotePlusDocument {
final String id;
final String title;
final String parentId; // 父文档 ID空字符串 = 根级
final int sortIndex; // 同级排序序号
final List<NoteBlock> blocks;
final String? blocksJson; // 原始 Delta JSONflutter_quill 模式优先使用)
final List<String> tags;
final List<String> images;
final DateTime createdAt;
final DateTime updatedAt;
final bool isDeleted;
NotePlusDocument({
String? id,
this.title = '',
this.parentId = '',
this.sortIndex = 0,
List<NoteBlock>? blocks,
this.blocksJson,
List<String>? tags,
List<String>? images,
DateTime? createdAt,
DateTime? updatedAt,
this.isDeleted = false,
}) : id = id ?? const Uuid().v4(),
blocks = blocks ?? [NoteBlock()],
tags = tags ?? [],
images = images ?? [],
createdAt = createdAt ?? DateTime.now(),
updatedAt = updatedAt ?? DateTime.now();
/// 从 JSONDB 行)创建
factory NotePlusDocument.fromJson(Map<String, dynamic> json) {
final blocksJson = json['blocks_json'] as String? ?? '[]';
List<NoteBlock> blocksList;
try {
blocksList = (jsonDecode(blocksJson) as List<dynamic>)
.map((b) => NoteBlock.fromJson(b as Map<String, dynamic>))
.toList();
} catch (e) {
debugPrint('[NotePlusDocument] blocks_json 解析失败,使用默认空文档: $e');
blocksList = [];
}
return NotePlusDocument(
id: json['id'] as String?,
title: json['title'] as String? ?? '',
parentId: json['parent_id'] as String? ?? '',
sortIndex: json['sort_index'] as int? ?? 0,
blocks: blocksList.isEmpty ? [NoteBlock()] : blocksList,
blocksJson: json['blocks_json'] as String?,
tags: _parseStringList(json['tags'] as String?),
images: _parseStringList(json['images'] as String?),
createdAt: json['created_at'] != null
? (DateTime.tryParse(json['created_at'] as String)?.toLocal() ?? DateTime.now())
: DateTime.now(),
updatedAt: json['updated_at'] != null
? (DateTime.tryParse(json['updated_at'] as String)?.toLocal() ?? DateTime.now())
: DateTime.now(),
isDeleted: (json['is_deleted'] as int?) == 1,
);
}
/// 序列化为 DB 行
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
'parent_id': parentId,
'sort_index': sortIndex,
'blocks_json': blocksJson ?? jsonEncode(blocks.map((b) => b.toJson()).toList()),
'tags': tags.isEmpty ? null : jsonEncode(tags),
'images': images.isEmpty ? null : jsonEncode(images),
'created_at': createdAt.toUtc().toIso8601String(),
'updated_at': updatedAt.toUtc().toIso8601String(),
'is_deleted': isDeleted ? 1 : 0,
};
NotePlusDocument copyWith({
String? title,
String? parentId,
int? sortIndex,
List<NoteBlock>? blocks,
String? blocksJson,
List<String>? tags,
List<String>? images,
DateTime? updatedAt,
bool? isDeleted,
}) {
return NotePlusDocument(
id: id,
title: title ?? this.title,
parentId: parentId ?? this.parentId,
sortIndex: sortIndex ?? this.sortIndex,
blocks: blocks ?? List.from(this.blocks),
blocksJson: blocksJson ?? this.blocksJson,
tags: tags ?? List.from(this.tags),
images: images ?? List.from(this.images),
createdAt: createdAt,
updatedAt: updatedAt ?? this.updatedAt,
isDeleted: isDeleted ?? this.isDeleted,
);
}
/// 深拷贝
NotePlusDocument deepCopy() {
return NotePlusDocument(
id: id,
title: title,
parentId: parentId,
sortIndex: sortIndex,
blocks: blocks.map((b) => b.deepCopy()).toList(),
tags: List.from(tags),
images: List.from(images),
createdAt: createdAt,
updatedAt: updatedAt,
isDeleted: isDeleted,
);
}
static List<String> _parseStringList(String? json) {
if (json == null || json.isEmpty) return [];
try {
final list = jsonDecode(json) as List<dynamic>;
return list.map((e) => e.toString()).toList();
} catch (_) {
return [];
}
}
}