flutter_bbcode 1.5.0 flutter_bbcode: ^1.5.0 copied to clipboard
A package to display BBCode text in Flutter apps. Manage your own tags or use those of others.
import 'package:example/example_text.dart' as example_texts;
import 'package:flutter/material.dart';
import 'package:flutter_bbcode/flutter_bbcode.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(const MyApp());
}
/// Wrapper class to wrap the style with an hint on what has been changed.
class HintedStyle {
final BBStylesheet? style;
final String hint;
HintedStyle(this.style, this.hint);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const inputs = <String>[
'This is a text without ANY bbcode',
'This text features [b]bold[/b] text.',
'This text [s]is epic[/s] combines features [u][b]bold underlined[/u][/b] text.',
'This text features [url=https://mstruijk.nl]a link[/url].',
example_texts.flutterPackages,
example_texts.flutterLogo,
example_texts.flutterText,
example_texts.flutterDevtools,
example_texts.badBBCode,
example_texts.listBBCode,
example_texts.alignBBCode,
example_texts.simpleListsTags,
];
// Helper method from https://pub.dev/packages/url_launcher
static Future<void> _launchUrl(Uri uri) async {
if (!await launchUrl(uri)) {
throw 'Could not launch $uri';
}
}
// Working URL tag
static final _implementedUrlTag = UrlTag(onTap: (url) {
_launchUrl(Uri.parse(url));
});
static final styles = <HintedStyle>[
HintedStyle(defaultBBStylesheet(), "Default style"),
HintedStyle(
defaultBBStylesheet(
textStyle: const TextStyle(color: Colors.blue, fontSize: 28, height: 1)),
"Default style with text style changed."),
HintedStyle(BBStylesheet(tags: []), "Empty style sheet"),
HintedStyle(defaultBBStylesheet().replaceTag(HeaderTag(3, 6)),
"Default style, replaced H3 tag (smaller)."),
HintedStyle(defaultBBStylesheet().replaceTag(_implementedUrlTag),
"Default style, replaced URL tag with working URL launcher."),
HintedStyle(
BBStylesheet(tags: [
BoldTag(),
ItalicTag(),
]),
"Only Bold and Italic tags"),
];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter BBCode Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(
title: "Example BBCode outputs",
examples: inputs,
styles: styles,
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage(
{Key? key,
required this.title,
required this.examples,
required this.styles})
: super(key: key);
final String title;
final List<String> examples;
final List<HintedStyle?> styles;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentTextIndex = 0;
int _currentStyleIndex = 0;
String get _currentExampleText => widget.examples[_currentTextIndex];
HintedStyle get _currentHintedStyle => widget.styles[_currentStyleIndex]!;
bool selectable = false;
void _showSnack(String text) {
var sm = ScaffoldMessenger.of(context);
sm.clearSnackBars();
sm.showSnackBar(SnackBar(
content: Text(text),
behavior: SnackBarBehavior.fixed,
duration: const Duration(seconds: 2),
));
}
void _selectNextExample() {
setState(() {
_currentTextIndex = (_currentTextIndex + 1) % widget.examples.length;
});
}
void _selectNextStyle() {
setState(() {
_currentStyleIndex = (_currentStyleIndex + 1) % widget.styles.length;
});
_showSnack(_currentHintedStyle.hint);
}
void _toggleSelectableText() {
setState(() {
selectable = !selectable;
});
_showSnack("Selectable text: $selectable");
}
@override
Widget build(BuildContext context) {
var style = _currentHintedStyle.style?.copyWith(selectableText: selectable);
Widget parsedBBCode = BBCodeText(
errorBuilder: (context, error, stack) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Failed to parse BBCode correctly.",
style: TextStyle(color: Colors.red)),
const Text(
"This usually means on of the tags is not properly handling unexpected input.\n"),
Text(error.toString()),
],
);
},
stylesheet: style,
data: _currentExampleText);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Center(child: parsedBBCode),
),
floatingActionButton:
Column(mainAxisAlignment: MainAxisAlignment.end, children: [
FloatingActionButton.small(
onPressed: _selectNextExample,
tooltip: 'Next example text',
child: const Icon(Icons.navigate_next),
),
FloatingActionButton.small(
onPressed: _selectNextStyle,
child: const Icon(Icons.draw),
tooltip: 'Next BBStylesheet',
),
FloatingActionButton.small(
onPressed: _toggleSelectableText,
child: const Icon(Icons.select_all),
tooltip: 'Toggle selectable text',
),
]),
);
}
}