settings: svg background
This commit is contained in:
parent
5311caf494
commit
7a8e8503af
14 changed files with 149 additions and 82 deletions
|
@ -1,4 +1,5 @@
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:aves/widgets/common/data_providers/settings_provider.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/home_page.dart';
|
import 'package:aves/widgets/home_page.dart';
|
||||||
import 'package:aves/widgets/welcome_page.dart';
|
import 'package:aves/widgets/welcome_page.dart';
|
||||||
|
@ -37,34 +38,38 @@ class _AvesAppState extends State<AvesApp> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
// place the settings provider above `MaterialApp`
|
||||||
title: 'Aves',
|
// so it can be used during navigation transitions
|
||||||
theme: ThemeData(
|
return SettingsProvider(
|
||||||
brightness: Brightness.dark,
|
child: MaterialApp(
|
||||||
accentColor: accentColor,
|
title: 'Aves',
|
||||||
scaffoldBackgroundColor: Colors.grey[900],
|
theme: ThemeData(
|
||||||
buttonColor: accentColor,
|
brightness: Brightness.dark,
|
||||||
toggleableActiveColor: accentColor,
|
accentColor: accentColor,
|
||||||
tooltipTheme: TooltipThemeData(
|
scaffoldBackgroundColor: Colors.grey[900],
|
||||||
verticalOffset: 32,
|
buttonColor: accentColor,
|
||||||
),
|
toggleableActiveColor: accentColor,
|
||||||
appBarTheme: AppBarTheme(
|
tooltipTheme: TooltipThemeData(
|
||||||
textTheme: TextTheme(
|
verticalOffset: 32,
|
||||||
headline6: TextStyle(
|
),
|
||||||
fontSize: 20,
|
appBarTheme: AppBarTheme(
|
||||||
fontWeight: FontWeight.bold,
|
textTheme: TextTheme(
|
||||||
fontFamily: 'Concourse Caps',
|
headline6: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: 'Concourse Caps',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
home: FutureBuilder<void>(
|
||||||
home: FutureBuilder<void>(
|
future: _appSetup,
|
||||||
future: _appSetup,
|
builder: (context, snapshot) {
|
||||||
builder: (context, snapshot) {
|
if (snapshot.hasError) return Icon(AIcons.error);
|
||||||
if (snapshot.hasError) return Icon(AIcons.error);
|
if (snapshot.connectionState != ConnectionState.done) return Scaffold();
|
||||||
if (snapshot.connectionState != ConnectionState.done) return Scaffold();
|
return settings.hasAcceptedTerms ? HomePage() : WelcomePage();
|
||||||
return settings.hasAcceptedTerms ? HomePage() : WelcomePage();
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,9 @@ final Settings settings = Settings._private();
|
||||||
|
|
||||||
typedef SettingsCallback = void Function(String key, dynamic oldValue, dynamic newValue);
|
typedef SettingsCallback = void Function(String key, dynamic oldValue, dynamic newValue);
|
||||||
|
|
||||||
class Settings {
|
class Settings extends ChangeNotifier {
|
||||||
static SharedPreferences _prefs;
|
static SharedPreferences _prefs;
|
||||||
|
|
||||||
final ObserverList<SettingsCallback> _listeners = ObserverList<SettingsCallback>();
|
|
||||||
|
|
||||||
Settings._private();
|
Settings._private();
|
||||||
|
|
||||||
// preferences
|
// preferences
|
||||||
|
@ -28,6 +26,7 @@ class Settings {
|
||||||
static const infoMapZoomKey = 'info_map_zoom';
|
static const infoMapZoomKey = 'info_map_zoom';
|
||||||
static const launchPageKey = 'launch_page';
|
static const launchPageKey = 'launch_page';
|
||||||
static const coordinateFormatKey = 'coordinates_format';
|
static const coordinateFormatKey = 'coordinates_format';
|
||||||
|
static const svgBackgroundKey = 'svg_background';
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
_prefs = await SharedPreferences.getInstance();
|
_prefs = await SharedPreferences.getInstance();
|
||||||
|
@ -37,26 +36,6 @@ class Settings {
|
||||||
return _prefs.clear();
|
return _prefs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addListener(SettingsCallback listener) => _listeners.add(listener);
|
|
||||||
|
|
||||||
void removeListener(SettingsCallback listener) => _listeners.remove(listener);
|
|
||||||
|
|
||||||
void notifyListeners(String key, dynamic oldValue, dynamic newValue) {
|
|
||||||
debugPrint('$runtimeType notifyListeners key=$key, old=$oldValue, new=$newValue');
|
|
||||||
if (_listeners != null) {
|
|
||||||
final localListeners = _listeners.toList();
|
|
||||||
for (final listener in localListeners) {
|
|
||||||
try {
|
|
||||||
if (_listeners.contains(listener)) {
|
|
||||||
listener(key, oldValue, newValue);
|
|
||||||
}
|
|
||||||
} catch (exception, stack) {
|
|
||||||
debugPrint('$runtimeType failed to notify listeners with exception=$exception\n$stack');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String get catalogTimeZone => _prefs.getString(catalogTimeZoneKey) ?? '';
|
String get catalogTimeZone => _prefs.getString(catalogTimeZoneKey) ?? '';
|
||||||
|
|
||||||
set catalogTimeZone(String newValue) => setAndNotify(catalogTimeZoneKey, newValue);
|
set catalogTimeZone(String newValue) => setAndNotify(catalogTimeZoneKey, newValue);
|
||||||
|
@ -93,6 +72,10 @@ class Settings {
|
||||||
|
|
||||||
set coordinateFormat(CoordinateFormat newValue) => setAndNotify(coordinateFormatKey, newValue.toString());
|
set coordinateFormat(CoordinateFormat newValue) => setAndNotify(coordinateFormatKey, newValue.toString());
|
||||||
|
|
||||||
|
int get svgBackground => _prefs.getInt(svgBackgroundKey) ?? 0xFFFFFFFF;
|
||||||
|
|
||||||
|
set svgBackground(int newValue) => setAndNotify(svgBackgroundKey, newValue);
|
||||||
|
|
||||||
// convenience methods
|
// convenience methods
|
||||||
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
// ignore: avoid_positional_boolean_parameters
|
||||||
|
@ -133,7 +116,7 @@ class Settings {
|
||||||
_prefs.setBool(key, newValue);
|
_prefs.setBool(key, newValue);
|
||||||
}
|
}
|
||||||
if (oldValue != newValue) {
|
if (oldValue != newValue) {
|
||||||
notifyListeners(key, oldValue, newValue);
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,6 @@ class Constants {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
static const svgBackground = Colors.white;
|
|
||||||
static const svgColorFilter = ColorFilter.mode(svgBackground, BlendMode.dstOver);
|
|
||||||
|
|
||||||
static const List<Dependency> androidDependencies = [
|
static const List<Dependency> androidDependencies = [
|
||||||
Dependency(
|
Dependency(
|
||||||
name: 'CWAC-Document',
|
name: 'CWAC-Document',
|
||||||
|
|
|
@ -87,7 +87,8 @@ class SectionHeader extends StatelessWidget {
|
||||||
// force a higher first line to match leading icon/selector dimension
|
// force a higher first line to match leading icon/selector dimension
|
||||||
style: TextStyle(height: 2.3 * textScaleFactor),
|
style: TextStyle(height: 2.3 * textScaleFactor),
|
||||||
), // 23 hair spaces match a width of 40.0
|
), // 23 hair spaces match a width of 40.0
|
||||||
if (hasTrailing) TextSpan(text: '\u200A' * 17),
|
if (hasTrailing)
|
||||||
|
TextSpan(text: '\u200A' * 17),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: text,
|
text: text,
|
||||||
style: Constants.titleTextStyle,
|
style: Constants.titleTextStyle,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/widgets/common/image_providers/uri_picture_provider.dart';
|
import 'package:aves/widgets/common/image_providers/uri_picture_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class ThumbnailVectorImage extends StatelessWidget {
|
class ThumbnailVectorImage extends StatelessWidget {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
|
@ -23,14 +24,20 @@ class ThumbnailVectorImage extends StatelessWidget {
|
||||||
// so that `SvgPicture` doesn't get aligned by the `Stack` like the overlay icons
|
// so that `SvgPicture` doesn't get aligned by the `Stack` like the overlay icons
|
||||||
width: extent,
|
width: extent,
|
||||||
height: extent,
|
height: extent,
|
||||||
child: SvgPicture(
|
child: Selector<Settings, int>(
|
||||||
UriPicture(
|
selector: (context, s) => s.svgBackground,
|
||||||
uri: entry.uri,
|
builder: (context, svgBackground, child) {
|
||||||
mimeType: entry.mimeType,
|
final colorFilter = ColorFilter.mode(Color(svgBackground), BlendMode.dstOver);
|
||||||
colorFilter: Constants.svgColorFilter,
|
return SvgPicture(
|
||||||
),
|
UriPicture(
|
||||||
width: extent,
|
uri: entry.uri,
|
||||||
height: extent,
|
mimeType: entry.mimeType,
|
||||||
|
colorFilter: colorFilter,
|
||||||
|
),
|
||||||
|
width: extent,
|
||||||
|
height: extent,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return heroTag == null
|
return heroTag == null
|
||||||
|
|
11
lib/widgets/common/borders.dart
Normal file
11
lib/widgets/common/borders.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AvesCircleBorder {
|
||||||
|
static BoxBorder build(BuildContext context) {
|
||||||
|
final subPixel = MediaQuery.of(context).devicePixelRatio > 2;
|
||||||
|
return Border.all(
|
||||||
|
color: Colors.white30,
|
||||||
|
width: subPixel ? 0.5 : 1.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
17
lib/widgets/common/data_providers/settings_provider.dart
Normal file
17
lib/widgets/common/data_providers/settings_provider.dart
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class SettingsProvider extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const SettingsProvider({@required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider<Settings>.value(
|
||||||
|
value: settings,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/widgets/album/empty.dart';
|
import 'package:aves/widgets/album/empty.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
|
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
|
||||||
|
@ -77,12 +77,13 @@ class ImageView extends StatelessWidget {
|
||||||
|
|
||||||
Widget child;
|
Widget child;
|
||||||
if (entry.isSvg) {
|
if (entry.isSvg) {
|
||||||
|
final colorFilter = ColorFilter.mode(Color(settings.svgBackground), BlendMode.dstOver);
|
||||||
child = PhotoView.customChild(
|
child = PhotoView.customChild(
|
||||||
child: SvgPicture(
|
child: SvgPicture(
|
||||||
UriPicture(
|
UriPicture(
|
||||||
uri: entry.uri,
|
uri: entry.uri,
|
||||||
mimeType: entry.mimeType,
|
mimeType: entry.mimeType,
|
||||||
colorFilter: Constants.svgColorFilter,
|
colorFilter: colorFilter,
|
||||||
),
|
),
|
||||||
placeholderBuilder: (context) => loadingBuilder(context, fastThumbnailProvider),
|
placeholderBuilder: (context) => loadingBuilder(context, fastThumbnailProvider),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/services/android_app_service.dart';
|
||||||
import 'package:aves/widgets/common/action_delegates/map_style_dialog.dart';
|
import 'package:aves/widgets/common/action_delegates/map_style_dialog.dart';
|
||||||
|
import 'package:aves/widgets/common/borders.dart';
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
||||||
|
@ -115,10 +116,10 @@ class MapOverlayButton extends StatelessWidget {
|
||||||
return BlurredOval(
|
return BlurredOval(
|
||||||
child: Material(
|
child: Material(
|
||||||
type: MaterialType.circle,
|
type: MaterialType.circle,
|
||||||
color: FullscreenOverlay.backgroundColor,
|
color: kOverlayBackgroundColor,
|
||||||
child: Ink(
|
child: Ink(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: FullscreenOverlay.buildBorder(context),
|
border: AvesCircleBorder.build(context),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
|
|
|
@ -80,7 +80,7 @@ class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
|
||||||
final overlayContentMaxWidth = mqWidth - viewPadding.horizontal - innerPadding.horizontal;
|
final overlayContentMaxWidth = mqWidth - viewPadding.horizontal - innerPadding.horizontal;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: FullscreenOverlay.backgroundColor,
|
color: kOverlayBackgroundColor,
|
||||||
padding: viewInsets + viewPadding.copyWith(top: 0),
|
padding: viewInsets + viewPadding.copyWith(top: 0),
|
||||||
child: FutureBuilder<OverlayMetadata>(
|
child: FutureBuilder<OverlayMetadata>(
|
||||||
future: _detailLoader,
|
future: _detailLoader,
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
|
import 'package:aves/widgets/common/borders.dart';
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class FullscreenOverlay {
|
const kOverlayBackgroundColor = Colors.black26;
|
||||||
static const backgroundColor = Colors.black26;
|
|
||||||
|
|
||||||
static BoxBorder buildBorder(BuildContext context) {
|
|
||||||
final subPixel = MediaQuery.of(context).devicePixelRatio > 2;
|
|
||||||
return Border.all(
|
|
||||||
color: Colors.white30,
|
|
||||||
width: subPixel ? 0.5 : 1.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OverlayButton extends StatelessWidget {
|
class OverlayButton extends StatelessWidget {
|
||||||
final Animation<double> scale;
|
final Animation<double> scale;
|
||||||
|
@ -26,10 +17,10 @@ class OverlayButton extends StatelessWidget {
|
||||||
child: BlurredOval(
|
child: BlurredOval(
|
||||||
child: Material(
|
child: Material(
|
||||||
type: MaterialType.circle,
|
type: MaterialType.circle,
|
||||||
color: FullscreenOverlay.backgroundColor,
|
color: kOverlayBackgroundColor,
|
||||||
child: Ink(
|
child: Ink(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: FullscreenOverlay.buildBorder(context),
|
border: AvesCircleBorder.build(context),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/services/android_app_service.dart';
|
||||||
import 'package:aves/utils/durations.dart';
|
import 'package:aves/utils/durations.dart';
|
||||||
import 'package:aves/utils/time_utils.dart';
|
import 'package:aves/utils/time_utils.dart';
|
||||||
|
import 'package:aves/widgets/common/borders.dart';
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
|
@ -180,8 +181,8 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16) + EdgeInsets.only(bottom: 16),
|
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16) + EdgeInsets.only(bottom: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: FullscreenOverlay.backgroundColor,
|
color: kOverlayBackgroundColor,
|
||||||
border: FullscreenOverlay.buildBorder(context),
|
border: AvesCircleBorder.build(context),
|
||||||
borderRadius: BorderRadius.circular(progressBarBorderRadius),
|
borderRadius: BorderRadius.circular(progressBarBorderRadius),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/settings/coordinate_format.dart';
|
import 'package:aves/widgets/settings/coordinate_format.dart';
|
||||||
import 'package:aves/widgets/settings/launch_page.dart';
|
import 'package:aves/widgets/settings/launch_page.dart';
|
||||||
|
import 'package:aves/widgets/settings/svg_background.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class SettingsPage extends StatelessWidget {
|
class SettingsPage extends StatelessWidget {
|
||||||
|
@ -27,6 +28,14 @@ class SettingsPage extends StatelessWidget {
|
||||||
Flexible(child: LaunchPageSelector()),
|
Flexible(child: LaunchPageSelector()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('SVG background:'),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Flexible(child: SvgBackgroundSelector()),
|
||||||
|
],
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|
43
lib/widgets/settings/svg_background.dart
Normal file
43
lib/widgets/settings/svg_background.dart
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:aves/widgets/common/borders.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SvgBackgroundSelector extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_SvgBackgroundSelectorState createState() => _SvgBackgroundSelectorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SvgBackgroundSelectorState extends State<SvgBackgroundSelector> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const radius = 24.0;
|
||||||
|
return DropdownButton<int>(
|
||||||
|
items: [0xFFFFFFFF, 0xFF000000, 0x00000000].map((selected) {
|
||||||
|
return DropdownMenuItem(
|
||||||
|
value: selected,
|
||||||
|
child: Container(
|
||||||
|
height: radius,
|
||||||
|
width: radius,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(selected),
|
||||||
|
border: AvesCircleBorder.build(context),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: selected == 0
|
||||||
|
? Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 20,
|
||||||
|
color: Colors.white30,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
value: settings.svgBackground,
|
||||||
|
onChanged: (selected) {
|
||||||
|
settings.svgBackground = selected;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue