删除未使用的相机和记录类来重构记录功能;更新pubspec中的依赖项。Yaml为本地插件路径;简化MainActivity和相关类,以提高性能和可维护性。

This commit is contained in:
2026-07-09 16:17:34 +08:00
parent 75c42ea168
commit 6138eddc16
65 changed files with 3677 additions and 2672 deletions
@@ -1,61 +0,0 @@
/// 小程序复制到剪切板的录制信息。
class ClipboardRecordingModel {
final String title;
int? startTimestamp;
int? endTimestamp;
final String address;
/// 录制文件名模板,如「选手名称_选手ID_赛事名称_赛项」。
final String? filename;
ClipboardRecordingModel({
required this.title,
this.startTimestamp,
this.endTimestamp,
required this.address,
this.filename,
});
factory ClipboardRecordingModel.fromJson(Map<String, dynamic> json) {
return ClipboardRecordingModel(
title: _readString(json, 'title'),
startTimestamp: _readOptionalInt(json, 'startTimestamp'),
endTimestamp: _readOptionalInt(json, 'endTimestamp'),
address: _readString(json, 'address'),
filename: _readOptionalString(json, 'filename'),
);
}
Map<String, dynamic> toJson() {
return {
'title': title,
'startTimestamp': startTimestamp,
'endTimestamp': endTimestamp,
'address': address,
if (filename != null) 'filename': filename,
};
}
static String? _readOptionalString(Map<String, dynamic> json, String key) {
final value = json[key];
if (value == null) return null;
if (value is String && value.isNotEmpty) return value;
if (value is! String) {
throw FormatException('Clipboard field "$key" must be a String.');
}
return null;
}
static String _readString(Map<String, dynamic> json, String key) {
final value = json[key];
if (value is String) return value;
throw FormatException('Clipboard field "$key" must be a String.');
}
static int? _readOptionalInt(Map<String, dynamic> json, String key) {
final value = json[key];
if (value == null) return null;
if (value is int) return value;
throw FormatException('Clipboard field "$key" must be an int.');
}
}
@@ -1,51 +1,26 @@
import 'package:recording_tool/features/recording/model/model_clipboard.dart';
import 'package:recording_tool/features/recording/model/model_recording_context.dart';
import 'package:recording_tool/features/recording/model/model_recording_session.dart';
class RecordingModel {
/// 剪切板内容
final ClipboardRecordingModel clipboardRecordingModel;
/// 剪切板是否包含有效的小程序录制信息
final bool hasValidClipboardInfo;
/// 从赛事项进入录制页时传入的录制上下文。
final RecordingContext recordingContext;
/// 录制会话状态
final RecordingSessionState session;
RecordingModel({
required this.clipboardRecordingModel,
this.hasValidClipboardInfo = false,
required this.recordingContext,
this.session = const RecordingSessionState(),
});
bool get isRecording => session.isRecording;
factory RecordingModel.fromJson(Map<String, dynamic> json) {
return RecordingModel(
clipboardRecordingModel: ClipboardRecordingModel.fromJson(
json['clipboardRecordingModel'],
),
);
}
Map<String, dynamic> toJson() {
return {'clipboardRecordingModel': clipboardRecordingModel.toJson()};
}
/// 剪切板是否包含可用于命名的 [ClipboardRecordingModel.filename]。
bool get hasClipboardFilename {
final name = clipboardRecordingModel.filename?.trim();
return hasValidClipboardInfo && name != null && name.isNotEmpty;
}
RecordingModel copyWith({
ClipboardRecordingModel? clipboardRecordingModel,
bool? hasValidClipboardInfo,
RecordingContext? recordingContext,
RecordingSessionState? session,
}) {
return RecordingModel(
clipboardRecordingModel:
clipboardRecordingModel ?? this.clipboardRecordingModel,
hasValidClipboardInfo:
hasValidClipboardInfo ?? this.hasValidClipboardInfo,
recordingContext: recordingContext ?? this.recordingContext,
session: session ?? this.session,
);
}
@@ -0,0 +1,55 @@
class RecordingContext {
const RecordingContext({
required this.eventTitle,
required this.matchName,
required this.group,
required this.venue,
required this.time,
required this.playerName,
required this.playerPhone,
this.laneNo,
this.status,
});
const RecordingContext.empty()
: eventTitle = '',
matchName = '',
group = '',
venue = '',
time = '',
playerName = '',
playerPhone = '',
laneNo = null,
status = null;
final String eventTitle;
final String matchName;
final String group;
final String venue;
final String time;
final String playerName;
final String playerPhone;
final String? laneNo;
final String? status;
String get title => '$matchName $group';
String get address => venue;
String get displayName {
final parts = [
playerName,
matchName,
group,
if (laneNo != null && laneNo!.trim().isNotEmpty) laneNo!,
];
return parts.map(_sanitize).where((part) => part.isNotEmpty).join('_');
}
static String _sanitize(String value) {
return value
.trim()
.replaceAll(RegExp(r'[\\/:*?"<>|]'), '_')
.replaceAll(RegExp(r'\s+'), '_');
}
}
@@ -15,12 +15,11 @@ class RecordingSessionState {
this.zoomRatio = 1.0,
this.minZoomRatio = 1.0,
this.maxZoomRatio = 3.0,
this.lastOutputPath,
this.lastSavedDisplayName,
this.lastStreamUrl,
this.errorMessage,
this.permissionWarning,
this.fileSaveFailed = false,
this.segmentOutputPaths = const [],
this.streamFinished = false,
this.streamFailed = false,
});
final RecordingStatus status;
@@ -35,12 +34,11 @@ class RecordingSessionState {
final double zoomRatio;
final double minZoomRatio;
final double maxZoomRatio;
final String? lastOutputPath;
final String? lastSavedDisplayName;
final String? lastStreamUrl;
final String? errorMessage;
final String? permissionWarning;
final bool fileSaveFailed;
final List<String> segmentOutputPaths;
final bool streamFinished;
final bool streamFailed;
bool get isRecording => status.isRecording;
@@ -65,14 +63,13 @@ class RecordingSessionState {
double? zoomRatio,
double? minZoomRatio,
double? maxZoomRatio,
String? lastOutputPath,
String? lastSavedDisplayName,
String? lastStreamUrl,
String? errorMessage,
String? permissionWarning,
bool? fileSaveFailed,
List<String>? segmentOutputPaths,
bool? streamFinished,
bool? streamFailed,
bool clearPermissionWarning = false,
bool clearLastSaved = false,
bool clearStreamResult = false,
}) {
return RecordingSessionState(
status: status ?? this.status,
@@ -88,16 +85,17 @@ class RecordingSessionState {
zoomRatio: zoomRatio ?? this.zoomRatio,
minZoomRatio: minZoomRatio ?? this.minZoomRatio,
maxZoomRatio: maxZoomRatio ?? this.maxZoomRatio,
lastOutputPath: lastOutputPath ?? this.lastOutputPath,
lastSavedDisplayName: clearLastSaved
? null
: (lastSavedDisplayName ?? this.lastSavedDisplayName),
lastStreamUrl: lastStreamUrl ?? this.lastStreamUrl,
errorMessage: errorMessage,
permissionWarning: clearPermissionWarning
? null
: (permissionWarning ?? this.permissionWarning),
fileSaveFailed: fileSaveFailed ?? this.fileSaveFailed,
segmentOutputPaths: segmentOutputPaths ?? this.segmentOutputPaths,
streamFinished: clearStreamResult
? false
: (streamFinished ?? this.streamFinished),
streamFailed: clearStreamResult
? false
: (streamFailed ?? this.streamFailed),
);
}
}