mirror of
https://gitlab.com/comunic/comunicmobile
synced 2025-06-19 08:15:16 +00:00
Start to fix null safety migration errors
This commit is contained in:
@ -5,6 +5,6 @@ import 'package:comunic/helpers/account_helper.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
/// Get the ID of the current user
|
||||
int userID() {
|
||||
int? userID() {
|
||||
return AccountHelper.getCurrentUserID();
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
/// @author Pierre Hubert
|
||||
|
||||
/// Casting helper
|
||||
T cast<T>(dynamic val) => val is T ? val : null;
|
||||
T? cast<T>(dynamic val) => val is T ? val : null;
|
||||
|
||||
/// Turn null and "null" into ""
|
||||
String nullToEmpty(String input) =>
|
||||
String nullToEmpty(String? input) =>
|
||||
input == null || input == "null" ? "" : input;
|
||||
|
@ -6,33 +6,33 @@ import 'package:flutter/material.dart';
|
||||
|
||||
/// This callback return null if the text has to be left as is or a TextSpan
|
||||
/// if it has been sub parsed...
|
||||
typedef ParseCallBack = List<InlineSpan> Function(TextStyle, String);
|
||||
typedef ParseCallBack = List<InlineSpan> Function(TextStyle, String?);
|
||||
|
||||
class BBCodeParsedWidget extends StatelessWidget {
|
||||
final _Element _content;
|
||||
final ParseCallBack parseCallback;
|
||||
final _Element? _content;
|
||||
final ParseCallBack? parseCallback;
|
||||
|
||||
BBCodeParsedWidget({@required String text, this.parseCallback})
|
||||
BBCodeParsedWidget({required String text, this.parseCallback})
|
||||
: assert(text != null),
|
||||
_content = _parse(text);
|
||||
|
||||
_printRecur(_Element el, {int pos = 0}) {
|
||||
String str;
|
||||
str = "".padLeft(pos, "*");
|
||||
if (el.text != null) print(str + el.text);
|
||||
el.children.forEach((f) => _printRecur(f, pos: pos + 1));
|
||||
if (el.text != null) print(str + el.text!);
|
||||
el.children.forEach((f) => _printRecur(f!, pos: pos + 1));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_printRecur(_content);
|
||||
_printRecur(_content!);
|
||||
return RichText(
|
||||
text: _content.toTextSpan(context, parseCallback),
|
||||
text: _content!.toTextSpan(context, parseCallback),
|
||||
);
|
||||
}
|
||||
|
||||
/// Initialize parsing
|
||||
static _Element _parse(String text) {
|
||||
static _Element? _parse(String text) {
|
||||
try {
|
||||
return _parseRecur(
|
||||
text: text,
|
||||
@ -48,19 +48,19 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
|
||||
/// Recursive parsing
|
||||
static _ElementRecur _parseRecur({
|
||||
@required String text,
|
||||
@required _ElementStyle style,
|
||||
@required int pos,
|
||||
String parentTag,
|
||||
required String text,
|
||||
required _ElementStyle style,
|
||||
required int pos,
|
||||
String? parentTag,
|
||||
}) {
|
||||
_Element el = _Element(style: style.clone());
|
||||
|
||||
int lastBeginPos = pos;
|
||||
int? lastBeginPos = pos;
|
||||
int childNumber = 0;
|
||||
bool stop = false;
|
||||
while (!stop && pos < text.length) {
|
||||
while (!stop && pos! < text.length) {
|
||||
//Go to next stop
|
||||
while (!stop && pos < text.length) {
|
||||
while (!stop && pos! < text.length) {
|
||||
if (text[pos] == '[') break;
|
||||
pos++;
|
||||
}
|
||||
@ -68,7 +68,7 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
//Check for text with default style to apply
|
||||
if (lastBeginPos != pos)
|
||||
el.children.add(_Element(
|
||||
style: style.clone(), text: text.substring(lastBeginPos, pos)));
|
||||
style: style.clone(), text: text.substring(lastBeginPos!, pos)));
|
||||
|
||||
//Check if the [ tag is alone
|
||||
if (pos == text.length)
|
||||
@ -89,7 +89,7 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
// Prepare tag detection
|
||||
final closeBrace = text.indexOf("]", pos);
|
||||
String tag = text.substring(pos + 1, closeBrace);
|
||||
String arg;
|
||||
String? arg;
|
||||
final newStyle = style.clone();
|
||||
|
||||
//Check for argument
|
||||
@ -126,7 +126,7 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Pre-parse tag
|
||||
static void _preParseTag(String tag, _ElementStyle style, [String arg]) {
|
||||
static void _preParseTag(String tag, _ElementStyle style, [String? arg]) {
|
||||
switch (tag) {
|
||||
// Bold
|
||||
case "b":
|
||||
@ -153,9 +153,9 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
assert(arg != null);
|
||||
style.color = Color.fromARGB(
|
||||
255,
|
||||
int.tryParse(arg.substring(1, 3), radix: 16),
|
||||
int.tryParse(arg.substring(3, 5), radix: 16),
|
||||
int.tryParse(arg.substring(5, 7), radix: 16),
|
||||
int.tryParse(arg!.substring(1, 3), radix: 16)!,
|
||||
int.tryParse(arg.substring(3, 5), radix: 16)!,
|
||||
int.tryParse(arg.substring(5, 7), radix: 16)!,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -167,18 +167,18 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Post-parse tag
|
||||
static void _postParseTag(String tag, _Element el,
|
||||
{String arg, String parentTag, int childNumber}) {
|
||||
static void _postParseTag(String tag, _Element? el,
|
||||
{String? arg, String? parentTag, int? childNumber}) {
|
||||
// List container
|
||||
if (tag == "ul" || tag == "ol")
|
||||
el.children.insert(0, _Element(style: el.style, text: "\n"));
|
||||
el!.children.insert(0, _Element(style: el.style, text: "\n"));
|
||||
|
||||
// List children
|
||||
if (tag == "li") {
|
||||
el.children.add(_Element(style: el.style, text: "\n"));
|
||||
el!.children.add(_Element(style: el.style, text: "\n"));
|
||||
if (parentTag == "ol")
|
||||
el.children.insert(
|
||||
0, _Element(style: el.style, text: " ${childNumber + 1}. "));
|
||||
0, _Element(style: el.style, text: " ${childNumber! + 1}. "));
|
||||
else
|
||||
el.children.insert(0, _Element(style: el.style, text: " \u2022 "));
|
||||
}
|
||||
@ -187,20 +187,20 @@ class BBCodeParsedWidget extends StatelessWidget {
|
||||
|
||||
/// An element's style
|
||||
class _ElementStyle {
|
||||
TextDecoration decoration;
|
||||
FontWeight fontWeight;
|
||||
FontStyle fontStyle;
|
||||
Color color;
|
||||
TextDecoration? decoration;
|
||||
FontWeight? fontWeight;
|
||||
FontStyle? fontStyle;
|
||||
Color? color;
|
||||
|
||||
/// Generate an empty style
|
||||
_ElementStyle.empty();
|
||||
|
||||
/// Construct an instance of this element
|
||||
_ElementStyle(
|
||||
{@required this.decoration,
|
||||
@required this.fontWeight,
|
||||
@required this.fontStyle,
|
||||
@required this.color});
|
||||
{required this.decoration,
|
||||
required this.fontWeight,
|
||||
required this.fontStyle,
|
||||
required this.color});
|
||||
|
||||
/// Clone this style
|
||||
_ElementStyle clone() {
|
||||
@ -213,7 +213,7 @@ class _ElementStyle {
|
||||
|
||||
/// Generate corresponding TextStyle
|
||||
TextStyle toTextStyle(BuildContext context) {
|
||||
return Theme.of(context).textTheme.bodyText2.copyWith(
|
||||
return Theme.of(context).textTheme.bodyText2!.copyWith(
|
||||
decoration: decoration,
|
||||
fontWeight: fontWeight,
|
||||
fontStyle: fontStyle,
|
||||
@ -224,14 +224,14 @@ class _ElementStyle {
|
||||
/// An element
|
||||
class _Element {
|
||||
/// Note : if text is not null, children must be empty !!!
|
||||
String text;
|
||||
String? text;
|
||||
final _ElementStyle style;
|
||||
final List<_Element> children = [];
|
||||
final List<_Element?> children = [];
|
||||
|
||||
_Element({@required this.style, this.text});
|
||||
_Element({required this.style, this.text});
|
||||
|
||||
/// Turn this element into a TextSpan
|
||||
TextSpan toTextSpan(BuildContext context, ParseCallBack parseCallback) {
|
||||
TextSpan toTextSpan(BuildContext context, ParseCallBack? parseCallback) {
|
||||
assert(text == null || children.length == 0);
|
||||
|
||||
final generatedStyle = this.style.toTextStyle(context);
|
||||
@ -250,14 +250,14 @@ class _Element {
|
||||
text: text,
|
||||
style: generatedStyle,
|
||||
children:
|
||||
children.map((f) => f.toTextSpan(context, parseCallback)).toList(),
|
||||
children.map((f) => f!.toTextSpan(context, parseCallback)).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ElementRecur {
|
||||
final _Element el;
|
||||
final _Element? el;
|
||||
final int finalPos;
|
||||
|
||||
const _ElementRecur({this.el, this.finalPos});
|
||||
const _ElementRecur({this.el, required this.finalPos});
|
||||
}
|
||||
|
@ -10,5 +10,5 @@ import 'intl_utils.dart';
|
||||
|
||||
void copyToClipboard(BuildContext context, String content) {
|
||||
FlutterClipboard.copy(content);
|
||||
snack(context, tr("'%1%' copied to clipboard!", args: {"1": content}));
|
||||
snack(context, tr("'%1%' copied to clipboard!", args: {"1": content})!);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import 'dart:ui';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
String colorToHex(Color color) {
|
||||
String colorToHex(Color? color) {
|
||||
if (color == null) return "";
|
||||
|
||||
return (color.red.toRadixString(16).padLeft(2, '0') +
|
||||
|
@ -9,17 +9,17 @@ import 'package:flutter/material.dart';
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
/// Open a private conversation with a given [userID]
|
||||
Future<bool> openPrivateConversation(BuildContext context, int userID) async {
|
||||
Future<bool> openPrivateConversation(BuildContext context, int? userID) async {
|
||||
try {
|
||||
final convID = await ConversationsHelper().getPrivate(userID);
|
||||
|
||||
// Open the conversation
|
||||
MainController.of(context).openConversationById(convID);
|
||||
MainController.of(context)!.openConversationById(convID);
|
||||
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
print("Failed to find private conversation! $e => $s");
|
||||
showSimpleSnack(context, tr("Could not find a private conversation!"));
|
||||
showSimpleSnack(context, tr("Could not find a private conversation!")!);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ int time() {
|
||||
return (DateTime.now().millisecondsSinceEpoch / 1000).floor();
|
||||
}
|
||||
|
||||
String diffTimeToStr(int amount) {
|
||||
String? diffTimeToStr(int amount) {
|
||||
if (amount < 0) amount = 0;
|
||||
|
||||
// Seconds
|
||||
@ -45,7 +45,7 @@ String diffTimeToStr(int amount) {
|
||||
: tr("%years% years", args: {"years": years.toString()});
|
||||
}
|
||||
|
||||
String diffTimeFromNowToStr(int date) {
|
||||
String? diffTimeFromNowToStr(int date) {
|
||||
return diffTimeToStr(time() - date);
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ String formatDuration(Duration d) =>
|
||||
"${d.inMinutes < 10 ? "0" + d.inMinutes.toString() : d.inMinutes.toString()}:${d.inSeconds % 60 < 10 ? "0" + (d.inSeconds % 60).toString() : (d.inSeconds % 60).toString()}";
|
||||
|
||||
/// Compare two [DateTime] on their date
|
||||
bool isSameDate(DateTime one, DateTime other) {
|
||||
bool isSameDate(DateTime one, DateTime? other) {
|
||||
if (other == null) return false;
|
||||
return one.year == other.year &&
|
||||
one.month == other.month &&
|
||||
|
@ -16,8 +16,8 @@ import '../ui/dialogs/pick_file_dialog.dart';
|
||||
/// Ask the user to choose an image, either from the gallery or using the camera
|
||||
///
|
||||
/// Throws an exception null in case of failure
|
||||
Future<BytesFile> pickImage(BuildContext context,
|
||||
{CropAspectRatio aspectRatio}) async {
|
||||
Future<BytesFile?> pickImage(BuildContext context,
|
||||
{CropAspectRatio? aspectRatio}) async {
|
||||
return await showPickFileDialog(
|
||||
context: context,
|
||||
allowedMimeTypes: ["image/png", "image/jpeg", "image/gif"],
|
||||
|
@ -10,11 +10,10 @@ import 'package:random_string/random_string.dart';
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
|
||||
// Based on https://stackoverflow.com/a/63215502/3781411
|
||||
Future<Uint8List> svgToPng(BuildContext context, String svgString,
|
||||
{int svgWidth, int svgHeight}) async {
|
||||
DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, null);
|
||||
{int? svgWidth, int? svgHeight}) async {
|
||||
DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, "svg");
|
||||
|
||||
// to have a nice rendering it is important to have the exact original height and width,
|
||||
// the easier way to retrieve it is directly from the svg string
|
||||
@ -40,7 +39,7 @@ Future<Uint8List> svgToPng(BuildContext context, String svgString,
|
||||
// Convert to ui.Image. toImage() takes width and height as parameters
|
||||
// you need to find the best size to suit your needs and take into account the screen DPI
|
||||
final image = await picture.toImage(width.toInt(), height.toInt());
|
||||
ByteData bytes = await image.toByteData(format: ImageByteFormat.png);
|
||||
ByteData bytes = (await image.toByteData(format: ImageByteFormat.png))!;
|
||||
|
||||
return bytes.buffer.asUint8List();
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ bool legacyValidatePassword(String s) => s.length > 3;
|
||||
bool validateEmail(String value) {
|
||||
Pattern pattern =
|
||||
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
|
||||
RegExp regex = new RegExp(pattern);
|
||||
RegExp regex = new RegExp(pattern as String);
|
||||
return regex.hasMatch(value);
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,8 @@ import 'package:intl/intl_standalone.dart';
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
String _currLang;
|
||||
Map<String, Map<String, String>> translations;
|
||||
String? _currLang;
|
||||
late Map<String, Map<String, String>> translations;
|
||||
|
||||
/// Initialize translations system
|
||||
///
|
||||
@ -35,22 +35,22 @@ Future<void> initTranslations() async {
|
||||
///
|
||||
/// Then apply the list of [args] to the string, each argument name is
|
||||
/// surrounded by '%'
|
||||
String tr(String string, {Map<String, String> args}) {
|
||||
String? tr(String? string, {Map<String, String?>? args}) {
|
||||
// Check if a translation is available
|
||||
if (_currLang != null &&
|
||||
translations.containsKey(_currLang) &&
|
||||
translations[_currLang].containsKey(string))
|
||||
string = translations[_currLang][string];
|
||||
translations[_currLang!]!.containsKey(string))
|
||||
string = translations[_currLang!]![string!];
|
||||
|
||||
//Apply arguments
|
||||
if (args != null)
|
||||
args.forEach((key, value) => string = string.replaceAll("%$key%", value));
|
||||
args.forEach((key, value) => string = string!.replaceAll("%$key%", value!));
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/// Get current lang, in format aa_BB
|
||||
String/*!*/ get lang => _currLang != null ? _currLang : "en_US";
|
||||
String get lang => _currLang != null ? _currLang! : "en_US";
|
||||
|
||||
|
||||
/// Get short lang format, in format aa
|
||||
|
@ -11,20 +11,20 @@ import 'package:flutter/material.dart';
|
||||
|
||||
/// Pop a page
|
||||
void popPage(BuildContext context) {
|
||||
MainController.of(context).popPage();
|
||||
MainController.of(context)!.popPage();
|
||||
}
|
||||
|
||||
/// Open the page of a user
|
||||
void openUserPage({@required int userID, @required BuildContext context}) {
|
||||
void openUserPage({required int userID, required BuildContext context}) {
|
||||
assert(userID != null);
|
||||
assert(context != null);
|
||||
|
||||
MainController.of(context).openUserPage(userID);
|
||||
MainController.of(context)!.openUserPage(userID);
|
||||
}
|
||||
|
||||
/// Open a post in full screen
|
||||
void openPostFullScreen(int postID, BuildContext context) {
|
||||
MainController.of(context).push(SinglePostRoute(postID: postID));
|
||||
MainController.of(context)!.push(SinglePostRoute(postID: postID));
|
||||
}
|
||||
|
||||
/// Open a virtual directory
|
||||
@ -36,22 +36,22 @@ void openVirtualDirectory(BuildContext context, String directory) async {
|
||||
|
||||
switch (result.type) {
|
||||
case VirtualDirectoryType.USER:
|
||||
openUserPage(context: context, userID: result.id);
|
||||
openUserPage(context: context, userID: result.id!);
|
||||
break;
|
||||
|
||||
case VirtualDirectoryType.GROUP:
|
||||
MainController.of(context).openGroup(result.id);
|
||||
MainController.of(context)!.openGroup(result.id!);
|
||||
break;
|
||||
|
||||
case VirtualDirectoryType.NONE:
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (c) => AlertDialog(
|
||||
title: Text(tr("Error")),
|
||||
content: Text(tr("Could not find related resource!")),
|
||||
title: Text(tr("Error")!),
|
||||
content: Text(tr("Could not find related resource!")!),
|
||||
actions: <Widget>[
|
||||
MaterialButton(
|
||||
child: Text(tr("OK")),
|
||||
child: Text(tr("OK")!),
|
||||
onPressed: () => Navigator.of(c).pop(),
|
||||
)
|
||||
],
|
||||
@ -61,6 +61,6 @@ void openVirtualDirectory(BuildContext context, String directory) async {
|
||||
} catch (e, stack) {
|
||||
print(e);
|
||||
print(stack);
|
||||
showSimpleSnack(context, tr("Could not search virtual directory!"));
|
||||
showSimpleSnack(context, tr("Could not search virtual directory!")!);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ Widget buildCenteredProgressBar() {
|
||||
/// Build and return a full loading page
|
||||
Widget buildLoadingPage({
|
||||
bool showAppBar = false,
|
||||
String routeTitle,
|
||||
String? routeTitle,
|
||||
}) {
|
||||
return Scaffold(
|
||||
appBar: showAppBar
|
||||
@ -36,8 +36,8 @@ Widget buildLoadingPage({
|
||||
}
|
||||
|
||||
/// Build and return an error card
|
||||
Widget buildErrorCard(String message,
|
||||
{List<Widget> actions, bool hide = false}) {
|
||||
Widget buildErrorCard(String? message,
|
||||
{List<Widget>? actions, bool hide = false}) {
|
||||
if (hide) return Container();
|
||||
|
||||
return Theme(
|
||||
@ -59,7 +59,7 @@ Widget buildErrorCard(String message,
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
message,
|
||||
message!,
|
||||
maxLines: null,
|
||||
),
|
||||
),
|
||||
@ -74,9 +74,9 @@ Widget buildErrorCard(String message,
|
||||
}
|
||||
|
||||
/// Show an image with a given [url] in full screen
|
||||
void showImageFullScreen(BuildContext context, String url) {
|
||||
void showImageFullScreen(BuildContext context, String? url) {
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (c) {
|
||||
return FullScreenImageRoute(url);
|
||||
return FullScreenImageRoute(url!);
|
||||
}));
|
||||
}
|
||||
|
||||
@ -92,12 +92,12 @@ void snack(BuildContext context, String message) {
|
||||
/// Show an alert dialog to ask the user to enter a string
|
||||
///
|
||||
/// Returns entered string if the dialog is confirmed, null else
|
||||
Future<String> askUserString({
|
||||
@required BuildContext context,
|
||||
@required String title,
|
||||
@required String message,
|
||||
@required String defaultValue,
|
||||
@required String hint,
|
||||
Future<String?> askUserString({
|
||||
required BuildContext context,
|
||||
required String title,
|
||||
required String message,
|
||||
required String defaultValue,
|
||||
required String hint,
|
||||
int maxLength = 200,
|
||||
int minLength = 1,
|
||||
}) async {
|
||||
@ -135,13 +135,13 @@ class _InputTextDialog extends StatefulWidget {
|
||||
final String hint;
|
||||
|
||||
const _InputTextDialog({
|
||||
Key key,
|
||||
@required this.title,
|
||||
@required this.message,
|
||||
@required this.controller,
|
||||
@required this.maxLength,
|
||||
@required this.minLength,
|
||||
@required this.hint,
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.message,
|
||||
required this.controller,
|
||||
required this.maxLength,
|
||||
required this.minLength,
|
||||
required this.hint,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -172,11 +172,11 @@ class __InputTextDialogState extends State<_InputTextDialog> {
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(tr("Cancel").toUpperCase()),
|
||||
child: Text(tr("Cancel")!.toUpperCase()),
|
||||
onPressed: () => Navigator.pop(c, false),
|
||||
),
|
||||
TextButton(
|
||||
child: Text(tr("OK")),
|
||||
child: Text(tr("OK")!),
|
||||
onPressed: widget.controller.text.length >= widget.minLength
|
||||
? () => Navigator.pop(c, true)
|
||||
: null,
|
||||
@ -189,9 +189,9 @@ class __InputTextDialogState extends State<_InputTextDialog> {
|
||||
///
|
||||
/// Return value of this function is never null
|
||||
Future<bool> showConfirmDialog({
|
||||
@required BuildContext context,
|
||||
String title,
|
||||
@required String message,
|
||||
required BuildContext context,
|
||||
String? title,
|
||||
required String? message,
|
||||
}) async {
|
||||
if (title == null) title = tr("Confirm operation");
|
||||
|
||||
@ -202,17 +202,17 @@ Future<bool> showConfirmDialog({
|
||||
final result = await showDialog<bool>(
|
||||
context: ctx,
|
||||
builder: (c) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(message),
|
||||
title: Text(title!),
|
||||
content: Text(message!),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: Text(tr("Cancel").toUpperCase()),
|
||||
child: Text(tr("Cancel")!.toUpperCase()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: Text(
|
||||
tr("Confirm").toUpperCase(),
|
||||
tr("Confirm")!.toUpperCase(),
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
@ -224,15 +224,15 @@ Future<bool> showConfirmDialog({
|
||||
|
||||
/// Show a simple alert dialog
|
||||
Future<void> showAlert({
|
||||
@required BuildContext context,
|
||||
@required String message,
|
||||
String title,
|
||||
required BuildContext context,
|
||||
required String? message,
|
||||
String? title,
|
||||
}) async =>
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (c) => AlertDialog(
|
||||
title: title == null ? null : Text(title),
|
||||
content: Text(message),
|
||||
content: Text(message!),
|
||||
actions: [CancelDialogButton()],
|
||||
));
|
||||
|
||||
@ -240,28 +240,28 @@ Future<void> showAlert({
|
||||
/// text has already been entered by the user
|
||||
Widget smartInputCounterWidgetBuilder(
|
||||
BuildContext context, {
|
||||
@required int currentLength,
|
||||
@required int maxLength,
|
||||
@required bool isFocused,
|
||||
required int currentLength,
|
||||
required int? maxLength,
|
||||
required bool isFocused,
|
||||
}) =>
|
||||
currentLength > 0 ? Text("$currentLength/$maxLength") : Container();
|
||||
|
||||
/// Parse an HTML String to decode special characters
|
||||
String htmlDecodeCharacters(String input) {
|
||||
String htmlDecodeCharacters(String? input) {
|
||||
if (input == null || input == "") return "";
|
||||
|
||||
return parse(input).documentElement.text;
|
||||
return parse(input).documentElement!.text;
|
||||
}
|
||||
|
||||
const darkAccentColor = Colors.white70;
|
||||
const darkerAccentColor = Colors.white30;
|
||||
|
||||
/// Check out whether dark theme is enabled or not
|
||||
bool darkTheme() => preferences().getBool(PreferencesKeyList.ENABLE_DARK_THEME);
|
||||
bool darkTheme() => preferences()!.getBool(PreferencesKeyList.ENABLE_DARK_THEME);
|
||||
|
||||
/// Check out whether we use tablet mode or not
|
||||
bool isTablet(BuildContext context) =>
|
||||
!preferences().getBool(PreferencesKeyList.FORCE_MOBILE_MODE) &&
|
||||
!preferences()!.getBool(PreferencesKeyList.FORCE_MOBILE_MODE) &&
|
||||
MediaQuery.of(context).size.width >= 1024;
|
||||
|
||||
/// Show about Comunic dialog
|
||||
@ -272,7 +272,7 @@ void showAboutAppDialog(BuildContext context) {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
tr(config().appQuickDescription) ??
|
||||
tr("Comunic is a free and OpenSource social network that respect your privacy."),
|
||||
tr("Comunic is a free and OpenSource social network that respect your privacy.")!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(
|
||||
@ -287,7 +287,7 @@ void showAboutAppDialog(BuildContext context) {
|
||||
|
||||
/// Apply new theme settings
|
||||
void applyNewThemeSettings(BuildContext context) =>
|
||||
context.findAncestorStateOfType<ComunicApplicationState>().refresh();
|
||||
context.findAncestorStateOfType<ComunicApplicationState>()!.refresh();
|
||||
|
||||
/// Parse emojies
|
||||
String parseEmojies(String input) => EmojiParser().emojify(input);
|
||||
|
@ -2,7 +2,6 @@ import 'dart:io';
|
||||
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:comunic/utils/log_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:video_thumbnail/video_thumbnail.dart';
|
||||
|
||||
import 'files_utils.dart';
|
||||
@ -12,16 +11,16 @@ import 'files_utils.dart';
|
||||
/// @author Pierre Hubert
|
||||
|
||||
/// Generate a thumbnail for a video. In case of failure, return null
|
||||
Future<BytesFile> generateVideoThumbnail({
|
||||
@required BytesFile videoFile,
|
||||
int maxWidth,
|
||||
Future<BytesFile?> generateVideoThumbnail({
|
||||
required BytesFile videoFile,
|
||||
required int maxWidth,
|
||||
}) async {
|
||||
File file;
|
||||
File? file;
|
||||
|
||||
try {
|
||||
file = await generateTemporaryFile();
|
||||
|
||||
await file.writeAsBytes(videoFile.bytes);
|
||||
await file.writeAsBytes(videoFile.bytes!);
|
||||
|
||||
return BytesFile(
|
||||
"thumb.png",
|
||||
|
Reference in New Issue
Block a user