Unverified Commit 6425a3b4 authored by Xilai Zhang's avatar Xilai Zhang Committed by GitHub

[flutter roll] Revert "LinkedText (Linkify)" (#134955)

Reverts flutter/flutter#125927

context: b/300804374

Looks like a g3 fix might involve changing the names of widget on the customer app, and I am not sure if that would be the right approach forward. Putting up a revert to be safe for now.
parent 9dd3e1e6
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
// This example demonstrates highlighting both URLs and Twitter handles with
// different actions and different styles.
void main() {
runApp(const TextLinkerApp());
}
class TextLinkerApp extends StatelessWidget {
const TextLinkerApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Link Twitter Handle Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
super.key,
required this.title
});
final String title;
static const String _text = '@FlutterDev is our Twitter account, or find us at www.flutter.dev';
void _handleTapTwitterHandle(BuildContext context, String linkString) {
final String handleWithoutAt = linkString.substring(1);
final String twitterUriString = 'https://www.twitter.com/$handleWithoutAt';
final Uri? uri = Uri.tryParse(twitterUriString);
if (uri == null) {
throw Exception('Failed to parse $twitterUriString.');
}
_showDialog(context, uri);
}
void _handleTapUrl(BuildContext context, String urlText) {
final Uri? uri = Uri.tryParse(urlText);
if (uri == null) {
throw Exception('Failed to parse $urlText.');
}
_showDialog(context, uri);
}
void _showDialog(BuildContext context, Uri uri) {
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: _TwitterAndUrlLinkedText(
text: _text,
onTapUrl: (String urlString) => _handleTapUrl(context, urlString),
onTapTwitterHandle: (String handleString) => _handleTapTwitterHandle(context, handleString),
),
);
},
),
),
);
}
}
class _TwitterAndUrlLinkedText extends StatefulWidget {
const _TwitterAndUrlLinkedText({
required this.text,
required this.onTapUrl,
required this.onTapTwitterHandle,
});
final String text;
final ValueChanged<String> onTapUrl;
final ValueChanged<String> onTapTwitterHandle;
@override
State<_TwitterAndUrlLinkedText> createState() => _TwitterAndUrlLinkedTextState();
}
class _TwitterAndUrlLinkedTextState extends State<_TwitterAndUrlLinkedText> {
final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
late Iterable<InlineSpan> _linkedSpans;
late final List<TextLinker> _textLinkers;
final RegExp _twitterHandleRegExp = RegExp(r'@[a-zA-Z0-9]{4,15}');
void _disposeRecognizers() {
for (final GestureRecognizer recognizer in _recognizers) {
recognizer.dispose();
}
_recognizers.clear();
}
void _linkSpans() {
_disposeRecognizers();
final Iterable<InlineSpan> linkedSpans = TextLinker.linkSpans(
<TextSpan>[TextSpan(text: widget.text)],
_textLinkers,
);
_linkedSpans = linkedSpans;
}
@override
void initState() {
super.initState();
_textLinkers = <TextLinker>[
TextLinker(
regExp: LinkedText.defaultUriRegExp,
linkBuilder: (String displayString, String linkString) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () => widget.onTapUrl(linkString);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
text: displayString,
color: const Color(0xff0000ee),
recognizer: recognizer,
);
},
),
TextLinker(
regExp: _twitterHandleRegExp,
linkBuilder: (String displayString, String linkString) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () => widget.onTapTwitterHandle(linkString);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
text: displayString,
color: const Color(0xff00aaaa),
recognizer: recognizer,
);
},
),
];
_linkSpans();
}
@override
void didUpdateWidget(_TwitterAndUrlLinkedText oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.text != oldWidget.text
|| widget.onTapUrl != oldWidget.onTapUrl
|| widget.onTapTwitterHandle != oldWidget.onTapTwitterHandle) {
_linkSpans();
}
}
@override
void dispose() {
_disposeRecognizers();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_linkedSpans.isEmpty) {
return const SizedBox.shrink();
}
return Text.rich(
TextSpan(
style: DefaultTextStyle.of(context).style,
children: _linkedSpans.toList(),
),
);
}
}
class _MyInlineLinkSpan extends TextSpan {
_MyInlineLinkSpan({
required String text,
required Color color,
required super.recognizer,
}) : super(
style: TextStyle(
color: color,
decorationColor: color,
decoration: TextDecoration.underline,
),
mouseCursor: SystemMouseCursors.click,
text: text,
);
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
// This example demonstrates creating links in a TextSpan tree instead of a flat
// String.
void main() {
runApp(const TextLinkerApp());
}
class TextLinkerApp extends StatelessWidget {
const TextLinkerApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter TextLinker Span Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
super.key,
required this.title
});
final String title;
void _handleTapTwitterHandle(BuildContext context, String linkString) {
final String handleWithoutAt = linkString.substring(1);
final String twitterUriString = 'https://www.twitter.com/$handleWithoutAt';
final Uri? uri = Uri.tryParse(twitterUriString);
if (uri == null) {
throw Exception('Failed to parse $twitterUriString.');
}
_showDialog(context, uri);
}
void _handleTapUrl(BuildContext context, String urlText) {
final Uri? uri = Uri.tryParse(urlText);
if (uri == null) {
throw Exception('Failed to parse $urlText.');
}
_showDialog(context, uri);
}
void _showDialog(BuildContext context, Uri uri) {
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: _TwitterAndUrlLinkedText(
spans: <InlineSpan>[
TextSpan(
text: '@FlutterDev is our Twitter, or find us at www.',
style: DefaultTextStyle.of(context).style,
children: const <InlineSpan>[
TextSpan(
style: TextStyle(
fontWeight: FontWeight.w800,
),
text: 'flutter',
),
],
),
TextSpan(
text: '.dev',
style: DefaultTextStyle.of(context).style,
),
],
onTapUrl: (String urlString) => _handleTapUrl(context, urlString),
onTapTwitterHandle: (String handleString) => _handleTapTwitterHandle(context, handleString),
),
);
},
),
),
);
}
}
class _TwitterAndUrlLinkedText extends StatefulWidget {
const _TwitterAndUrlLinkedText({
required this.spans,
required this.onTapUrl,
required this.onTapTwitterHandle,
});
final List<InlineSpan> spans;
final ValueChanged<String> onTapUrl;
final ValueChanged<String> onTapTwitterHandle;
@override
State<_TwitterAndUrlLinkedText> createState() => _TwitterAndUrlLinkedTextState();
}
class _TwitterAndUrlLinkedTextState extends State<_TwitterAndUrlLinkedText> {
final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
late Iterable<InlineSpan> _linkedSpans;
late final List<TextLinker> _textLinkers;
final RegExp _twitterHandleRegExp = RegExp(r'@[a-zA-Z0-9]{4,15}');
void _disposeRecognizers() {
for (final GestureRecognizer recognizer in _recognizers) {
recognizer.dispose();
}
_recognizers.clear();
}
void _linkSpans() {
_disposeRecognizers();
final Iterable<InlineSpan> linkedSpans = TextLinker.linkSpans(
widget.spans,
_textLinkers,
);
_linkedSpans = linkedSpans;
}
@override
void initState() {
super.initState();
_textLinkers = <TextLinker>[
TextLinker(
regExp: LinkedText.defaultUriRegExp,
linkBuilder: (String displayString, String linkString) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
// The linkString always contains the full matched text, so that's
// what should be linked to.
..onTap = () => widget.onTapUrl(linkString);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
// The displayString contains only the portion of the matched text
// in a given TextSpan. For example, the bold "flutter" text in
// the overall "www.flutter.dev" URL is in its own TextSpan with its
// bold styling. linkBuilder is called separately for each part.
text: displayString,
color: const Color(0xff0000ee),
recognizer: recognizer,
);
},
),
TextLinker(
regExp: _twitterHandleRegExp,
linkBuilder: (String displayString, String linkString) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () => widget.onTapTwitterHandle(linkString);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
text: displayString,
color: const Color(0xff00aaaa),
recognizer: recognizer,
);
},
),
];
_linkSpans();
}
@override
void didUpdateWidget(_TwitterAndUrlLinkedText oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.spans != oldWidget.spans
|| widget.onTapUrl != oldWidget.onTapUrl
|| widget.onTapTwitterHandle != oldWidget.onTapTwitterHandle) {
_linkSpans();
}
}
@override
void dispose() {
_disposeRecognizers();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_linkedSpans.isEmpty) {
return const SizedBox.shrink();
}
return Text.rich(
TextSpan(
style: DefaultTextStyle.of(context).style,
children: _linkedSpans.toList(),
),
);
}
}
class _MyInlineLinkSpan extends TextSpan {
_MyInlineLinkSpan({
required String text,
required Color color,
required super.recognizer,
}) : super(
style: TextStyle(
color: color,
decorationColor: color,
decoration: TextDecoration.underline,
),
mouseCursor: SystemMouseCursors.click,
text: text,
);
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
// This example demonstrates using LinkedText to make URLs open on tap.
void main() {
runApp(const LinkedTextApp());
}
class LinkedTextApp extends StatelessWidget {
const LinkedTextApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Link Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
super.key,
required this.title,
});
final String title;
static const String _text = 'Check out https://www.flutter.dev, or maybe just flutter.dev or www.flutter.dev.';
void _handleTapUri(BuildContext context, Uri uri) {
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LinkedText(
text: _text,
onTapUri: (Uri uri) => _handleTapUri(context, uri),
),
],
),
);
},
),
),
);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
// This example demonstrates highlighting and linking Twitter handles.
void main() {
runApp(const LinkedTextApp());
}
class LinkedTextApp extends StatelessWidget {
const LinkedTextApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Link Twitter Handle Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({
super.key,
required this.title
});
final String title;
static const String _text = 'Please check out @FlutterDev on Twitter for the latest.';
void _handleTapTwitterHandle(BuildContext context, String linkText) {
final String handleWithoutAt = linkText.substring(1);
final String twitterUriString = 'https://www.twitter.com/$handleWithoutAt';
final Uri? uri = Uri.tryParse(twitterUriString);
if (uri == null) {
throw Exception('Failed to parse $twitterUriString.');
}
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
final RegExp _twitterHandleRegExp = RegExp(r'@[a-zA-Z0-9]{4,15}');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LinkedText.regExp(
text: _text,
regExp: _twitterHandleRegExp,
onTap: (String twitterHandleString) => _handleTapTwitterHandle(context, twitterHandleString),
),
],
),
);
},
),
),
);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
// This example demonstrates highlighting URLs in a TextSpan tree instead of a
// flat String.
void main() {
runApp(const LinkedTextApp());
}
class LinkedTextApp extends StatelessWidget {
const LinkedTextApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter LinkedText.spans Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
super.key,
required this.title,
});
final String title;
void _onTapUri (BuildContext context, Uri uri) {
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LinkedText(
onTapUri: (Uri uri) => _onTapUri(context, uri),
spans: <InlineSpan>[
TextSpan(
text: 'Check out https://www.',
style: DefaultTextStyle.of(context).style,
children: const <InlineSpan>[
TextSpan(
style: TextStyle(
fontWeight: FontWeight.w800,
),
text: 'flutter',
),
],
),
TextSpan(
text: '.dev!',
style: DefaultTextStyle.of(context).style,
),
],
),
],
),
);
},
),
),
);
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
// This example demonstrates highlighting both URLs and Twitter handles with
// different actions and different styles.
void main() {
runApp(const LinkedTextApp());
}
class LinkedTextApp extends StatelessWidget {
const LinkedTextApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Link Twitter Handle Demo'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
super.key,
required this.title
});
final String title;
static const String _text = '@FlutterDev is our Twitter account, or find us at www.flutter.dev';
void _handleTapTwitterHandle(BuildContext context, String linkText) {
final String handleWithoutAt = linkText.substring(1);
final String twitterUriString = 'https://www.twitter.com/$handleWithoutAt';
final Uri? uri = Uri.tryParse(twitterUriString);
if (uri == null) {
throw Exception('Failed to parse $twitterUriString.');
}
_showDialog(context, uri);
}
void _handleTapUrl(BuildContext context, String urlText) {
final Uri? uri = Uri.tryParse(urlText);
if (uri == null) {
throw Exception('Failed to parse $urlText.');
}
_showDialog(context, uri);
}
void _showDialog(BuildContext context, Uri uri) {
// A package like url_launcher would be useful for actually opening the URL
// here instead of just showing a dialog.
Navigator.of(context).push(
DialogRoute<void>(
context: context,
builder: (BuildContext context) => AlertDialog(title: Text('You tapped: $uri')),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return SelectionArea(
child: _TwitterAndUrlLinkedText(
text: _text,
onTapUrl: (String urlString) => _handleTapUrl(context, urlString),
onTapTwitterHandle: (String handleString) => _handleTapTwitterHandle(context, handleString),
),
);
},
),
),
);
}
}
class _TwitterAndUrlLinkedText extends StatefulWidget {
const _TwitterAndUrlLinkedText({
required this.text,
required this.onTapUrl,
required this.onTapTwitterHandle,
});
final String text;
final ValueChanged<String> onTapUrl;
final ValueChanged<String> onTapTwitterHandle;
@override
State<_TwitterAndUrlLinkedText> createState() => _TwitterAndUrlLinkedTextState();
}
class _TwitterAndUrlLinkedTextState extends State<_TwitterAndUrlLinkedText> {
final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
late final List<TextLinker> _textLinkers;
final RegExp _twitterHandleRegExp = RegExp(r'@[a-zA-Z0-9]{4,15}');
void _disposeRecognizers() {
for (final GestureRecognizer recognizer in _recognizers) {
recognizer.dispose();
}
_recognizers.clear();
}
@override
void initState() {
super.initState();
_textLinkers = <TextLinker>[
TextLinker(
regExp: LinkedText.defaultUriRegExp,
linkBuilder: (String displayText, String linkText) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () => widget.onTapUrl(linkText);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
text: displayText,
color: const Color(0xff0000ee),
recognizer: recognizer,
);
},
),
TextLinker(
regExp: _twitterHandleRegExp,
linkBuilder: (String displayText, String linkText) {
final TapGestureRecognizer recognizer = TapGestureRecognizer()
..onTap = () => widget.onTapTwitterHandle(linkText);
_recognizers.add(recognizer);
return _MyInlineLinkSpan(
text: displayText,
color: const Color(0xff00aaaa),
recognizer: recognizer,
);
},
),
];
}
@override
void dispose() {
_disposeRecognizers();
super.dispose();
}
@override
Widget build(BuildContext context) {
return LinkedText.textLinkers(
text: widget.text,
textLinkers: _textLinkers,
);
}
}
class _MyInlineLinkSpan extends TextSpan {
_MyInlineLinkSpan({
required String text,
required Color color,
required super.recognizer,
}) : super(
style: TextStyle(
color: color,
decorationColor: color,
decoration: TextDecoration.underline,
),
mouseCursor: SystemMouseCursors.click,
text: text,
);
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/painting/text_linker/text_linker.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('can tap different link types with different results', (WidgetTester tester) async {
await tester.pumpWidget(
const example.TextLinkerApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(SelectionArea),
matching: find.byType(Text),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getTopLeft(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.twitter.com/FlutterDev'), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.byType(Scaffold)));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: www.flutter.dev'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/painting/text_linker/text_linker.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('can tap different link types with different results', (WidgetTester tester) async {
await tester.pumpWidget(
const example.TextLinkerApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(SelectionArea),
matching: find.byType(Text),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getTopLeft(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.twitter.com/FlutterDev'), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.byType(Scaffold)));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: www.flutter.dev'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/widgets/linked_text/linked_text.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('tapping a link shows a dialog with the tapped uri', (WidgetTester tester) async {
await tester.pumpWidget(
const example.LinkedTextApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(LinkedText),
matching: find.byType(RichText),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.flutter.dev'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/widgets/linked_text/linked_text.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('tapping a Twitter handle shows a dialog with the uri of the user', (WidgetTester tester) async {
await tester.pumpWidget(
const example.LinkedTextApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(LinkedText),
matching: find.byType(RichText),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.twitter.com/FlutterDev'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/widgets/linked_text/linked_text.2.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('can tap links generated from TextSpans', (WidgetTester tester) async {
await tester.pumpWidget(
const example.LinkedTextApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(LinkedText),
matching: find.byType(RichText),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.flutter.dev'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/widgets/linked_text/linked_text.3.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('can tap different link types with different results', (WidgetTester tester) async {
await tester.pumpWidget(
const example.LinkedTextApp(),
);
final Finder textFinder = find.descendant(
of: find.byType(SelectionArea),
matching: find.byType(Text),
);
expect(textFinder, findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getTopLeft(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: https://www.twitter.com/FlutterDev'), findsOneWidget);
await tester.tapAt(tester.getTopLeft(find.byType(Scaffold)));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsNothing);
await tester.tapAt(tester.getCenter(textFinder));
await tester.pumpAndSettle();
expect(find.byType(AlertDialog), findsOneWidget);
expect(find.text('You tapped: www.flutter.dev'), findsOneWidget);
});
}
......@@ -59,7 +59,6 @@ export 'src/painting/shape_decoration.dart';
export 'src/painting/stadium_border.dart';
export 'src/painting/star_border.dart';
export 'src/painting/strut_style.dart';
export 'src/painting/text_linker.dart';
export 'src/painting/text_painter.dart';
export 'src/painting/text_scaler.dart';
export 'src/painting/text_span.dart';
......
This diff is collapsed.
This diff is collapsed.
......@@ -73,7 +73,6 @@ export 'src/widgets/inherited_theme.dart';
export 'src/widgets/interactive_viewer.dart';
export 'src/widgets/keyboard_listener.dart';
export 'src/widgets/layout_builder.dart';
export 'src/widgets/linked_text.dart';
export 'src/widgets/list_wheel_scroll_view.dart';
export 'src/widgets/localizations.dart';
export 'src/widgets/lookup_boundary.dart';
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment