优化录制、停止录制逻辑

This commit is contained in:
2026-06-05 14:30:56 +08:00
parent c0aa2db6db
commit d598b36449
2 changed files with 22 additions and 33 deletions

View File

@@ -7,7 +7,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:recording_tool/core/logging/app_logger.dart'; import 'package:recording_tool/core/logging/app_logger.dart';
import 'package:recording_tool/core/permission/permission_service.dart'; import 'package:recording_tool/core/permission/permission_service.dart';
import 'package:recording_tool/core/utils/rate_limiter.dart';
import 'package:recording_tool/features/recording/model/model_clipboard.dart'; import 'package:recording_tool/features/recording/model/model_clipboard.dart';
import 'package:recording_tool/features/recording/model/model_recording.dart'; import 'package:recording_tool/features/recording/model/model_recording.dart';
import 'package:recording_tool/features/recording/model/model_recording_session.dart'; import 'package:recording_tool/features/recording/model/model_recording_session.dart';
@@ -32,24 +31,17 @@ enum ClipboardReadResult {
} }
class RecordingViewModel extends Notifier<RecordingModel> { class RecordingViewModel extends Notifier<RecordingModel> {
static const Duration _recordingActionInterval = Duration(milliseconds: 300);
static const Object _startRecordingThrottleKey = 'recording.session.start';
static const Object _stopRecordingThrottleKey = 'recording.session.stop';
static final _defaultClipboard = ClipboardRecordingModel( static final _defaultClipboard = ClipboardRecordingModel(
title: '', title: '',
address: '', address: '',
); );
StreamSubscription<RecordingStatus>? _statusSubscription; StreamSubscription<RecordingStatus>? _statusSubscription;
final _rateLimit = RateLimitHub();
@override @override
RecordingModel build() { RecordingModel build() {
ref.onDispose(_dispose); ref.onDispose(_dispose);
return RecordingModel( return RecordingModel(clipboardRecordingModel: _defaultClipboard);
clipboardRecordingModel: _defaultClipboard,
);
} }
void _updateSession( void _updateSession(
@@ -214,7 +206,9 @@ class RecordingViewModel extends Notifier<RecordingModel> {
return const []; return const [];
} }
bool _isGalleryPermissionGranted(Map<Permission, PermissionStatus> permissions) { bool _isGalleryPermissionGranted(
Map<Permission, PermissionStatus> permissions,
) {
for (final permission in _galleryPermissions()) { for (final permission in _galleryPermissions()) {
if (permissions[permission]?.isGranted ?? false) { if (permissions[permission]?.isGranted ?? false) {
return true; return true;
@@ -223,21 +217,7 @@ class RecordingViewModel extends Notifier<RecordingModel> {
return _galleryPermissions().isEmpty; return _galleryPermissions().isEmpty;
} }
bool _tryAcquireRecordingAction(Object key) {
var executed = false;
_rateLimit.throttle<void>(
key: key,
value: null,
duration: _recordingActionInterval,
options: const ThrottleOptions(leading: true, trailing: false),
onCallback: (_) => executed = true,
);
return executed;
}
Future<void> startRecording({bool enableDoNotDisturb = true}) async { Future<void> startRecording({bool enableDoNotDisturb = true}) async {
if (!_tryAcquireRecordingAction(_startRecordingThrottleKey)) return;
final session = state.session; final session = state.session;
if (!session.isPreviewReady || if (!session.isPreviewReady ||
session.isRecording || session.isRecording ||
@@ -277,8 +257,6 @@ class RecordingViewModel extends Notifier<RecordingModel> {
} }
Future<void> stopRecording() async { Future<void> stopRecording() async {
if (!_tryAcquireRecordingAction(_stopRecordingThrottleKey)) return;
if (!state.session.isRecording) return; if (!state.session.isRecording) return;
try { try {
@@ -346,7 +324,6 @@ class RecordingViewModel extends Notifier<RecordingModel> {
} }
Future<void> _dispose() async { Future<void> _dispose() async {
_rateLimit.clear();
await _statusSubscription?.cancel(); await _statusSubscription?.cancel();
} }
} }

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:recording_tool/core/utils/rate_limiter.dart';
import 'package:recording_tool/features/recording/model/model_recording_session.dart'; import 'package:recording_tool/features/recording/model/model_recording_session.dart';
import 'package:recording_tool/features/recording/widgets/widget_clipboard_address_clock_chip.dart'; import 'package:recording_tool/features/recording/widgets/widget_clipboard_address_clock_chip.dart';
import 'package:recording_tool/features/recording/widgets/widget_recording_setup_hints.dart'; import 'package:recording_tool/features/recording/widgets/widget_recording_setup_hints.dart';
@@ -116,9 +117,23 @@ class RecordingHudWidget extends StatelessWidget {
? null ? null
: () async { : () async {
if (state.isRecording) { if (state.isRecording) {
await onStop(); RateLimit.instance.debounce<void>(
key: 'recording.session.stop',
value: null,
duration: Duration(milliseconds: 300),
onCallback: (_) async {
await onStop();
},
);
} else { } else {
await onStart(); RateLimit.instance.debounce<void>(
key: 'recording.session.start',
value: null,
duration: Duration(milliseconds: 300),
onCallback: (_) async {
await onStart();
},
);
} }
}, },
child: Container( child: Container(
@@ -126,10 +141,7 @@ class RecordingHudWidget extends StatelessWidget {
height: _recordButtonSize, height: _recordButtonSize,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all( border: Border.all(color: Colors.white, width: 4.r),
color: Colors.white,
width: 4.r,
),
color: state.isRecording ? Colors.white : Colors.red, color: state.isRecording ? Colors.white : Colors.red,
), ),
child: Icon( child: Icon(