From d9efad47f8fffb343a70f33cd72c185ee0baa83c Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Tue, 16 Apr 2024 22:54:57 +0200 Subject: [PATCH] WIP geopoints filter on map --- lib/Helpers/translations.dart | 30 ++-- lib/Screens/MainView/main_view.dart | 2 + lib/Screens/Map/geo_point_filter.dart | 194 ++++++++++++++++++-------- lib/Screens/Map/google_map_view.dart | 21 +++ lib/Screens/Map/map_box_view.dart | 20 ++- lib/Screens/Map/map_view.dart | 88 +++++++----- lib/Screens/Map/marker_view.dart | 3 +- lib/main.dart | 9 +- 8 files changed, 250 insertions(+), 117 deletions(-) diff --git a/lib/Helpers/translations.dart b/lib/Helpers/translations.dart index b6e196e..17544e3 100644 --- a/lib/Helpers/translations.dart +++ b/lib/Helpers/translations.dart @@ -14,7 +14,8 @@ List translations = [ "sunday": "Dimanche", "menu": "Menu", "quiz.seeResponses": "Voir les réponses", - "quiz.restart": "Recommencer" + "quiz.restart": "Recommencer", + "map.search": "Rechercher" }), Translation(language: "EN", data: { "weather.hourly": "Hourly", @@ -29,7 +30,8 @@ List translations = [ "sunday": "Sunday", "menu": "Menu", "quiz.seeResponses": "See the answers", - "quiz.restart": "Restart" + "quiz.restart": "Restart", + "map.search": "Search" }), Translation(language: "DE", data: { "weather.hourly": "Nächste Stunden", @@ -44,7 +46,8 @@ List translations = [ "sunday": "Sonntag", "menu": "Speisekarte", "quiz.seeResponses": "Sehen Sie sich die Antworten an", - "quiz.restart": "Neu starten" + "quiz.restart": "Neu starten", + "map.search": "Suchen" }), Translation(language: "NL", data: { "weather.hourly": "Volgende uren", @@ -59,7 +62,8 @@ List translations = [ "sunday": "Zondag", "menu": "Menu", "quiz.seeResponses": "Zie de antwoorden", - "quiz.restart": "Herstarten" + "quiz.restart": "Herstarten", + "map.search": "Zoeken" }), Translation(language: "IT", data: { "weather.hourly": "Le prossime ore", @@ -74,7 +78,8 @@ List translations = [ "sunday": "Domenica", "menu": "Menù", "quiz.seeResponses": "Vedi le risposte", - "quiz.restart": "Ricomincia" + "quiz.restart": "Ricomincia", + "map.search": "Cerca" }), Translation(language: "ES", data: { "weather.hourly": "Próximas horas", @@ -89,7 +94,8 @@ List translations = [ "sunday": "Domingo", "menu": "Menú", "quiz.seeResponses": "Ver las respuestas", - "quiz.restart": "Reanudar" + "quiz.restart": "Reanudar", + "map.search": "Buscar" }), Translation(language: "PL", data: { "weather.hourly": "Następne godziny", @@ -104,7 +110,8 @@ List translations = [ "sunday": "Niedziela", "menu": "Menu", "quiz.seeResponses": "Zobacz odpowiedzi", - "quiz.restart": "Uruchom ponownie" + "quiz.restart": "Uruchom ponownie", + "map.search": "Szukaj" }), Translation(language: "CN", data: { "weather.hourly": "接下来的几个小时", @@ -119,7 +126,8 @@ List translations = [ "sunday": "星期日", "menu": "菜单", "quiz.seeResponses": "查看答案", - "quiz.restart": "重新开始" + "quiz.restart": "重新开始", + "map.search": "搜索" }), Translation(language: "UK", data: { "weather.hourly": "Наступні години", @@ -134,7 +142,8 @@ List translations = [ "sunday": "Неділя", "menu": "Меню", "quiz.seeResponses": "Подивіться відповіді", - "quiz.restart": "Перезапустіть" + "quiz.restart": "Перезапустіть", + "map.search": "Шукати" }), Translation(language: "AR", data: { "weather.hourly": "الساعات القادمة", @@ -149,6 +158,7 @@ List translations = [ "sunday": "الأحد", "menu": "القائمة", "quiz.seeResponses": "انظر الإجابات", - "quiz.restart": "إعادة تشغيل" + "quiz.restart": "إعادة تشغيل", + "map.search": "بحث" }), ]; \ No newline at end of file diff --git a/lib/Screens/MainView/main_view.dart b/lib/Screens/MainView/main_view.dart index 02ce751..554aad4 100644 --- a/lib/Screens/MainView/main_view.dart +++ b/lib/Screens/MainView/main_view.dart @@ -154,6 +154,7 @@ class _MainViewWidget extends State { break; } return Scaffold( + resizeToAvoidBottomInset: false, body: SingleChildScrollView( child: Container( height: size.height, @@ -328,6 +329,7 @@ class _MainViewWidget extends State { ); } else { return Scaffold( + resizeToAvoidBottomInset: false, body: Container( height: size.height, width: size.width, diff --git a/lib/Screens/Map/geo_point_filter.dart b/lib/Screens/Map/geo_point_filter.dart index c8e7a99..0d5b483 100644 --- a/lib/Screens/Map/geo_point_filter.dart +++ b/lib/Screens/Map/geo_point_filter.dart @@ -1,12 +1,14 @@ import 'dart:ui'; //import 'package:animated_tree_view/animated_tree_view.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:generate_tree/generate_tree.dart'; import 'package:generate_tree/treeNode.dart'; import 'package:manager_api/api.dart'; import 'package:provider/provider.dart'; +import 'package:tablet_app/Helpers/translationHelper.dart'; import 'package:tablet_app/Models/tabletContext.dart'; import 'package:tablet_app/app_context.dart'; import 'package:tablet_app/constants.dart'; @@ -29,19 +31,28 @@ class _GeoPointFilterState extends State { //late List treeNodes; late List _filteredNodes; late ValueNotifier _searchTextNotifier; + final TextEditingController _searchController = TextEditingController(); + FocusNode focusNode = new FocusNode(); @override void initState() { super.initState(); _searchTextNotifier = ValueNotifier(''); + //_searchTextNotifier.addListener(_onSearchTextChanged); // Cause the setState ? // Construire les nœuds de l'arborescence en utilisant les catégories et les géopoints //treeNodes = buildTreeNodes(widget.categories, widget.geoPoints); _filteredNodes = buildTreeNodes(widget.categories, widget.geoPoints); } + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + void _onSearchTextChanged() { - filterNodes(_searchTextNotifier.value); + //filterNodes(_searchTextNotifier.value); } List buildTreeNodes(List categories, List geoPoints) { @@ -53,7 +64,7 @@ class _GeoPointFilterState extends State { id: category.id ?? 0, title: parse(category.label!.firstWhere((l) => l.language == widget.language).value!).documentElement!.text, children: [], - checked: false, + checked: true, // default true show: false, pid: 0, commonID: 0, @@ -63,9 +74,9 @@ class _GeoPointFilterState extends State { for (var geoPoint in geoPoints) { if (geoPoint.categorieId == category.id) { TreeNode geoPointNode = TreeNode( - id: geoPoint.id ?? 0, + id: int.parse(geoPoint.latitude!.substring(0,10).replaceAll(".", "")+geoPoint.longitude!.substring(0,10).replaceAll(".", "")), title: parse(geoPoint.title!.firstWhere((l) => l.language == widget.language).value!).documentElement!.text, - checked: false, + checked: true, // default true show: false, children: [], pid: 0, @@ -81,28 +92,60 @@ class _GeoPointFilterState extends State { return nodes; } - void filterNodes(String searchText) { - //setState(() { - _searchTextNotifier.value = searchText; - //_searchText = searchText; - // Filtrer les nœuds en fonction du texte de recherche - _filteredNodes = _searchTextNotifier.value.isEmpty + void filterNodes() { + String searchText = _searchController.text; + setState(() { + _filteredNodes = searchText.isEmpty ? buildTreeNodes(widget.categories, widget.geoPoints) - : _filterNodesBySearchText(_searchTextNotifier.value); - //}); + : _filterNodesBySearchText(searchText); + + // if unfocus, then + if(searchText.isEmpty && !focusNode.hasFocus) { + // widget.filteredPoints = //todo + sendFilteredGeoPoint(); + } + }); + } + + sendFilteredGeoPoint() { + List checkedGeoPoints = []; + // Parcourez les nœuds filtrés pour récupérer les GeoPointDTO correspondants qui sont cochés + for (var node in _filteredNodes) { + if (node.children.isNotEmpty) { + for (var childNode in node.children) { + if (childNode.checked) { + checkedGeoPoints.add(widget.geoPoints.firstWhere((point) => int.parse(point.latitude!.substring(0,10).replaceAll(".", "")+point.longitude!.substring(0,10).replaceAll(".", "")) == childNode.id)); + } + } + } + } + + // Passez la liste des GeoPointDTO cochés à la fonction filteredPoints + widget.filteredPoints(checkedGeoPoints); } List _filterNodesBySearchText(String searchText) { List filteredNodes = []; for (var node in buildTreeNodes(widget.categories, widget.geoPoints)) { - if (node.title.toLowerCase().contains(searchText.toLowerCase())) { - // Si le titre du nœud contient le texte de recherche, ajoutez-le aux nœuds filtrés + if (_nodeOrChildrenContainsText(node, searchText)) { filteredNodes.add(node); } } return filteredNodes; } + bool _nodeOrChildrenContainsText(TreeNode node, String searchText) { + if (node.title.toLowerCase().contains(searchText)) { + return true; + } + for (var childNode in node.children) { + if (_nodeOrChildrenContainsText(childNode, searchText)) { + return true; + } + } + return false; + } + @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; @@ -112,54 +155,85 @@ class _GeoPointFilterState extends State { var primaryColor = tabletAppContext.configuration != null ? tabletAppContext.configuration!.primaryColor != null ? new Color(int.parse(tabletAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kTestSecondColor : kTestSecondColor; - return Container( - decoration: BoxDecoration( - color: kBackgroundColor.withOpacity(0.78), - borderRadius: BorderRadius.all(Radius.circular(tabletAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - TextFormField( - //initialValue: 'Input text', - decoration: InputDecoration( - labelText: 'Recherche', - suffixIcon: Icon( - Icons.search, + return Positioned( + left: 5, + top: 35, + child: Container( + width: size.width * 0.3, + decoration: BoxDecoration( + color: kBackgroundColor.withOpacity(0.78), + borderRadius: BorderRadius.all(Radius.circular(tabletAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 8.0, top: 4.0), + child: TextField( + focusNode: focusNode, + controller: _searchController, + onChanged: (value) { + filterNodes(); + }, + cursorColor: Colors.black, + style: TextStyle(color: Colors.black), + decoration: InputDecoration( + labelText: TranslationHelper.getFromLocale("map.search", appContext.getContext()), + labelStyle: TextStyle( + color: focusNode.hasFocus ? primaryColor : Colors.black + ), + focusColor: primaryColor, + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(tabletAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), + borderSide: BorderSide(color: primaryColor)), + //labelStyle: TextStyle(color: primaryColor), + suffixIcon: IconButton( + icon: _searchController.text.isNotEmpty ? Icon(Icons.close) : Icon(Icons.search), + onPressed: () { + if(_searchController.text.isNotEmpty) { + _searchController.text = ""; + } + filterNodes(); + if(_searchController.text.isNotEmpty) { + focusNode.unfocus(); + } + }, + ), + ), ), ), - onChanged: filterNodes, - ), - ValueListenableBuilder( - valueListenable: _searchTextNotifier, - builder: (context, value, _) { - return Container( - color: Colors.greenAccent, - height: size.height * 0.7, - width: size.width * 0.3, - child: GenerateTree( - data: _filteredNodes, - selectOneToAll: true, - textColor: Colors.black, - onChecked: (node, checked, commonID) { - if(checked) { - //node. - //var test = - //selectedGeoPoints.add(); - } - print('isChecked : $checked'); - print('common Node ID : ${commonID}'); - print('children node data : ${node.children.map((e) => '${e.title}')}'); - // Todo update selection - }, - checkBoxColor: primaryColor, - childrenPadding: EdgeInsets.only(left: 20, top: 10, right: 0, bottom: 10), - ), - ); - } - ), - ], + ValueListenableBuilder( + valueListenable: _searchTextNotifier, + builder: (context, value, _) { + return Container( + //color: Colors.greenAccent, + height: size.height * 0.65, + width: size.width * 0.3, + child: GenerateTree( + data: _filteredNodes, + selectOneToAll: true, + textColor: Colors.black, + onChecked: (node, checked, commonID) { + if(checked) { + //node. + //var test = + //selectedGeoPoints.add(); + } + print('isChecked : $checked'); + print('common Node ID : ${commonID}'); + print('children node data : ${node.children.map((e) => '${e.title}')}'); + // Todo update selection + sendFilteredGeoPoint(); + }, + checkBoxColor: primaryColor, + childrenPadding: EdgeInsets.only(left: 20, top: 10, right: 0, bottom: 10), + ), + ); + } + ), + ], + ), ), ), ); diff --git a/lib/Screens/Map/google_map_view.dart b/lib/Screens/Map/google_map_view.dart index 2f0b42b..f88a067 100644 --- a/lib/Screens/Map/google_map_view.dart +++ b/lib/Screens/Map/google_map_view.dart @@ -8,8 +8,11 @@ import 'package:manager_api/api.dart'; import 'package:provider/provider.dart'; import 'package:tablet_app/Components/multi_select_container.dart'; import 'package:tablet_app/Models/map-marker.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; +import 'package:tablet_app/Screens/Map/geo_point_filter.dart'; import 'package:tablet_app/Screens/Map/map_context.dart'; import 'package:html/parser.dart' show parse; +import 'package:tablet_app/app_context.dart'; import 'package:tablet_app/constants.dart'; class GoogleMapView extends StatefulWidget { @@ -95,6 +98,8 @@ class _GoogleMapViewState extends State { @override Widget build(BuildContext context) { final mapContext = Provider.of(context); + final appContext = Provider.of(context); + TabletAppContext tabletAppContext = appContext.getContext() as TabletAppContext; Size size = MediaQuery.of(context).size; if(!init) { @@ -168,6 +173,22 @@ class _GoogleMapViewState extends State { }, ), ), + Positioned( + left: 5, + top: 35, + child: SizedBox( + width: size.width * 0.3, + height: size.height * 0.76, + child: GeoPointFilter( + language: tabletAppContext.language!, + geoPoints: widget.mapDTO!.points!, + categories: widget.mapDTO!.categories!, + filteredPoints: (filteredPoints) { + print("COUCOU FILTERED POINTS"); + print(filteredPoints); + }), + ), + ), Positioned( bottom: 35, left: 10, diff --git a/lib/Screens/Map/map_box_view.dart b/lib/Screens/Map/map_box_view.dart index cc93995..3531828 100644 --- a/lib/Screens/Map/map_box_view.dart +++ b/lib/Screens/Map/map_box_view.dart @@ -19,11 +19,13 @@ import 'package:tablet_app/constants.dart'; class MapBoxView extends StatefulWidget { final MapDTO? mapDTO; + final List geoPoints; final Uint8List? selectedMarkerIcon; final String? language; const MapBoxView({ Key? key, this.mapDTO, + required this.geoPoints, this.selectedMarkerIcon, this.language, }) : super(key: key); @@ -55,7 +57,7 @@ class AnnotationClickListener extends mapBox.OnPointAnnotationClickListener { class _MapBoxViewState extends State { late mapBox.MapboxMap? mapboxMap; - late mapBox.PointAnnotationManager? pointAnnotationManager; + mapBox.PointAnnotationManager? pointAnnotationManager; bool filterZoneSelected = false; createPoints() { @@ -116,20 +118,28 @@ class _MapBoxViewState extends State { @override void initState() { - pointsToShow = widget.mapDTO!.points; + pointsToShow = widget.geoPoints;//widget.mapDTO!.points; selectedCategories = widget.mapDTO!.categories!.map((categorie) => categorie.label!.firstWhere((element) => element.language == widget.language).value!).toList(); super.initState(); } @override void dispose() { - // TODO: implement dispose super.dispose(); } @override Widget build(BuildContext context) { final mapContext = Provider.of(context); + + pointsToShow = widget.geoPoints;//widget.mapDTO!.points; + + if(pointAnnotationManager != null) { + pointAnnotationManager!.deleteAll(); + pointAnnotationManager!.createMulti(createPoints()); + //mapContext.notifyListeners(); + } + final appContext = Provider.of(context); TabletAppContext tabletAppContext = appContext.getContext() as TabletAppContext; Size size = MediaQuery.of(context).size; @@ -178,7 +188,7 @@ class _MapBoxViewState extends State { zoom: widget.mapDTO!.zoom != null ? widget.mapDTO!.zoom!.toDouble() : 12), ) ), - Positioned( + /*Positioned( left: 5, top: 35, child: SizedBox( @@ -193,7 +203,7 @@ class _MapBoxViewState extends State { print(filteredPoints); }), ), - ), + ),*/ ], ); } diff --git a/lib/Screens/Map/map_view.dart b/lib/Screens/Map/map_view.dart index 97e517a..8702e48 100644 --- a/lib/Screens/Map/map_view.dart +++ b/lib/Screens/Map/map_view.dart @@ -12,6 +12,8 @@ import 'package:tablet_app/Components/loading_common.dart'; import 'package:tablet_app/Models/map-marker.dart'; import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; +import 'package:tablet_app/Screens/Map/geo_point_filter.dart'; import 'package:tablet_app/Screens/Map/map_box_view.dart'; import 'package:tablet_app/Screens/Map/marker_view.dart'; import 'package:http/http.dart' as http; @@ -35,6 +37,7 @@ class _MapViewWidget extends State { MapDTO? mapDTO; //Completer _controller = Completer(); Uint8List? selectedMarkerIcon; + late ValueNotifier> _geoPoints = ValueNotifier>([]); Future getBytesFromAsset(ByteData data, int width) async { //ByteData data = await rootBundle.load(path); @@ -49,6 +52,7 @@ class _MapViewWidget extends State { @override void initState() { mapDTO = MapDTO.fromJson(jsonDecode(widget.section!.data!)); + _geoPoints.value = mapDTO!.points!; super.initState(); } @@ -68,44 +72,52 @@ class _MapViewWidget extends State { Widget build(BuildContext context) { //final mapContext = Provider.of(context); final appContext = Provider.of(context); - return Stack( - children: [ - FutureBuilder( - future: getByteIcon(mapDTO!.iconSource), - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - print("snapshot"); - print(snapshot.data); - print(selectedMarkerIcon); - - switch(mapDTO!.mapProvider) { - case MapProvider.Google: - return GoogleMapView(language: appContext.getContext().language, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); - case MapProvider.MapBox: - return MapBoxView(language: appContext.getContext().language, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); - default: - // By default google - return GoogleMapView(language: appContext.getContext().language, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); - } - - } else if (snapshot.connectionState == ConnectionState.none) { - return Text("No data"); - } else { - return Center( - child: Container( - child: LoadingCommon() - ) - ); - } - } - ), - MarkerViewWidget() - ] - /*floatingActionButton: FloatingActionButton.extended( - onPressed: _goToTheLake, - label: Text('To the lake!'), - icon: Icon(Icons.directions_boat), - ),*/ + TabletAppContext tabletAppContext = appContext.getContext() as TabletAppContext; + return FutureBuilder( + future: getByteIcon(mapDTO!.iconSource), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Stack( + children: [ + ValueListenableBuilder>( + valueListenable: _geoPoints, + builder: (context, value, _) { + switch(mapDTO!.mapProvider) { + case MapProvider.Google: + return GoogleMapView(language: appContext.getContext().language, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); + case MapProvider.MapBox: + return MapBoxView(language: appContext.getContext().language, geoPoints: value, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); + default: + // By default google + return GoogleMapView(language: appContext.getContext().language, mapDTO: mapDTO, selectedMarkerIcon: selectedMarkerIcon); + } + } + ), + GeoPointFilter( + language: tabletAppContext.language!, + geoPoints: mapDTO!.points!, + categories: mapDTO!.categories!, + filteredPoints: (value) { + _geoPoints.value = value!; + }), + MarkerViewWidget(), + ] + /*floatingActionButton: FloatingActionButton.extended( + onPressed: _goToTheLake, + label: Text('To the lake!'), + icon: Icon(Icons.directions_boat), + ),*/ + ); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text("No data"); + } else { + return Center( + child: Container( + child: LoadingCommon() + ) + ); + } + } ); } diff --git a/lib/Screens/Map/marker_view.dart b/lib/Screens/Map/marker_view.dart index 66e59f6..59e0089 100644 --- a/lib/Screens/Map/marker_view.dart +++ b/lib/Screens/Map/marker_view.dart @@ -24,7 +24,6 @@ class MarkerViewWidget extends StatefulWidget { } class _MarkerInfoWidget extends State { - Size sizeScreen = new Size(1080.0, 1920.0); // Tablet resolution CarouselController? sliderController; ValueNotifier currentIndex = ValueNotifier(1); @@ -51,7 +50,7 @@ class _MarkerInfoWidget extends State { return new AnimatedPositioned( duration: const Duration(milliseconds: 1500), curve: Curves.easeInOutSine, - right: 25, // 140 + left: 25, // 140 top: 10, // 150 child: Visibility( visible: (mapContext.getSelectedMarker() as MapMarker).longitude != null, diff --git a/lib/main.dart b/lib/main.dart index 004df98..7750afe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -118,11 +118,16 @@ class _MyAppState extends State { const Locale('fr', 'FR'), ],*/ theme: ThemeData( - primaryColor: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.primaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.secondaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kTestSecondColor : kTestSecondColor : kTestSecondColor, + primaryColor: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.primaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kTestSecondColor : kTestSecondColor : kTestSecondColor, primarySwatch: Colors.grey, scaffoldBackgroundColor: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.secondaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.secondaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kBackgroundGrey : kBackgroundGrey : kBackgroundGrey, fontFamily: "Roboto", - textTheme: TextTheme(bodyLarge: TextStyle(color: kTestSecondColor)), + textSelectionTheme: TextSelectionThemeData( + selectionHandleColor: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.primaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kTestSecondColor : kTestSecondColor : kTestSecondColor, + cursorColor: Colors.white, + selectionColor: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.primaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kTestSecondColor : kTestSecondColor : kTestSecondColor, + ), + textTheme: TextTheme(bodyLarge: TextStyle(color: widget.tabletAppContext != null ? widget.tabletAppContext!.configuration != null ? widget.tabletAppContext!.configuration!.primaryColor != null ? new Color(int.parse(widget.tabletAppContext!.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)): kTestSecondColor : kTestSecondColor : kTestSecondColor)), visualDensity: VisualDensity.adaptivePlatformDensity, ), routes: {