1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-08 13:58:47 +00:00

Dart 3.9 / Flutter 3.35 [first LLM release] (#2714)

I got carried away with Gemini and basically rewrote CI and the release
process for the new LLM reality. This work was largely completed by
Gemini.

- Bump all SDK versions to the current beta (3.9.0-0)
- Run `flutter channel beta`
- Wrote `ci_script.dart` to replace the bash scripts
- Converted repository to pub workspace #2499 
- Added llm.md and release.md
- Added redirect for deprecated Samples Index

## Pre-launch Checklist

- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I have added sample code updates to the [changelog].
- [x] I updated/added relevant documentation (doc comments with `///`).
This commit is contained in:
Eric Windmill
2025-08-14 12:26:24 -07:00
committed by GitHub
parent 0aa5415d5e
commit 2999d738b8
410 changed files with 28166 additions and 27661 deletions

View File

@@ -53,7 +53,9 @@ class AppStateWidgetState extends State<AppStateWidget> {
toggleButtonsState: <ToggleButtonsState>{},
);
void updateTextEditingDeltaHistory(List<TextEditingDelta> textEditingDeltas) {
void updateTextEditingDeltaHistory(
List<TextEditingDelta> textEditingDeltas,
) {
_data = _data.copyWith(
textEditingDeltaHistory: <TextEditingDelta>[
..._data.textEditingDeltaHistory,
@@ -76,11 +78,12 @@ class AppStateWidgetState extends State<AppStateWidget> {
if (replacementStyles.isEmpty) {
_data = _data.copyWith(
toggleButtonsState: Set.from(_data.toggleButtonsState)..removeAll({
ToggleButtonsState.bold,
ToggleButtonsState.italic,
ToggleButtonsState.underline,
}),
toggleButtonsState: Set.from(_data.toggleButtonsState)
..removeAll({
ToggleButtonsState.bold,
ToggleButtonsState.italic,
ToggleButtonsState.underline,
}),
);
}
@@ -180,7 +183,8 @@ class AppStateWidgetState extends State<AppStateWidget> {
controller.applyReplacement(
TextEditingInlineSpanReplacement(
replacementRange,
(string, range) => TextSpan(text: string, style: attributeMap[index]),
(string, range) =>
TextSpan(text: string, style: attributeMap[index]),
true,
),
);

View File

@@ -10,8 +10,8 @@ class AppStateManager extends InheritedWidget {
}) : _appState = state;
static AppStateManager of(BuildContext context) {
final AppStateManager? result =
context.dependOnInheritedWidgetOfExactType<AppStateManager>();
final AppStateManager? result = context
.dependOnInheritedWidgetOfExactType<AppStateManager>();
assert(result != null, 'No AppStateManager found in context');
return result!;
}

View File

@@ -89,7 +89,9 @@ class _BasicTextFieldState extends State<BasicTextField> {
TextSelection selection,
SelectionChangedCause? cause,
) {
final bool willShowSelectionHandles = _shouldShowSelectionHandles(cause);
final bool willShowSelectionHandles = _shouldShowSelectionHandles(
cause,
);
if (willShowSelectionHandles != _showSelectionHandles) {
setState(() {
_showSelectionHandles = willShowSelectionHandles;
@@ -98,16 +100,15 @@ class _BasicTextFieldState extends State<BasicTextField> {
}
void _onDragUpdate(DragUpdateDetails details) {
final Offset startOffset =
_renderEditable.maxLines == 1
? Offset(
_renderEditable.offset.pixels - _dragStartViewportOffset,
0.0,
)
: Offset(
0.0,
_renderEditable.offset.pixels - _dragStartViewportOffset,
);
final Offset startOffset = _renderEditable.maxLines == 1
? Offset(
_renderEditable.offset.pixels - _dragStartViewportOffset,
0.0,
)
: Offset(
0.0,
_renderEditable.offset.pixels - _dragStartViewportOffset,
);
_renderEditable.selectPositionAt(
from: _startDetails.globalPosition - startOffset,
@@ -134,7 +135,8 @@ class _BasicTextFieldState extends State<BasicTextField> {
_textSelectionControls = cupertinoTextSelectionHandleControls;
case TargetPlatform.macOS:
// ignore: deprecated_member_use
_textSelectionControls = cupertinoDesktopTextSelectionHandleControls;
_textSelectionControls =
cupertinoDesktopTextSelectionHandleControls;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
// ignore: deprecated_member_use
@@ -151,7 +153,8 @@ class _BasicTextFieldState extends State<BasicTextField> {
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onPanStart: (dragStartDetails) => _onDragStart(dragStartDetails),
onPanUpdate: (dragUpdateDetails) => _onDragUpdate(dragUpdateDetails),
onPanUpdate: (dragUpdateDetails) =>
_onDragUpdate(dragUpdateDetails),
onSecondaryTapDown: (secondaryTapDownDetails) {
_renderEditable.selectWordsInRange(
from: secondaryTapDownDetails.globalPosition,
@@ -190,12 +193,12 @@ class _BasicTextFieldState extends State<BasicTextField> {
);
}
},
onLongPressEnd:
(longPressEndDetails) => _textInputClient!.showToolbar(),
onHorizontalDragStart:
(dragStartDetails) => _onDragStart(dragStartDetails),
onHorizontalDragUpdate:
(dragUpdateDetails) => _onDragUpdate(dragUpdateDetails),
onLongPressEnd: (longPressEndDetails) =>
_textInputClient!.showToolbar(),
onHorizontalDragStart: (dragStartDetails) =>
_onDragStart(dragStartDetails),
onHorizontalDragUpdate: (dragUpdateDetails) =>
_onDragUpdate(dragUpdateDetails),
child: SizedBox(
height: double.infinity,
width: MediaQuery.of(context).size.width,

View File

@@ -63,8 +63,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
with TextSelectionDelegate, TextInputClient, DeltaTextInputClient {
final GlobalKey _textKey = GlobalKey();
late AppStateWidgetState manager;
final ClipboardStatusNotifier? _clipboardStatus =
kIsWeb ? null : ClipboardStatusNotifier();
final ClipboardStatusNotifier? _clipboardStatus = kIsWeb
? null
: ClipboardStatusNotifier();
@override
void initState() {
@@ -180,7 +181,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
}
@override
void updateEditingValueWithDeltas(List<TextEditingDelta> textEditingDeltas) {
void updateEditingValueWithDeltas(
List<TextEditingDelta> textEditingDeltas,
) {
TextEditingValue value = _value;
for (final TextEditingDelta delta in textEditingDeltas) {
@@ -339,40 +342,40 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
}
// These actions have yet to be implemented for this sample.
static final Map<Type, Action<Intent>> _unsupportedActions =
<Type, Action<Intent>>{
DeleteToNextWordBoundaryIntent: DoNothingAction(consumesKey: false),
DeleteToLineBreakIntent: DoNothingAction(consumesKey: false),
ExtendSelectionToNextWordBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToNextParagraphBoundaryOrCaretLocationIntent:
DoNothingAction(consumesKey: false),
ExtendSelectionToLineBreakIntent: DoNothingAction(consumesKey: false),
ExtendSelectionVerticallyToAdjacentLineIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionVerticallyToAdjacentPageIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToNextParagraphBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToDocumentBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionByPageIntent: DoNothingAction(consumesKey: false),
ExpandSelectionToDocumentBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExpandSelectionToLineBreakIntent: DoNothingAction(consumesKey: false),
ScrollToDocumentBoundaryIntent: DoNothingAction(consumesKey: false),
RedoTextIntent: DoNothingAction(consumesKey: false),
ReplaceTextIntent: DoNothingAction(consumesKey: false),
UndoTextIntent: DoNothingAction(consumesKey: false),
UpdateSelectionIntent: DoNothingAction(consumesKey: false),
TransposeCharactersIntent: DoNothingAction(consumesKey: false),
};
static final Map<Type, Action<Intent>>
_unsupportedActions = <Type, Action<Intent>>{
DeleteToNextWordBoundaryIntent: DoNothingAction(consumesKey: false),
DeleteToLineBreakIntent: DoNothingAction(consumesKey: false),
ExtendSelectionToNextWordBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToNextParagraphBoundaryOrCaretLocationIntent:
DoNothingAction(consumesKey: false),
ExtendSelectionToLineBreakIntent: DoNothingAction(consumesKey: false),
ExtendSelectionVerticallyToAdjacentLineIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionVerticallyToAdjacentPageIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToNextParagraphBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionToDocumentBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExtendSelectionByPageIntent: DoNothingAction(consumesKey: false),
ExpandSelectionToDocumentBoundaryIntent: DoNothingAction(
consumesKey: false,
),
ExpandSelectionToLineBreakIntent: DoNothingAction(consumesKey: false),
ScrollToDocumentBoundaryIntent: DoNothingAction(consumesKey: false),
RedoTextIntent: DoNothingAction(consumesKey: false),
ReplaceTextIntent: DoNothingAction(consumesKey: false),
UndoTextIntent: DoNothingAction(consumesKey: false),
UpdateSelectionIntent: DoNothingAction(consumesKey: false),
TransposeCharactersIntent: DoNothingAction(consumesKey: false),
};
/// Keyboard text editing actions.
// The Handling of the default text editing shortcuts with deltas
@@ -388,9 +391,8 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
),
ExtendSelectionByCharacterIntent:
CallbackAction<ExtendSelectionByCharacterIntent>(
onInvoke:
(intent) =>
_extendSelection(intent.forward, intent.collapseSelection),
onInvoke: (intent) =>
_extendSelection(intent.forward, intent.collapseSelection),
),
SelectAllTextIntent: CallbackAction<SelectAllTextIntent>(
onInvoke: (intent) => selectAll(intent.cause),
@@ -401,7 +403,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
PasteTextIntent: CallbackAction<PasteTextIntent>(
onInvoke: (intent) => pasteText(intent.cause),
),
DoNothingAndStopPropagationTextIntent: DoNothingAction(consumesKey: false),
DoNothingAndStopPropagationTextIntent: DoNothingAction(
consumesKey: false,
),
..._unsupportedActions,
};
@@ -458,28 +462,29 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
if (collapseSelection) {
if (!_selection.isCollapsed) {
final int firstOffset =
_selection.isNormalized ? _selection.start : _selection.end;
final int lastOffset =
_selection.isNormalized ? _selection.end : _selection.start;
final int firstOffset = _selection.isNormalized
? _selection.start
: _selection.end;
final int lastOffset = _selection.isNormalized
? _selection.end
: _selection.start;
selection = TextSelection.collapsed(
offset: forward ? lastOffset : firstOffset,
);
} else {
if (forward && _selection.baseOffset == _value.text.length) return;
if (!forward && _selection.baseOffset == 0) return;
final int adjustment =
forward
? _value.text
.substring(_selection.baseOffset)
.characters
.first
.length
: -_value.text
.substring(0, _selection.baseOffset)
.characters
.last
.length;
final int adjustment = forward
? _value.text
.substring(_selection.baseOffset)
.characters
.first
.length
: -_value.text
.substring(0, _selection.baseOffset)
.characters
.last
.length;
selection = TextSelection.collapsed(
offset: _selection.baseOffset + adjustment,
);
@@ -487,18 +492,17 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
} else {
if (forward && _selection.extentOffset == _value.text.length) return;
if (!forward && _selection.extentOffset == 0) return;
final int adjustment =
forward
? _value.text
.substring(_selection.baseOffset)
.characters
.first
.length
: -_value.text
.substring(0, _selection.baseOffset)
.characters
.last
.length;
final int adjustment = forward
? _value.text
.substring(_selection.baseOffset)
.characters
.first
.length
: -_value.text
.substring(0, _selection.baseOffset)
.characters
.last
.length;
selection = TextSelection(
baseOffset: _selection.baseOffset,
extentOffset: _selection.extentOffset + adjustment,
@@ -578,7 +582,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
void _updateCaretRectIfNeeded() {
final TextSelection? selection = renderEditable.selection;
if (selection == null || !selection.isValid || !selection.isCollapsed) {
if (selection == null ||
!selection.isValid ||
!selection.isCollapsed) {
return;
}
final TextPosition currentTextPosition = TextPosition(
@@ -691,7 +697,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
final TextSelection pasteRange = textEditingValue.selection;
if (!pasteRange.isValid) return;
final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
final ClipboardData? data = await Clipboard.getData(
Clipboard.kTextPlain,
);
if (data == null) return;
// After the paste, the cursor should be collapsed and located after the
@@ -846,7 +854,8 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
requestKeyboard();
}
}
if (widget.selectionControls == null && widget.contextMenuBuilder == null) {
if (widget.selectionControls == null &&
widget.contextMenuBuilder == null) {
_selectionOverlay?.dispose();
_selectionOverlay = null;
} else {
@@ -891,41 +900,43 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
onSelectionHandleTapped: () {
_toggleToolbar();
},
contextMenuBuilder:
widget.contextMenuBuilder == null || kIsWeb
? null
: (context) {
return widget.contextMenuBuilder!(
context,
_clipboardStatus!.value,
copyEnabled
? () => copySelection(SelectionChangedCause.toolbar)
: null,
cutEnabled
? () => cutSelection(SelectionChangedCause.toolbar)
: null,
pasteEnabled
? () => pasteText(SelectionChangedCause.toolbar)
: null,
selectAllEnabled
? () => selectAll(SelectionChangedCause.toolbar)
: null,
lookUpEnabled
? () => _lookUpSelection(SelectionChangedCause.toolbar)
: null,
liveTextInputEnabled
? () => _startLiveTextInput(SelectionChangedCause.toolbar)
: null,
searchWebEnabled
? () =>
_searchWebForSelection(SelectionChangedCause.toolbar)
: null,
shareEnabled
? () => _shareSelection(SelectionChangedCause.toolbar)
: null,
_contextMenuAnchors,
);
},
contextMenuBuilder: widget.contextMenuBuilder == null || kIsWeb
? null
: (context) {
return widget.contextMenuBuilder!(
context,
_clipboardStatus!.value,
copyEnabled
? () => copySelection(SelectionChangedCause.toolbar)
: null,
cutEnabled
? () => cutSelection(SelectionChangedCause.toolbar)
: null,
pasteEnabled
? () => pasteText(SelectionChangedCause.toolbar)
: null,
selectAllEnabled
? () => selectAll(SelectionChangedCause.toolbar)
: null,
lookUpEnabled
? () => _lookUpSelection(SelectionChangedCause.toolbar)
: null,
liveTextInputEnabled
? () => _startLiveTextInput(
SelectionChangedCause.toolbar,
)
: null,
searchWebEnabled
? () => _searchWebForSelection(
SelectionChangedCause.toolbar,
)
: null,
shareEnabled
? () => _shareSelection(SelectionChangedCause.toolbar)
: null,
_contextMenuAnchors,
);
},
magnifierConfiguration: TextMagnifierConfiguration.disabled,
);
@@ -933,8 +944,8 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
}
void _toggleToolbar() {
final TextSelectionOverlay selectionOverlay =
_selectionOverlay ??= _createSelectionOverlay();
final TextSelectionOverlay selectionOverlay = _selectionOverlay ??=
_createSelectionOverlay();
if (selectionOverlay.toolbarIsVisible) {
hideToolbar(false);
@@ -971,7 +982,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
final InlineSpan span = renderEditable.text!;
final String prevText = span.toPlainText();
final String currText = textEditingValue.text;
if (prevText != currText || !selection.isValid || selection.isCollapsed) {
if (prevText != currText ||
!selection.isValid ||
selection.isCollapsed) {
return _GlyphHeights(
start: renderEditable.preferredLineHeight,
end: renderEditable.preferredLineHeight,
@@ -981,12 +994,13 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
final String selectedGraphemes = selection.textInside(currText);
final int firstSelectedGraphemeExtent =
selectedGraphemes.characters.first.length;
final Rect? startCharacterRect = renderEditable.getRectForComposingRange(
TextRange(
start: selection.start,
end: selection.start + firstSelectedGraphemeExtent,
),
);
final Rect? startCharacterRect = renderEditable
.getRectForComposingRange(
TextRange(
start: selection.start,
end: selection.start + firstSelectedGraphemeExtent,
),
);
final int lastSelectedGraphemeExtent =
selectedGraphemes.characters.last.length;
final Rect? endCharacterRect = renderEditable.getRectForComposingRange(
@@ -996,7 +1010,8 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
),
);
return _GlyphHeights(
start: startCharacterRect?.height ?? renderEditable.preferredLineHeight,
start:
startCharacterRect?.height ?? renderEditable.preferredLineHeight,
end: endCharacterRect?.height ?? renderEditable.preferredLineHeight,
);
}
@@ -1023,8 +1038,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
/// For OCR Support.
/// Detects whether the Live Text input is enabled.
final LiveTextInputStatusNotifier? _liveTextInputStatus =
kIsWeb ? null : LiveTextInputStatusNotifier();
final LiveTextInputStatusNotifier? _liveTextInputStatus = kIsWeb
? null
: LiveTextInputStatusNotifier();
@override
bool get liveTextInputEnabled {
@@ -1079,7 +1095,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
}
return !textEditingValue.selection.isCollapsed &&
textEditingValue.selection.textInside(textEditingValue.text).trim() !=
textEditingValue.selection
.textInside(textEditingValue.text)
.trim() !=
'';
}
@@ -1142,7 +1160,8 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
startHandleLayerLink: _startHandleLayerLink,
endHandleLayerLink: _endHandleLayerLink,
inlineSpan: _buildTextSpan(),
value: _value, // We pass value.selection to RenderEditable.
value:
_value, // We pass value.selection to RenderEditable.
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey[100],
showCursor: ValueNotifier<bool>(_hasFocus),
@@ -1159,7 +1178,9 @@ class BasicTextInputClientState extends State<BasicTextInputClient>
textAlign: TextAlign.left,
textDirection: _textDirection,
locale: Localizations.maybeLocaleOf(context),
textHeightBehavior: DefaultTextHeightBehavior.maybeOf(context),
textHeightBehavior: DefaultTextHeightBehavior.maybeOf(
context,
),
textWidthBasis: TextWidthBasis.parent,
obscuringCharacter: '',
obscureText:
@@ -1321,7 +1342,10 @@ class _Editable extends MultiChildRenderObjectWidget {
}
@override
void updateRenderObject(BuildContext context, RenderEditable renderObject) {
void updateRenderObject(
BuildContext context,
RenderEditable renderObject,
) {
renderObject
..text = inlineSpan
..cursorColor = cursorColor

View File

@@ -31,10 +31,9 @@ class FormattingToolbar extends StatelessWidget {
ToggleButtonsState.underline,
),
],
onPressed:
(index) => AppStateWidget.of(
context,
).updateToggleButtonsStateOnButtonPressed(index),
onPressed: (index) => AppStateWidget.of(
context,
).updateToggleButtonsStateOnButtonPressed(index),
children: const [
Icon(Icons.format_bold),
Icon(Icons.format_italic),

View File

@@ -49,8 +49,9 @@ class _MyHomePageState extends State<MyHomePage> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
_replacementTextEditingController =
AppStateManager.of(context).appState.replacementsController;
_replacementTextEditingController = AppStateManager.of(
context,
).appState.replacementsController;
}
static Route<Object?> _aboutDialogBuilder(
@@ -67,11 +68,10 @@ class _MyHomePageState extends State<MyHomePage> {
' more powerful rich text editing applications such as this small example. This feature is supported on all platforms.';
return DialogRoute<void>(
context: context,
builder:
(context) => const AlertDialog(
title: Center(child: Text('About')),
content: Text(aboutContent),
),
builder: (context) => const AlertDialog(
title: Center(child: Text('About')),
content: Text(aboutContent),
),
);
}
@@ -100,7 +100,10 @@ class _MyHomePageState extends State<MyHomePage> {
padding: const EdgeInsets.symmetric(horizontal: 35.0),
child: BasicTextField(
controller: _replacementTextEditingController,
style: const TextStyle(fontSize: 18.0, color: Colors.black),
style: const TextStyle(
fontSize: 18.0,
color: Colors.black,
),
focusNode: _focusNode,
),
),

View File

@@ -41,7 +41,11 @@ typedef InlineSpanGenerator = InlineSpan Function(String, TextRange);
class TextEditingInlineSpanReplacement {
/// Constructs a replacement that replaces matches of the [TextRange] with the
/// output of the [generator].
TextEditingInlineSpanReplacement(this.range, this.generator, this.expand);
TextEditingInlineSpanReplacement(
this.range,
this.generator,
this.expand,
);
/// The [TextRange] to replace.
///
@@ -54,7 +58,9 @@ class TextEditingInlineSpanReplacement {
bool expand;
TextEditingInlineSpanReplacement? onDelete(TextEditingDeltaDeletion delta) {
TextEditingInlineSpanReplacement? onDelete(
TextEditingDeltaDeletion delta,
) {
final TextRange deletedRange = delta.deletedRange;
final int deletedLength = delta.textDeleted.length;
@@ -75,7 +81,10 @@ class TextEditingInlineSpanReplacement {
} else if (range.start < deletedRange.start &&
range.end > deletedRange.end) {
return copy(
range: TextRange(start: range.start, end: range.end - deletedLength),
range: TextRange(
start: range.start,
end: range.end - deletedLength,
),
);
} else if (range.start >= deletedRange.start &&
range.end <= deletedRange.end) {
@@ -90,7 +99,9 @@ class TextEditingInlineSpanReplacement {
);
} else if (range.end <= deletedRange.start &&
range.end < deletedRange.end) {
return copy(range: TextRange(start: range.start, end: range.end));
return copy(
range: TextRange(start: range.start, end: range.end),
);
}
return null;
@@ -105,24 +116,36 @@ class TextEditingInlineSpanReplacement {
if (range.end == insertionOffset) {
if (expand) {
return copy(
range: TextRange(start: range.start, end: range.end + insertedLength),
range: TextRange(
start: range.start,
end: range.end + insertedLength,
),
);
} else {
return copy(range: TextRange(start: range.start, end: range.end));
return copy(
range: TextRange(start: range.start, end: range.end),
);
}
}
if (range.start < insertionOffset && range.end < insertionOffset) {
return copy(range: TextRange(start: range.start, end: range.end));
} else if (range.start >= insertionOffset && range.end > insertionOffset) {
return copy(
range: TextRange(start: range.start, end: range.end),
);
} else if (range.start >= insertionOffset &&
range.end > insertionOffset) {
return copy(
range: TextRange(
start: range.start + insertedLength,
end: range.end + insertedLength,
),
);
} else if (range.start < insertionOffset && range.end > insertionOffset) {
} else if (range.start < insertionOffset &&
range.end > insertionOffset) {
return copy(
range: TextRange(start: range.start, end: range.end + insertedLength),
range: TextRange(
start: range.start,
end: range.end + insertedLength,
),
);
}
@@ -139,13 +162,13 @@ class TextEditingInlineSpanReplacement {
delta.replacementText.length > delta.textReplaced.length;
final bool replacementEqualLength =
delta.replacementText.length == delta.textReplaced.length;
final int changedOffset =
replacementShortenedText
? delta.textReplaced.length - delta.replacementText.length
: delta.replacementText.length - delta.textReplaced.length;
final int changedOffset = replacementShortenedText
? delta.textReplaced.length - delta.replacementText.length
: delta.replacementText.length - delta.textReplaced.length;
if (range.start >= replacedRange.start &&
(range.start < replacedRange.end && range.end > replacedRange.end)) {
(range.start < replacedRange.end &&
range.end > replacedRange.end)) {
if (replacementShortenedText) {
return [
copy(
@@ -166,20 +189,26 @@ class TextEditingInlineSpanReplacement {
];
} else if (replacementEqualLength) {
return [
copy(range: TextRange(start: replacedRange.end, end: range.end)),
copy(
range: TextRange(start: replacedRange.end, end: range.end),
),
];
}
} else if ((range.start < replacedRange.start &&
range.end > replacedRange.start) &&
range.end <= replacedRange.end) {
return [
copy(range: TextRange(start: range.start, end: replacedRange.start)),
copy(
range: TextRange(start: range.start, end: replacedRange.start),
),
];
} else if (range.start < replacedRange.start &&
range.end > replacedRange.end) {
if (replacementShortenedText) {
return [
copy(range: TextRange(start: range.start, end: replacedRange.start)),
copy(
range: TextRange(start: range.start, end: replacedRange.start),
),
copy(
range: TextRange(
start: replacedRange.end - changedOffset,
@@ -189,7 +218,9 @@ class TextEditingInlineSpanReplacement {
];
} else if (replacementLengthenedText) {
return [
copy(range: TextRange(start: range.start, end: replacedRange.start)),
copy(
range: TextRange(start: range.start, end: replacedRange.start),
),
copy(
range: TextRange(
start: replacedRange.end + changedOffset,
@@ -199,8 +230,12 @@ class TextEditingInlineSpanReplacement {
];
} else if (replacementEqualLength) {
return [
copy(range: TextRange(start: range.start, end: replacedRange.start)),
copy(range: TextRange(start: replacedRange.end, end: range.end)),
copy(
range: TextRange(start: range.start, end: replacedRange.start),
),
copy(
range: TextRange(start: replacedRange.end, end: range.end),
),
];
}
} else if (range.start >= replacedRange.start &&
@@ -232,7 +267,11 @@ class TextEditingInlineSpanReplacement {
}
} else if (range.end <= replacedRange.start &&
range.end < replacedRange.end) {
return [copy(range: TextRange(start: range.start, end: range.end))];
return [
copy(
range: TextRange(start: range.start, end: range.end),
),
];
}
return null;
@@ -250,15 +289,23 @@ class TextEditingInlineSpanReplacement {
return this;
}
List<TextEditingInlineSpanReplacement>? removeRange(TextRange removalRange) {
List<TextEditingInlineSpanReplacement>? removeRange(
TextRange removalRange,
) {
if (range.start >= removalRange.start &&
(range.start < removalRange.end && range.end > removalRange.end)) {
return [copy(range: TextRange(start: removalRange.end, end: range.end))];
return [
copy(
range: TextRange(start: removalRange.end, end: range.end),
),
];
} else if ((range.start < removalRange.start &&
range.end > removalRange.start) &&
range.end <= removalRange.end) {
return [
copy(range: TextRange(start: range.start, end: removalRange.start)),
copy(
range: TextRange(start: range.start, end: removalRange.start),
),
];
} else if (range.start < removalRange.start &&
range.end > removalRange.end) {
@@ -267,7 +314,9 @@ class TextEditingInlineSpanReplacement {
range: TextRange(start: range.start, end: removalRange.start),
expand: removalRange.isCollapsed ? false : expand,
),
copy(range: TextRange(start: removalRange.end, end: range.end)),
copy(
range: TextRange(start: removalRange.end, end: range.end),
),
];
} else if (range.start >= removalRange.start &&
range.end <= removalRange.end) {
@@ -278,7 +327,8 @@ class TextEditingInlineSpanReplacement {
} else if (range.end <= removalRange.start &&
range.end < removalRange.end) {
return [this];
} else if (removalRange.isCollapsed && range.end == removalRange.start) {
} else if (removalRange.isCollapsed &&
range.end == removalRange.start) {
return [this];
}
@@ -453,7 +503,9 @@ class ReplacementTextEditingController extends TextEditingController {
required bool withComposing,
}) {
assert(
!value.composing.isValid || !withComposing || value.isComposingRangeValid,
!value.composing.isValid ||
!withComposing ||
value.isComposingRangeValid,
);
// Keep a mapping of TextRanges to the InlineSpan to replace it with.
@@ -467,7 +519,10 @@ class ReplacementTextEditingController extends TextEditingController {
in replacements!) {
_addToMappingWithOverlaps(
replacement.generator,
TextRange(start: replacement.range.start, end: replacement.range.end),
TextRange(
start: replacement.range.start,
end: replacement.range.end,
),
rangeSpanMapping,
value.text,
);
@@ -484,12 +539,11 @@ class ReplacementTextEditingController extends TextEditingController {
withComposing) {
_addToMappingWithOverlaps(
(value, range) {
final TextStyle composingStyle =
style != null
? style.merge(
const TextStyle(decoration: TextDecoration.underline),
)
: const TextStyle(decoration: TextDecoration.underline);
final TextStyle composingStyle = style != null
? style.merge(
const TextStyle(decoration: TextDecoration.underline),
)
: const TextStyle(decoration: TextDecoration.underline);
return TextSpan(style: composingStyle, text: value);
},
value.composing,
@@ -509,7 +563,9 @@ class ReplacementTextEditingController extends TextEditingController {
for (final TextRange range in sortedRanges) {
if (range.start > previousEndIndex) {
spans.add(
TextSpan(text: value.text.substring(previousEndIndex, range.start)),
TextSpan(
text: value.text.substring(previousEndIndex, range.start),
),
);
}
spans.add(rangeSpanMapping[range]!);
@@ -624,8 +680,9 @@ class ReplacementTextEditingController extends TextEditingController {
}
Set<TextStyle> styles = <TextStyle>{};
List<int> otherEndPoints =
endPoints.getRange(1, endPoints.length).toList();
List<int> otherEndPoints = endPoints
.getRange(1, endPoints.length)
.toList();
for (int i = 0; i < endPoints.length - 1; i++) {
styles = styles.difference(end[endPoints[i]]!);
styles.addAll(start[endPoints[i]]!);
@@ -671,7 +728,8 @@ class ReplacementTextEditingController extends TextEditingController {
final List<TextEditingInlineSpanReplacement> toRemove = [];
final List<TextEditingInlineSpanReplacement> toAdd = [];
for (final TextEditingInlineSpanReplacement replacement in replacements!) {
for (final TextEditingInlineSpanReplacement replacement
in replacements!) {
if (replacement.range.end == selection.start) {
TextStyle? replacementStyle =
(replacement.generator('', const TextRange.collapsed(0))
@@ -689,7 +747,8 @@ class ReplacementTextEditingController extends TextEditingController {
replacements!.remove(replacementToRemove);
}
for (final TextEditingInlineSpanReplacement replacementWithExpandDisabled
for (final TextEditingInlineSpanReplacement
replacementWithExpandDisabled
in toAdd) {
replacements!.add(replacementWithExpandDisabled);
}
@@ -704,7 +763,8 @@ class ReplacementTextEditingController extends TextEditingController {
// should be enabled.
final List<TextStyle> stylesAtSelection = <TextStyle>[];
for (final TextEditingInlineSpanReplacement replacement in replacements!) {
for (final TextEditingInlineSpanReplacement replacement
in replacements!) {
if (selection.isCollapsed) {
if (math.max(replacement.range.start, selection.start) <=
math.min(replacement.range.end, selection.end)) {
@@ -738,7 +798,10 @@ class ReplacementTextEditingController extends TextEditingController {
return stylesAtSelection;
}
void removeReplacementsAtRange(TextRange removalRange, TextStyle? attribute) {
void removeReplacementsAtRange(
TextRange removalRange,
TextStyle? attribute,
) {
final List<TextEditingInlineSpanReplacement> toRemove = [];
final List<TextEditingInlineSpanReplacement> toAdd = [];
@@ -755,8 +818,8 @@ class ReplacementTextEditingController extends TextEditingController {
math.min(replacement.range.end, removalRange.end)) &&
replacementStyle != null) {
if (replacementStyle == attribute!) {
List<TextEditingInlineSpanReplacement>? newReplacements = replacement
.removeRange(removalRange);
List<TextEditingInlineSpanReplacement>? newReplacements =
replacement.removeRange(removalRange);
if (newReplacements != null) {
if (newReplacements.length == 1) {
@@ -782,7 +845,8 @@ class ReplacementTextEditingController extends TextEditingController {
replacements!.add(replacementToAdd);
}
for (TextEditingInlineSpanReplacement replacementToRemove in toRemove) {
for (TextEditingInlineSpanReplacement replacementToRemove
in toRemove) {
replacements!.remove(replacementToRemove);
}
}

View File

@@ -64,7 +64,10 @@ class TextEditingDeltaHistoryView extends StatelessWidget {
Widget _buildTextEditingDeltaViewHeader() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 10.0),
padding: const EdgeInsets.symmetric(
horizontal: 35.0,
vertical: 10.0,
),
child: Row(
children: [
Expanded(
@@ -186,9 +189,15 @@ class TextEditingDeltaView extends StatelessWidget {
children: [
Expanded(child: Text(deltaType)),
Expanded(child: Text(deltaText)),
Expanded(child: Text('(${deltaRange.start}, ${deltaRange.end})')),
Expanded(child: Text('(${newSelection.start}, ${newSelection.end})')),
Expanded(child: Text('(${newComposing.start}, ${newComposing.end})')),
Expanded(
child: Text('(${deltaRange.start}, ${deltaRange.end})'),
),
Expanded(
child: Text('(${newSelection.start}, ${newSelection.end})'),
),
Expanded(
child: Text('(${newComposing.start}, ${newComposing.end})'),
),
],
),
);

View File

@@ -1,5 +1,7 @@
name: simplistic_editor
description: A new Flutter project.
version: 1.0.0+1
resolution: workspace
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
@@ -15,10 +17,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ^3.7.0-0
sdk: ^3.9.0-0
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@@ -30,7 +32,6 @@ dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
@@ -40,7 +41,6 @@ dev_dependencies:
path: ../analysis_defaults
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

View File

@@ -71,7 +71,10 @@ void main() {
);
// About Dialog
expect(find.widgetWithIcon(IconButton, Icons.info_outline), findsOneWidget);
expect(
find.widgetWithIcon(IconButton, Icons.info_outline),
findsOneWidget,
);
await tester.tap(find.widgetWithIcon(IconButton, Icons.info_outline));
await tester.pumpAndSettle();
expect(find.widgetWithText(Center, 'About'), findsOneWidget);