6e09d853fd
feat(ai-scribe): Fix async function declared without proper return type annotation. feat(ai-scribe): Fix Async operations not properly awaited. feat(ai-scribe): Fix inconsistent capitalization between button labels. feat(ai-scribe): Fix GenerateAITextFailure check will never match. feat(ai-scribe): Fix consider validating text input for predefined actions. feat(ai-scribe): Using a subshell for directory isolation. feat(ai-scribe): Fix verify the mock usage or document intent. feat(ai-scribe): Using a more conventional import for Offset. feat(ai-scribe): Adding error handling for consistency feat(ai-scribe): Remove `fromJson` and `toJson` of AIResponse feat(ai-scribe): Using constants for role values. feat(ai-scribe): Using a more specific import. feat(ai-scribe): Using Timer for cleaner lifecycle management feat(ai-scribe): Adding error handling to fromMap() for consistency. feat(ai-scribe): Disposing the ValueNotifier feat(ai-scribe): Redundant null check after assignment feat(ai-scribe): Fix calling `registerSelectionChangeListener` multiple times may be inefficient. feat(ai-scribe): Safer type handling for JavaScript callback args feat(ai-scribe): Fix async callbacks not awaited in switch statement. feat(ai-scribe): Fix binding lifecycle mismatch for GetAIScribeConfigInteractor feat(ai-scribe): Fix ai prompts feat(ai-scribe): Fix unawaited async call to `_setupSelectionListener` feat(ai-scribe): Fix switch cases use top-origin coordinates while `PositionedDirectional(bottom:)`` expects bottom-origin coordinates. feat(ai-scribe): Adding error handling for selection listener setup.
89 lines
2.2 KiB
Dart
89 lines
2.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
typedef OnTextSelectionChanged = Function(TextSelectionData?);
|
|
|
|
class TextSelectionData {
|
|
final bool hasSelection;
|
|
final String? selectedText;
|
|
final TextSelectionCoordinates? coordinates;
|
|
|
|
const TextSelectionData({
|
|
required this.hasSelection,
|
|
this.selectedText,
|
|
this.coordinates,
|
|
});
|
|
|
|
factory TextSelectionData.empty() {
|
|
return const TextSelectionData(hasSelection: false);
|
|
}
|
|
|
|
factory TextSelectionData.fromMap(Map<dynamic, dynamic> data) {
|
|
try {
|
|
final hasSelection = data['hasSelection'] as bool? ?? false;
|
|
|
|
if (!hasSelection) {
|
|
return TextSelectionData.empty();
|
|
}
|
|
|
|
final selectedText = data['selectedText'] as String?;
|
|
final coordinatesData = data['coordinates'];
|
|
|
|
if (coordinatesData != null && selectedText != null) {
|
|
final coordinates = TextSelectionCoordinates.fromMap(coordinatesData);
|
|
return TextSelectionData(
|
|
hasSelection: true,
|
|
selectedText: selectedText,
|
|
coordinates: coordinates,
|
|
);
|
|
}
|
|
|
|
return TextSelectionData.empty();
|
|
} catch (e) {
|
|
return TextSelectionData.empty();
|
|
}
|
|
}
|
|
}
|
|
|
|
class TextSelectionCoordinates {
|
|
final double x;
|
|
final double y;
|
|
final double width;
|
|
final double height;
|
|
|
|
const TextSelectionCoordinates({
|
|
required this.x,
|
|
required this.y,
|
|
required this.width,
|
|
required this.height,
|
|
});
|
|
|
|
factory TextSelectionCoordinates.fromMap(Map<dynamic, dynamic> data) {
|
|
try {
|
|
return TextSelectionCoordinates(
|
|
x: (data['x'] as num?)?.toDouble() ?? 0.0,
|
|
y: (data['y'] as num?)?.toDouble() ?? 0.0,
|
|
width: (data['width'] as num?)?.toDouble() ?? 0.0,
|
|
height: (data['height'] as num?)?.toDouble() ?? 0.0,
|
|
);
|
|
} catch (e) {
|
|
return const TextSelectionCoordinates(
|
|
x: 0.0,
|
|
y: 0.0,
|
|
width: 0.0,
|
|
height: 0.0,
|
|
);
|
|
}
|
|
}
|
|
|
|
Offset get position => Offset(x, y);
|
|
}
|
|
|
|
mixin TextSelectionMixin<T extends StatefulWidget> on State<T> {
|
|
OnTextSelectionChanged? get onSelectionChanged => null;
|
|
|
|
void handleSelectionChange(Map<dynamic, dynamic> data) {
|
|
final selectionData = TextSelectionData.fromMap(data);
|
|
onSelectionChanged?.call(selectionData);
|
|
}
|
|
}
|