update hunt light mode
This commit is contained in:
parent
895ea862b0
commit
3f7ad2a3df
|
|
@ -151,14 +151,14 @@ class _HuntContentState extends State<_HuntContent> with TickerProviderStateMixi
|
|||
const Color(0xFF0F172A), (cos(t * pi * 2 + pi) + 1) / 2)!,
|
||||
]
|
||||
: [
|
||||
Color.lerp(const Color(0xFF84CEEB),
|
||||
const Color(0xFF5680E9), (sin(t * pi * 2) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFF5680E9),
|
||||
const Color(0xFF8860D0), (cos(t * pi * 2 + pi / 3) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFF8860D0),
|
||||
const Color(0xFF5AB9EA), (sin(t * pi * 2 + pi / 2) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFF5AB9EA),
|
||||
const Color(0xFF84CEEB), (cos(t * pi * 2 + pi) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFFFFFFFF),
|
||||
const Color(0xFFF8F9FA), (sin(t * pi * 2) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFFF8F9FA),
|
||||
const Color(0xFFE9ECEF), (cos(t * pi * 2 + pi / 3) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFFE9ECEF),
|
||||
const Color(0xFFF8F9FA), (sin(t * pi * 2 + pi / 2) + 1) / 2)!,
|
||||
Color.lerp(const Color(0xFFF8F9FA),
|
||||
const Color(0xFFFFFFFF), (cos(t * pi * 2 + pi) + 1) / 2)!,
|
||||
],
|
||||
stops: const [0.0, 0.3, 0.7, 1.0],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -33,6 +33,21 @@ class LocationService {
|
|||
}
|
||||
}
|
||||
|
||||
static Stream<Position>? getPositionStream() async* {
|
||||
bool hasPermission = await checkLocationPermission();
|
||||
if (!hasPermission) {
|
||||
yield* Stream.empty();
|
||||
return;
|
||||
}
|
||||
|
||||
const LocationSettings locationSettings = LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 1,
|
||||
);
|
||||
|
||||
yield* Geolocator.getPositionStream(locationSettings: locationSettings);
|
||||
}
|
||||
|
||||
static double calculateDistance(
|
||||
double lat1,
|
||||
double lon1,
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import 'dart:ui';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:lba/gen/assets.gen.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:flutter_compass/flutter_compass.dart';
|
||||
import 'package:lba/res/colors.dart';
|
||||
import '../services/location_service.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
class HintCameraWidget extends StatefulWidget {
|
||||
final double targetLatitude;
|
||||
|
|
@ -40,7 +40,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
with TickerProviderStateMixin {
|
||||
MobileScannerController? _controller;
|
||||
StreamSubscription<CompassEvent>? _compassSubscription;
|
||||
Timer? _locationTimer;
|
||||
StreamSubscription<Position>? _locationSubscription;
|
||||
Timer? _countdownTimer;
|
||||
|
||||
final MapController _miniMapController = MapController();
|
||||
|
|
@ -86,7 +86,8 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
if (mounted) {
|
||||
setState(() {
|
||||
if (_currentRemainingTime.inSeconds > 0) {
|
||||
_currentRemainingTime = Duration(seconds: _currentRemainingTime.inSeconds - 1);
|
||||
_currentRemainingTime =
|
||||
Duration(seconds: _currentRemainingTime.inSeconds - 1);
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
|
|
@ -130,12 +131,8 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
}
|
||||
|
||||
void _startLocationUpdates() {
|
||||
_locationTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) async {
|
||||
if (!mounted) {
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
final position = await LocationService.getCurrentPosition();
|
||||
_locationSubscription =
|
||||
LocationService.getPositionStream()?.listen((Position? position) {
|
||||
if (position != null && mounted) {
|
||||
final bearing = LocationService.getBearing(
|
||||
position.latitude,
|
||||
|
|
@ -168,8 +165,10 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
|
||||
void _updateMiniMapCamera() {
|
||||
if (_currentPosition != null) {
|
||||
final userLocation = LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
final targetLocation = LatLng(widget.targetLatitude, widget.targetLongitude);
|
||||
final userLocation =
|
||||
LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
final targetLocation =
|
||||
LatLng(widget.targetLatitude, widget.targetLongitude);
|
||||
_miniMapController.fitCamera(
|
||||
CameraFit.bounds(
|
||||
bounds: LatLngBounds(userLocation, targetLocation),
|
||||
|
|
@ -211,7 +210,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
@override
|
||||
void dispose() {
|
||||
_compassSubscription?.cancel();
|
||||
_locationTimer?.cancel();
|
||||
_locationSubscription?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
_controller?.dispose();
|
||||
_rotationController.dispose();
|
||||
|
|
@ -222,8 +221,10 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
|
||||
Widget _buildMiniMap() {
|
||||
if (_currentPosition == null) return const SizedBox.shrink();
|
||||
final userLocation = LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
final targetLocation = LatLng(widget.targetLatitude, widget.targetLongitude);
|
||||
final userLocation =
|
||||
LatLng(_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
final targetLocation =
|
||||
LatLng(widget.targetLatitude, widget.targetLongitude);
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
curve: Curves.easeInOutCubic,
|
||||
|
|
@ -248,11 +249,13 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
options: MapOptions(
|
||||
initialCenter: userLocation,
|
||||
initialZoom: 15,
|
||||
interactionOptions: const InteractionOptions(flags: InteractiveFlag.none),
|
||||
interactionOptions:
|
||||
const InteractionOptions(flags: InteractiveFlag.none),
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',
|
||||
urlTemplate:
|
||||
'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',
|
||||
subdomains: const ['a', 'b', 'c', 'd'],
|
||||
),
|
||||
MarkerLayer(
|
||||
|
|
@ -261,13 +264,13 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
point: userLocation,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: PulsingMarker(isUser: true),
|
||||
child: const PulsingMarker(isUser: true),
|
||||
),
|
||||
Marker(
|
||||
point: targetLocation,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: PulsingMarker(isUser: false),
|
||||
child: const PulsingMarker(isUser: false),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -330,13 +333,16 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
),
|
||||
child: IconButton(
|
||||
onPressed: widget.onClose,
|
||||
icon: SvgPicture.asset(Assets.icons.back.path, color: Colors.white,),
|
||||
icon: SvgPicture.asset(Assets.icons.back.path,
|
||||
colorFilter:
|
||||
const ColorFilter.mode(Colors.white, BlendMode.srcIn)),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
title: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
|
|
@ -371,8 +377,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 1.2,
|
||||
fontFamily: 'monospace'
|
||||
),
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
|
|
@ -400,9 +405,10 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
],
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
},
|
||||
icon: SvgPicture.asset(Assets.icons.infoCircle.path, color: Colors.white,),
|
||||
onPressed: () {},
|
||||
icon: SvgPicture.asset(Assets.icons.infoCircle.path,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
Colors.white, BlendMode.srcIn)),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -439,14 +445,16 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
if (widget.remainingTime == null) return const SizedBox.shrink();
|
||||
|
||||
final Duration timeToShow = _currentRemainingTime.inSeconds <= 0
|
||||
? (widget.remainingTime!.inSeconds == 0 ? const Duration(hours: 12) : Duration.zero)
|
||||
? (widget.remainingTime!.inSeconds == 0
|
||||
? const Duration(hours: 12)
|
||||
: Duration.zero)
|
||||
: _currentRemainingTime;
|
||||
|
||||
final hours = timeToShow.inHours;
|
||||
final minutes = timeToShow.inMinutes % 60;
|
||||
final seconds = timeToShow.inSeconds % 60;
|
||||
final isUrgent = timeToShow.inMinutes < 5 && timeToShow.inHours == 0;
|
||||
final isExpired = _currentRemainingTime.inSeconds <= 0 && widget.remainingTime!.inSeconds > 0;
|
||||
final isExpired =
|
||||
_currentRemainingTime.inSeconds <= 0 && widget.remainingTime!.inSeconds > 0;
|
||||
|
||||
return Positioned(
|
||||
top: kToolbarHeight + 60,
|
||||
|
|
@ -475,9 +483,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
? '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}'
|
||||
: '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}',
|
||||
style: TextStyle(
|
||||
color: isExpired
|
||||
? const Color(0xFFFF3B30)
|
||||
: Colors.white,
|
||||
color: isExpired ? const Color(0xFFFF3B30) : Colors.white,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.5,
|
||||
|
|
@ -491,8 +497,6 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget _buildMapFAB() {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
|
|
@ -575,7 +579,9 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Icon(
|
||||
isLeft ? Icons.arrow_back_ios_new_rounded : Icons.arrow_forward_ios_rounded,
|
||||
isLeft
|
||||
? Icons.arrow_back_ios_new_rounded
|
||||
: Icons.arrow_forward_ios_rounded,
|
||||
color: AppColors.primary.withOpacity(0.8),
|
||||
size: 48,
|
||||
shadows: [
|
||||
|
|
@ -642,8 +648,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
letterSpacing: 1.5,
|
||||
fontFamily: 'monospace'
|
||||
),
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
|
|
@ -653,8 +658,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
fontWeight: FontWeight.w800,
|
||||
fontSize: _getDistanceFontSize(distance),
|
||||
letterSpacing: 0.5,
|
||||
fontFamily: 'monospace'
|
||||
),
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -701,9 +705,11 @@ class _PulsingMarkerState extends State<PulsingMarker>
|
|||
Widget build(BuildContext context) {
|
||||
final color = widget.isUser ? Colors.blue.shade400 : Colors.yellow.shade700;
|
||||
return FadeTransition(
|
||||
opacity: Tween<double>(begin: 1.0, end: 0.3).animate(_animationController),
|
||||
opacity:
|
||||
Tween<double>(begin: 1.0, end: 0.3).animate(_animationController),
|
||||
child: ScaleTransition(
|
||||
scale: Tween<double>(begin: 0.5, end: 1.0).animate(_animationController),
|
||||
scale:
|
||||
Tween<double>(begin: 0.5, end: 1.0).animate(_animationController),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
|
|
@ -713,8 +719,11 @@ class _PulsingMarkerState extends State<PulsingMarker>
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset(
|
||||
widget.isUser ? Assets.icons.gps.path : Assets.icons.locationCross.path,
|
||||
color: Colors.black,
|
||||
widget.isUser
|
||||
? Assets.icons.gps.path
|
||||
: Assets.icons.locationCross.path,
|
||||
colorFilter:
|
||||
const ColorFilter.mode(Colors.black, BlendMode.srcIn),
|
||||
width: 10,
|
||||
),
|
||||
),
|
||||
|
|
@ -738,18 +747,31 @@ class HudPainter extends CustomPainter {
|
|||
const bracketSize = 30.0;
|
||||
const margin = 20.0;
|
||||
|
||||
canvas.drawLine(Offset(margin, margin), Offset(margin + bracketSize, margin), paint);
|
||||
canvas.drawLine(Offset(margin, margin), Offset(margin, margin + bracketSize), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, margin), Offset(size.width - margin - bracketSize, margin), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, margin), Offset(size.width - margin, margin + bracketSize), paint);
|
||||
canvas.drawLine(Offset(margin, size.height - margin), Offset(margin + bracketSize, size.height - margin), paint);
|
||||
canvas.drawLine(Offset(margin, size.height - margin), Offset(margin, size.height - margin - bracketSize), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, size.height - margin), Offset(size.width - margin - bracketSize, size.height - margin), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, size.height - margin), Offset(size.width - margin, size.height - margin - bracketSize), paint);
|
||||
canvas.drawLine(
|
||||
Offset(margin, margin), Offset(margin + bracketSize, margin), paint);
|
||||
canvas.drawLine(
|
||||
Offset(margin, margin), Offset(margin, margin + bracketSize), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, margin),
|
||||
Offset(size.width - margin - bracketSize, margin), paint);
|
||||
canvas.drawLine(Offset(size.width - margin, margin),
|
||||
Offset(size.width - margin, margin + bracketSize), paint);
|
||||
canvas.drawLine(Offset(margin, size.height - margin),
|
||||
Offset(margin + bracketSize, size.height - margin), paint);
|
||||
canvas.drawLine(Offset(margin, size.height - margin),
|
||||
Offset(margin, size.height - margin - bracketSize), paint);
|
||||
canvas.drawLine(
|
||||
Offset(size.width - margin, size.height - margin),
|
||||
Offset(size.width - margin - bracketSize, size.height - margin),
|
||||
paint);
|
||||
canvas.drawLine(
|
||||
Offset(size.width - margin, size.height - margin),
|
||||
Offset(size.width - margin, size.height - margin - bracketSize),
|
||||
paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant HudPainter oldDelegate) => oldDelegate.animationValue != animationValue;
|
||||
bool shouldRepaint(covariant HudPainter oldDelegate) =>
|
||||
oldDelegate.animationValue != animationValue;
|
||||
}
|
||||
|
||||
class AdvancedTargetPainter extends CustomPainter {
|
||||
|
|
@ -771,7 +793,8 @@ class AdvancedTargetPainter extends CustomPainter {
|
|||
void paint(Canvas canvas, Size size) {
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final paint = Paint()..style = PaintingStyle.stroke;
|
||||
final primaryColor = isNear ? const Color(0xFF00E676) : const Color(0xFF2196F3);
|
||||
final primaryColor =
|
||||
isNear ? const Color(0xFF00E676) : const Color(0xFF2196F3);
|
||||
final baseRadius = math.max(60.0, math.min(85.0, 100 - (distance / 2)));
|
||||
|
||||
paint
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ class _HuntCardWidgetState extends State<HuntCardWidget>
|
|||
Icons.stars_rounded,
|
||||
color: AppColors.isDarkMode
|
||||
? AppColors.confirmButton
|
||||
: const Color(0xFF2E7D32),
|
||||
: const Color.fromARGB(255, 38, 121, 41),
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
|
|
@ -358,7 +358,7 @@ class _HuntCardWidgetState extends State<HuntCardWidget>
|
|||
style: TextStyle(
|
||||
color: AppColors.isDarkMode
|
||||
? AppColors.confirmButton
|
||||
: const Color(0xFF2E7D32),
|
||||
: const Color.fromARGB(255, 38, 121, 41),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
|
|
@ -443,15 +443,13 @@ class _HuntCardWidgetState extends State<HuntCardWidget>
|
|||
: const Color(0xFF1976D2).withOpacity(0.2),
|
||||
width: 1.5,
|
||||
),
|
||||
boxShadow: [
|
||||
boxShadow: AppColors.isDarkMode ? [
|
||||
BoxShadow(
|
||||
color: AppColors.isDarkMode
|
||||
? AppColors.primary.withOpacity(0.1)
|
||||
: const Color(0xFF1976D2).withOpacity(0.06),
|
||||
color: AppColors.primary.withOpacity(0.1),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
] : null,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue