Images: null safety++

This commit is contained in:
Vishesh Handa
2021-06-02 09:42:33 +02:00
parent 9acf3d15f6
commit bdd23f44ee
4 changed files with 68 additions and 66 deletions

View File

@ -1,5 +1,3 @@
// @dart=2.9
/* /*
Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de> Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de>
@ -38,7 +36,10 @@ class SettingsDisplayImagesCaptionScreenState
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var settings = Provider.of<Settings>(context); var settings = Provider.of<Settings>(context);
var saveDoNotCaptionTag = (String doNotCaptionTags) { var saveDoNotCaptionTag = (String? doNotCaptionTags) {
if (doNotCaptionTags == null) {
return;
}
settings.doNotCaptionTags = parseTags(doNotCaptionTags); settings.doNotCaptionTags = parseTags(doNotCaptionTags);
settings.save(); settings.save();
}; };
@ -52,8 +53,8 @@ class SettingsDisplayImagesCaptionScreenState
labelText: labelText:
tr('settings.display.images.captions.doNotCaptionTags.label'), tr('settings.display.images.captions.doNotCaptionTags.label'),
), ),
validator: (String value) { validator: (String? value) {
value = value.trim(); value = value!.trim();
if (parseTags(value).isEmpty) { if (parseTags(value).isEmpty) {
return tr( return tr(
'settings.display.images.captions.doNotCaptionTags.validator.empty'); 'settings.display.images.captions.doNotCaptionTags.validator.empty');
@ -74,12 +75,15 @@ class SettingsDisplayImagesCaptionScreenState
initialValue: csvTags(settings.doNotCaptionTags), initialValue: csvTags(settings.doNotCaptionTags),
), ),
onChanged: () { onChanged: () {
if (!doNotCaptionTagsKey.currentState.validate()) return; if (!doNotCaptionTagsKey.currentState!.validate()) return;
saveDoNotCaptionTag(doNotCaptionTagsKey.currentState.value); saveDoNotCaptionTag(doNotCaptionTagsKey.currentState!.value);
}, },
); );
var saveDoThemeTag = (String doCaptionTags) { var saveDoThemeTag = (String? doCaptionTags) {
if (doCaptionTags == null) {
return;
}
settings.doCaptionTags = parseTags(doCaptionTags); settings.doCaptionTags = parseTags(doCaptionTags);
settings.save(); settings.save();
doNotCaptionTagsForm.createState(); doNotCaptionTagsForm.createState();
@ -92,8 +96,8 @@ class SettingsDisplayImagesCaptionScreenState
hintText: tr('settings.display.images.captions.doCaptionTags.hint'), hintText: tr('settings.display.images.captions.doCaptionTags.hint'),
labelText: tr('settings.display.images.captions.doCaptionTags.label'), labelText: tr('settings.display.images.captions.doCaptionTags.label'),
), ),
validator: (String value) { validator: (String? value) {
if (parseTags(value).isEmpty) { if (parseTags(value!).isEmpty) {
return tr( return tr(
'settings.display.images.captions.doCaptionTags.validator.empty'); 'settings.display.images.captions.doCaptionTags.validator.empty');
} }
@ -113,8 +117,8 @@ class SettingsDisplayImagesCaptionScreenState
initialValue: csvTags(settings.doCaptionTags), initialValue: csvTags(settings.doCaptionTags),
), ),
onChanged: () { onChanged: () {
if (!doCaptionTagsKey.currentState.validate()) return; if (!doCaptionTagsKey.currentState!.validate()) return;
saveDoThemeTag(doCaptionTagsKey.currentState.value); saveDoThemeTag(doCaptionTagsKey.currentState!.value);
}, },
); );

View File

@ -1,4 +1,4 @@
// @dart=2.9
/* /*
Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de> Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de>
@ -40,8 +40,8 @@ class SettingsDisplayImagesThemingScreenState
Widget build(BuildContext context) { Widget build(BuildContext context) {
var settings = Provider.of<Settings>(context); var settings = Provider.of<Settings>(context);
var saveDoNotThemeTag = (String doNotThemeTags) { var saveDoNotThemeTag = (String? doNotThemeTags) {
settings.doNotThemeTags = parseTags(doNotThemeTags); settings.doNotThemeTags = parseTags(doNotThemeTags!);
settings.save(); settings.save();
}; };
var doNotThemeTagsForm = Form( var doNotThemeTagsForm = Form(
@ -52,8 +52,8 @@ class SettingsDisplayImagesThemingScreenState
hintText: tr('settings.display.images.theming.doNotThemeTags.hint'), hintText: tr('settings.display.images.theming.doNotThemeTags.hint'),
labelText: tr('settings.display.images.theming.doNotThemeTags.label'), labelText: tr('settings.display.images.theming.doNotThemeTags.label'),
), ),
validator: (String value) { validator: (String? value) {
value = value.trim(); value = value!.trim();
if (parseTags(value).isEmpty) { if (parseTags(value).isEmpty) {
return tr( return tr(
'settings.display.images.theming.doNotThemeTags.validator.empty'); 'settings.display.images.theming.doNotThemeTags.validator.empty');
@ -72,13 +72,13 @@ class SettingsDisplayImagesThemingScreenState
initialValue: csvTags(settings.doNotThemeTags), initialValue: csvTags(settings.doNotThemeTags),
), ),
onChanged: () { onChanged: () {
if (!doNotThemeTagsKey.currentState.validate()) return; if (!doNotThemeTagsKey.currentState!.validate()) return;
saveDoNotThemeTag(doNotThemeTagsKey.currentState.value); saveDoNotThemeTag(doNotThemeTagsKey.currentState!.value);
}, },
); );
var saveDoThemeTag = (String doThemeTags) { var saveDoThemeTag = (String? doThemeTags) {
settings.doThemeTags = parseTags(doThemeTags); settings.doThemeTags = parseTags(doThemeTags!);
settings.save(); settings.save();
}; };
var doThemeTagsForm = Form( var doThemeTagsForm = Form(
@ -89,8 +89,8 @@ class SettingsDisplayImagesThemingScreenState
hintText: tr('settings.display.images.theming.doThemeTags.hint'), hintText: tr('settings.display.images.theming.doThemeTags.hint'),
labelText: tr('settings.display.images.theming.doThemeTags.label'), labelText: tr('settings.display.images.theming.doThemeTags.label'),
), ),
validator: (String value) { validator: (String? value) {
if (parseTags(value).isEmpty) { if (parseTags(value!).isEmpty) {
return tr( return tr(
'settings.display.images.theming.doThemeTags.validator.empty'); 'settings.display.images.theming.doThemeTags.validator.empty');
} }
@ -110,8 +110,8 @@ class SettingsDisplayImagesThemingScreenState
initialValue: csvTags(settings.doThemeTags), initialValue: csvTags(settings.doThemeTags),
), ),
onChanged: () { onChanged: () {
if (!doThemeTagsKey.currentState.validate()) return; if (!doThemeTagsKey.currentState!.validate()) return;
saveDoThemeTag(doThemeTagsKey.currentState.value); saveDoThemeTag(doThemeTagsKey.currentState!.value);
}, },
); );
var body = ListView(children: <Widget>[ var body = ListView(children: <Widget>[

View File

@ -1,5 +1,3 @@
// @dart=2.9
/* /*
Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de> Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de>
@ -35,19 +33,21 @@ import 'package:gitjournal/widgets/images/image_details.dart';
import 'package:gitjournal/widgets/images/themable_image.dart'; import 'package:gitjournal/widgets/images/themable_image.dart';
class MarkdownImage extends StatelessWidget { class MarkdownImage extends StatelessWidget {
final double width; final double? width;
final double height; final double? height;
final String altText; final String altText;
final String tooltip; final String tooltip;
// FIXME: Avoid using dynamic!
final Future<dynamic> data; final Future<dynamic> data;
MarkdownImage._( MarkdownImage._(
this.data, this.width, this.height, String altText, String tooltip) this.data, this.width, this.height, String? altText, String? tooltip)
: altText = altText ?? "", : altText = altText ?? "",
tooltip = tooltip ?? ""; tooltip = tooltip ?? "";
factory MarkdownImage(Uri uri, String imageDirectory, factory MarkdownImage(Uri uri, String imageDirectory,
{double width, double height, String altText, String titel}) { {double? width, double? height, String? altText, String? titel}) {
final file = ((uri.isScheme("http") || uri.isScheme("https")) final file = ((uri.isScheme("http") || uri.isScheme("https"))
? DefaultCacheManager().getSingleFile(uri.toString()) ? DefaultCacheManager().getSingleFile(uri.toString())
: Future.sync( : Future.sync(
@ -118,7 +118,7 @@ class MarkdownImage extends StatelessWidget {
), ),
Text( Text(
errorMessage, errorMessage,
style: theme.textTheme.bodyText1 style: theme.textTheme.bodyText1!
.copyWith(color: theme.errorColor), .copyWith(color: theme.errorColor),
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, maxLines: 2,
@ -134,7 +134,7 @@ class MarkdownImage extends StatelessWidget {
Widget im; Widget im;
if (snapshot.data is String) { if (snapshot.data is String) {
im = ThemableImage.svg( im = ThemableImage.svg(
snapshot.data, snapshot.data as String,
width: width ?? MediaQuery.of(context).size.width, width: width ?? MediaQuery.of(context).size.width,
height: height, height: height,
themingMethod: override == ThemeOverride.No || themingMethod: override == ThemeOverride.No ||
@ -167,7 +167,7 @@ class MarkdownImage extends StatelessWidget {
); );
} else { } else {
im = ThemableImage.image( im = ThemableImage.image(
snapshot.data, snapshot.data as File,
width: width, width: width,
height: height, height: height,
doTheme: (settings.themeRasterGraphics || doTheme: (settings.themeRasterGraphics ||
@ -185,7 +185,8 @@ class MarkdownImage extends StatelessWidget {
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => ImageDetails( builder: (context) => ImageDetails(
im, captionText(context, altText, tooltip)))); im as ThemableImage,
captionText(context, altText, tooltip))));
}, },
); );
} }
@ -215,7 +216,7 @@ class MarkdownImage extends StatelessWidget {
} }
Color getOverlayBackgroundColor(BuildContext context, Color getOverlayBackgroundColor(BuildContext context,
{Color light, Color dark}) { {Color? light, Color? dark}) {
final settings = Provider.of<Settings>(context); final settings = Provider.of<Settings>(context);
final theme = Theme.of(context); final theme = Theme.of(context);
return theme.brightness == Brightness.dark return theme.brightness == Brightness.dark

View File

@ -1,5 +1,3 @@
// @dart=2.9
/* /*
Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de> Copyright 2020-2021 Roland Fredenhagen <important@van-fredenhagen.de>
@ -25,9 +23,9 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
class ThemableImage extends StatelessWidget { class ThemableImage extends StatelessWidget {
final double width; final double? width;
final double height; final double? height;
final File file; final File? file;
final String string; final String string;
final ThemingMethod themingMethod; final ThemingMethod themingMethod;
final ThemingCondition themingCondition; final ThemingCondition themingCondition;
@ -57,12 +55,12 @@ class ThemableImage extends StatelessWidget {
ThemableImage.from( ThemableImage.from(
ThemableImage ti, { ThemableImage ti, {
double width, double? width,
double height, double? height,
ThemingMethod themingMethod, ThemingMethod? themingMethod,
ThemingCondition themingCondition, ThemingCondition? themingCondition,
ColorCondition colorCondition, ColorCondition? colorCondition,
Color bg, Color? bg,
}) : file = ti.file, }) : file = ti.file,
string = ti.string, string = ti.string,
width = width ?? ti.width, width = width ?? ti.width,
@ -76,7 +74,7 @@ class ThemableImage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget image; Widget image;
if (file != null) { if (file != null) {
image = Image.file(file, width: width, height: height); image = Image.file(file!, width: width, height: height);
} else if (string.isNotEmpty) { } else if (string.isNotEmpty) {
image = SvgPicture( image = SvgPicture(
StringPicture( StringPicture(
@ -104,7 +102,7 @@ class ThemableImage extends StatelessWidget {
!_hasBackground(svgRoot, svgRoot.viewport.viewBox.width, !_hasBackground(svgRoot, svgRoot.viewport.viewBox.width,
svgRoot.viewport.viewBox.height) || svgRoot.viewport.viewBox.height) ||
themingMethod == ThemingMethod.wToBg) { themingMethod == ThemingMethod.wToBg) {
svgRoot = _themeDrawable(svgRoot, (Color color) { svgRoot = _themeDrawable(svgRoot, (Color? color) {
switch (themingMethod) { switch (themingMethod) {
case ThemingMethod.wToBg: case ThemingMethod.wToBg:
return color == Colors.white ? bg : color; return color == Colors.white ? bg : color;
@ -114,7 +112,7 @@ class ThemableImage extends StatelessWidget {
return color; return color;
case ThemingMethod.invertBrightness: case ThemingMethod.invertBrightness:
final hslColor = HSLColor.fromColor(color); final hslColor = HSLColor.fromColor(color!);
final backGroundLightness = HSLColor.fromColor(bg).lightness; final backGroundLightness = HSLColor.fromColor(bg).lightness;
switch (colorCondition) { switch (colorCondition) {
case ColorCondition.all: case ColorCondition.all:
@ -142,8 +140,7 @@ class ThemableImage extends StatelessWidget {
return color; return color;
} }
} }
return color; }) as DrawableRoot;
});
} }
final Picture pic = svgRoot.toPicture( final Picture pic = svgRoot.toPicture(
@ -178,7 +175,7 @@ bool _hasBackground(Drawable draw, double width, double height,
if (draw is DrawableShape) { if (draw is DrawableShape) {
final drawShape = draw; final drawShape = draw;
return drawShape.style.fill != null && return drawShape.style.fill != null &&
drawShape.style.fill.color.alpha > minAlpha && drawShape.style.fill!.color!.alpha > minAlpha &&
[ [
Offset(width * maxBorder, height * maxBorder), Offset(width * maxBorder, height * maxBorder),
Offset(width - width * maxBorder, height * maxBorder), Offset(width - width * maxBorder, height * maxBorder),
@ -189,7 +186,7 @@ bool _hasBackground(Drawable draw, double width, double height,
// TODO Allow for two shapes to be the background together // TODO Allow for two shapes to be the background together
if (draw is DrawableParent) { if (draw is DrawableParent) {
final drawParent = draw; final drawParent = draw;
return drawParent.children.any((element) => _hasBackground( return drawParent.children!.any((element) => _hasBackground(
element, width, height, element, width, height,
minAlpha: minAlpha, maxBorder: maxBorder, maxDepth: maxDepth - 1)); minAlpha: minAlpha, maxBorder: maxBorder, maxDepth: maxDepth - 1));
} }
@ -198,28 +195,28 @@ bool _hasBackground(Drawable draw, double width, double height,
} }
Drawable _themeDrawable( Drawable _themeDrawable(
Drawable draw, Color Function(Color color) transformColor) { Drawable draw, Color? Function(Color? color) transformColor) {
if (draw is DrawableStyleable && !(draw is DrawableGroup)) { if (draw is DrawableStyleable && !(draw is DrawableGroup)) {
final DrawableStyleable drawStylable = draw; final DrawableStyleable drawStylable = draw;
draw = drawStylable.mergeStyle(DrawableStyle( draw = drawStylable.mergeStyle(DrawableStyle(
stroke: drawStylable.style.stroke != null && stroke: drawStylable.style!.stroke != null &&
drawStylable.style.stroke.color != null drawStylable.style!.stroke!.color != null
? DrawablePaint.merge( ? DrawablePaint.merge(
DrawablePaint(drawStylable.style.stroke.style, DrawablePaint(drawStylable.style!.stroke!.style,
color: transformColor(drawStylable.style.stroke.color)), color: transformColor(drawStylable.style!.stroke!.color)),
drawStylable.style.stroke) drawStylable.style!.stroke)
: null, : null,
fill: drawStylable.style.fill != null && fill: drawStylable.style!.fill != null &&
drawStylable.style.fill.color != null drawStylable.style!.fill!.color != null
? DrawablePaint.merge( ? DrawablePaint.merge(
DrawablePaint(drawStylable.style.fill.style, DrawablePaint(drawStylable.style!.fill!.style,
color: transformColor(drawStylable.style.fill.color)), color: transformColor(drawStylable.style!.fill!.color)),
drawStylable.style.fill) drawStylable.style!.fill)
: null)); : null));
} }
if (draw is DrawableParent) { if (draw is DrawableParent) {
final DrawableParent drawParent = draw; final DrawableParent drawParent = draw;
final children = drawParent.children final children = drawParent.children!
.map((e) => _themeDrawable(e, transformColor)) .map((e) => _themeDrawable(e, transformColor))
.toList(growable: false); .toList(growable: false);
if (draw is DrawableRoot) { if (draw is DrawableRoot) {