Fix markers

This commit is contained in:
Yoshi 2024-08-18 14:08:54 +03:00
parent 8ed047a1aa
commit 383fb24881
4 changed files with 361 additions and 315 deletions

2
.gitignore vendored
View file

@ -42,5 +42,3 @@ app.*.map.json
/android/app/debug /android/app/debug
/android/app/profile /android/app/profile
/android/app/release /android/app/release
/lib/secret_key.dart

View file

@ -85,7 +85,9 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
child: ScaffoldMessenger( child: ScaffoldMessenger(
key: globalKey, key: globalKey,
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: tabIndex == 2
? null
: AppBar(
centerTitle: true, centerTitle: true,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
leading: switch (tabIndex) { leading: switch (tabIndex) {
@ -116,7 +118,8 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
), ),
); );
}, },
optionsBuilder: (TextEditingValue textEditingValue) { optionsBuilder:
(TextEditingValue textEditingValue) {
if (textEditingValue.text.isEmpty) { if (textEditingValue.text.isEmpty) {
return const Iterable<Result>.empty(); return const Iterable<Result>.empty();
} }
@ -152,7 +155,8 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,
itemCount: options.length, itemCount: options.length,
itemBuilder: (BuildContext context, int index) { itemBuilder:
(BuildContext context, int index) {
final Result option = final Result option =
options.elementAt(index); options.elementAt(index);
return InkWell( return InkWell(
@ -187,7 +191,9 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
: '$city' ', $district' : '$city' ', $district'
: settings.location : settings.location
? 'search'.tr ? 'search'.tr
: (isar.locationCaches.where().findAllSync()) : (isar.locationCaches
.where()
.findAllSync())
.isNotEmpty .isNotEmpty
? 'loading'.tr ? 'loading'.tr
: 'searchCity'.tr, : 'searchCity'.tr,
@ -199,10 +205,6 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
'cities'.tr, 'cities'.tr,
style: textStyle, style: textStyle,
), ),
2 => Text(
'map'.tr,
style: textStyle,
),
3 => Text( 3 => Text(
'settings_full'.tr, 'settings_full'.tr,
style: textStyle, style: textStyle,

View file

@ -1,17 +1,19 @@
import 'dart:io'; import 'dart:io';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_file_store/dio_cache_interceptor_file_store.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart'; import 'package:flutter_map_cache/flutter_map_cache.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:iconsax_plus/iconsax_plus.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:rain/app/controller/controller.dart'; import 'package:rain/app/controller/controller.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; import 'package:rain/app/data/weather.dart';
import 'package:dio_cache_interceptor_file_store/dio_cache_interceptor_file_store.dart'; import 'package:rain/app/modules/cards/view/info_weather_card.dart';
import 'package:rain/app/modules/cards/widgets/create_card_weather.dart'; import 'package:rain/app/modules/cards/widgets/create_card_weather.dart';
import 'package:rain/secret_key.dart'; import 'package:rain/app/modules/cards/widgets/weather_card_container.dart';
import 'package:rain/app/widgets/status/status_weather.dart';
class MapWeather extends StatefulWidget { class MapWeather extends StatefulWidget {
const MapWeather({super.key}); const MapWeather({super.key});
@ -21,56 +23,163 @@ class MapWeather extends StatefulWidget {
} }
class _MapWeatherState extends State<MapWeather> with TickerProviderStateMixin { class _MapWeatherState extends State<MapWeather> with TickerProviderStateMixin {
late final _animatedMapController = AnimatedMapController(vsync: this); late final AnimatedMapController _animatedMapController =
AnimatedMapController(vsync: this);
final weatherController = Get.put(WeatherController()); final weatherController = Get.put(WeatherController());
bool isDarkMode = Get.theme.brightness == Brightness.dark; final statusWeather = StatusWeather();
final Future<CacheStore> _cacheStoreFuture = _getCacheStore(); final Future<CacheStore> _cacheStoreFuture = _getCacheStore();
final bool _isDarkMode = Get.theme.brightness == Brightness.dark;
WeatherCard? _selectedWeatherCard;
bool _isCardVisible = false;
double _cardBottomPosition = -200;
static Future<CacheStore> _getCacheStore() async { static Future<CacheStore> _getCacheStore() async {
final dir = await getTemporaryDirectory(); final dir = await getTemporaryDirectory();
return FileCacheStore('${dir.path}${Platform.pathSeparator}MapTiles'); return FileCacheStore('${dir.path}${Platform.pathSeparator}MapTiles');
} }
@override void _onMarkerTap(WeatherCard weatherCard) {
Widget build(BuildContext context) { setState(() {
final mainLocation = weatherController.location; _selectedWeatherCard = weatherCard;
// final mainWeather = weatherController.mainWeather; _cardBottomPosition = 0;
// final weatherCard = WeatherCard.fromJson({} _isCardVisible = true;
// ..addAll(mainWeather.toJson()) });
// ..addAll(mainLocation.toJson())); }
Widget darkModeTilesContainerBuilder( void _hideCard() {
BuildContext context, setState(() {
Widget tilesContainer, _cardBottomPosition = -200;
) { });
return ColorFiltered( Future.delayed(const Duration(milliseconds: 300), () {
colorFilter: const ColorFilter.matrix(<double>[ setState(() {
-0.2126, -0.7152, -0.0722, 0, 255, // Red channel _isCardVisible = false;
-0.2126, -0.7152, -0.0722, 0, 255, // Green channel });
-0.2126, -0.7152, -0.0722, 0, 255, // Blue channel });
0, 0, 0, 1, 0, // Alpha channel }
]),
child: tilesContainer, Marker _buildMainLocationMarker(
WeatherCard weatherCard, int hourOfDay, int dayOfNow) {
return Marker(
height: 40,
width: 40,
point: LatLng(weatherCard.lat!, weatherCard.lon!),
child: GestureDetector(
onTap: () => _onMarkerTap(weatherCard),
child: Container(
decoration: BoxDecoration(
color: context.theme.colorScheme.onSecondary,
shape: BoxShape.circle,
),
child: Image.asset(
statusWeather.getImageNow(
weatherCard.weathercode![hourOfDay],
weatherCard.time![hourOfDay],
weatherCard.sunrise![dayOfNow],
weatherCard.sunset![dayOfNow],
),
scale: 15,
),
),
),
); );
} }
Widget openStreetMapTileLayer(CacheStore cacheStore) { Marker _buildCardMarker(WeatherCard weatherCardList) {
return Marker(
height: 40,
width: 40,
point: LatLng(weatherCardList.lat!, weatherCardList.lon!),
child: GestureDetector(
onTap: () => _onMarkerTap(weatherCardList),
child: Container(
decoration: BoxDecoration(
color: context.theme.colorScheme.onSecondary,
shape: BoxShape.circle,
),
child: Image.asset(
statusWeather.getImageNow(
weatherCardList.weathercode![weatherController.getTime(
weatherCardList.time!, weatherCardList.timezone!)],
weatherCardList.time![weatherController.getTime(
weatherCardList.time!, weatherCardList.timezone!)],
weatherCardList.sunrise![weatherController.getDay(
weatherCardList.timeDaily!, weatherCardList.timezone!)],
weatherCardList.sunset![weatherController.getDay(
weatherCardList.timeDaily!, weatherCardList.timezone!)],
),
scale: 15,
),
),
),
);
}
Widget _buildMapTileLayer(CacheStore cacheStore) {
return TileLayer( return TileLayer(
urlTemplate: urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
'https://api.mapbox.com/styles/v1/yoshimok/clzvnt6ae000s01qsh52veh8f/tiles/256/{z}/{x}/{y}@2x?access_token=$accessToken',
userAgentPackageName: 'com.darkmoonight.rain', userAgentPackageName: 'com.darkmoonight.rain',
tileProvider: CachedTileProvider( tileProvider: CachedTileProvider(
store: cacheStore, store: cacheStore,
maxStale: const Duration(days: 30), maxStale: const Duration(days: 30),
)); ),
);
} }
Widget _buildWeatherCard() {
return AnimatedPositioned(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
left: 0,
right: 0,
bottom: _cardBottomPosition,
child: AnimatedOpacity(
opacity: _isCardVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 300),
child: _isCardVisible
? GestureDetector(
onTap: () => Get.to(
() => InfoWeatherCard(weatherCard: _selectedWeatherCard!),
transition: Transition.downToUp,
),
child: WeatherCardContainer(
time: _selectedWeatherCard!.time!,
timeDaily: _selectedWeatherCard!.timeDaily!,
timeDay: _selectedWeatherCard!.sunrise!,
timeNight: _selectedWeatherCard!.sunset!,
weather: _selectedWeatherCard!.weathercode!,
degree: _selectedWeatherCard!.temperature2M!,
district: _selectedWeatherCard!.district!,
city: _selectedWeatherCard!.city!,
timezone: _selectedWeatherCard!.timezone!,
),
)
: const SizedBox.shrink(),
),
);
}
@override
Widget build(BuildContext context) {
final mainLocation = weatherController.location;
final mainWeather = weatherController.mainWeather;
final hourOfDay = weatherController.hourOfDay.value;
final dayOfNow = weatherController.dayOfNow.value;
return FutureBuilder<CacheStore>( return FutureBuilder<CacheStore>(
future: _cacheStoreFuture, future: _cacheStoreFuture,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
}
final cacheStore = snapshot.data!; final cacheStore = snapshot.data!;
return FlutterMap( return FlutterMap(
mapController: _animatedMapController.mapController, mapController: _animatedMapController.mapController,
options: MapOptions( options: MapOptions(
@ -83,6 +192,7 @@ class _MapWeatherState extends State<MapWeather> with TickerProviderStateMixin {
const LatLng(90, 180), const LatLng(90, 180),
), ),
), ),
onTap: (_, __) => _hideCard(),
onLongPress: (tapPosition, point) => showModalBottomSheet( onLongPress: (tapPosition, point) => showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
@ -94,101 +204,50 @@ class _MapWeatherState extends State<MapWeather> with TickerProviderStateMixin {
), ),
), ),
children: [ children: [
isDarkMode if (_isDarkMode)
? darkModeTilesContainerBuilder( ColorFiltered(
context, openStreetMapTileLayer(cacheStore)) colorFilter: const ColorFilter.matrix(<double>[
: openStreetMapTileLayer(cacheStore), -0.2126, -0.7152, -0.0722, 0, 255, // Red channel
-0.2126, -0.7152, -0.0722, 0, 255, // Green channel
-0.2126, -0.7152, -0.0722, 0, 255, // Blue channel
0, 0, 0, 1, 0, // Alpha channel
]),
child: _buildMapTileLayer(cacheStore),
)
else
_buildMapTileLayer(cacheStore),
RichAttributionWidget( RichAttributionWidget(
animationConfig: const ScaleRAWA(), animationConfig: const ScaleRAWA(),
attributions: [ attributions: [
TextSourceAttribution( TextSourceAttribution(
'Mapbox contributors', 'OpenStreetMap contributors',
onTap: () => weatherController onTap: () => weatherController
.urlLauncher('https://www.mapbox.com/legal/tos'), .urlLauncher('https://openstreetmap.org/copyright'),
), ),
], ],
), ),
Obx( Obx(() {
() { final mainMarker = _buildMainLocationMarker(
var weatherCards = weatherController.weatherCards.toList(); WeatherCard.fromJson({
...mainWeather.toJson(),
...mainLocation.toJson(),
}),
hourOfDay,
dayOfNow,
);
final cardMarkers = weatherController.weatherCards
.map((weatherCardList) => _buildCardMarker(weatherCardList))
.toList();
return MarkerLayer( return MarkerLayer(
markers: [ markers: [mainMarker, ...cardMarkers],
Marker( );
point: LatLng(mainLocation.lat!, mainLocation.lon!), }),
child: GestureDetector( _buildWeatherCard(),
onTap: () {},
child: Container(
decoration: BoxDecoration(
color:
context.theme.colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(10),
),
child: Icon(
IconsaxPlusBold.home,
color: context
.theme.colorScheme.onSecondaryContainer,
),
),
),
),
...weatherCards.map(
(weatherCardList) => Marker(
width: 35,
height: 35,
point: LatLng(
weatherCardList.lat!, weatherCardList.lon!),
child: GestureDetector(
onTap: () {},
child: Container(
decoration: BoxDecoration(
color: context
.theme.colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(10),
),
child: const Icon(
IconsaxPlusBold.location,
color: Colors.red,
),
),
),
),
)
], ],
); );
}, },
),
// Positioned(
// left: 0,
// right: 0,
// bottom: 0,
// child: GestureDetector(
// onTap: () => Get.to(
// () => InfoWeatherCard(
// weatherCard: weatherCard,
// ),
// transition: Transition.downToUp,
// ),
// child: WeatherCardContainer(
// time: mainWeather.time!,
// timeDaily: mainWeather.timeDaily!,
// timeDay: mainWeather.sunrise!,
// timeNight: mainWeather.sunset!,
// weather: mainWeather.weathercode!,
// degree: mainWeather.temperature2M!,
// district: mainLocation.district!,
// city: mainLocation.city!,
// timezone: mainWeather.timezone!,
// ),
// ),
// )
],
);
}
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
}
return const Center(child: CircularProgressIndicator());
},
); );
} }
} }

View file

@ -15,7 +15,6 @@ import 'package:rain/app/modules/settings/widgets/setting_card.dart';
import 'package:rain/main.dart'; import 'package:rain/main.dart';
import 'package:rain/theme/theme_controller.dart'; import 'package:rain/theme/theme_controller.dart';
import 'package:rain/utils/color_converter.dart'; import 'package:rain/utils/color_converter.dart';
import 'package:url_launcher/url_launcher.dart';
class SettingsPage extends StatefulWidget { class SettingsPage extends StatefulWidget {
const SettingsPage({super.key}); const SettingsPage({super.key});
@ -978,27 +977,15 @@ class _SettingsPageState extends State<SettingsPage> {
elevation: 4, elevation: 4,
icon: const Icon(LineAwesomeIcons.discord), icon: const Icon(LineAwesomeIcons.discord),
text: 'Discord', text: 'Discord',
onPressed: () async { onPressed: () => weatherController.urlLauncher(
final Uri url = Uri.parse( 'https://discord.gg/JMMa9aHh8f'),
'https://discord.gg/JMMa9aHh8f');
if (!await launchUrl(url,
mode: LaunchMode.externalApplication)) {
throw Exception('Could not launch $url');
}
},
), ),
SettingCard( SettingCard(
elevation: 4, elevation: 4,
icon: const Icon(LineAwesomeIcons.telegram), icon: const Icon(LineAwesomeIcons.telegram),
text: 'Telegram', text: 'Telegram',
onPressed: () async { onPressed: () => weatherController
final Uri url = .urlLauncher('https://t.me/darkmoonightX'),
Uri.parse('https://t.me/darkmoonightX');
if (!await launchUrl(url,
mode: LaunchMode.externalApplication)) {
throw Exception('Could not launch $url');
}
},
), ),
const Gap(10), const Gap(10),
], ],