improve hunt hint ui
This commit is contained in:
parent
2c0133dff7
commit
895ea862b0
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 22.75C6.07 22.75 1.25 17.93 1.25 12C1.25 6.07 6.07 1.25 12 1.25C17.93 1.25 22.75 6.07 22.75 12C22.75 17.93 17.93 22.75 12 22.75ZM12 2.75C6.9 2.75 2.75 6.9 2.75 12C2.75 17.1 6.9 21.25 12 21.25C17.1 21.25 21.25 17.1 21.25 12C21.25 6.9 17.1 2.75 12 2.75Z" fill="#292D32"/>
|
||||
<path d="M9.17035 15.58C8.98035 15.58 8.79035 15.51 8.64035 15.36C8.35035 15.07 8.35035 14.59 8.64035 14.3L14.3004 8.63999C14.5904 8.34999 15.0704 8.34999 15.3604 8.63999C15.6504 8.92999 15.6504 9.40998 15.3604 9.69998L9.70035 15.36C9.56035 15.51 9.36035 15.58 9.17035 15.58Z" fill="#292D32"/>
|
||||
<path d="M14.8304 15.58C14.6404 15.58 14.4504 15.51 14.3004 15.36L8.64035 9.69998C8.35035 9.40998 8.35035 8.92999 8.64035 8.63999C8.93035 8.34999 9.41035 8.34999 9.70035 8.63999L15.3604 14.3C15.6504 14.59 15.6504 15.07 15.3604 15.36C15.2104 15.51 15.0204 15.58 14.8304 15.58Z" fill="#292D32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 974 B |
|
|
@ -0,0 +1,8 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 20.25C7.45 20.25 3.75 16.55 3.75 12C3.75 7.45 7.45 3.75 12 3.75C16.55 3.75 20.25 7.45 20.25 12C20.25 16.55 16.55 20.25 12 20.25ZM12 5.25C8.28 5.25 5.25 8.28 5.25 12C5.25 15.72 8.28 18.75 12 18.75C15.72 18.75 18.75 15.72 18.75 12C18.75 8.28 15.72 5.25 12 5.25Z" fill="#292D32"/>
|
||||
<path d="M12 15.75C9.93 15.75 8.25 14.07 8.25 12C8.25 9.93 9.93 8.25 12 8.25C14.07 8.25 15.75 9.93 15.75 12C15.75 14.07 14.07 15.75 12 15.75ZM12 9.75C10.76 9.75 9.75 10.76 9.75 12C9.75 13.24 10.76 14.25 12 14.25C13.24 14.25 14.25 13.24 14.25 12C14.25 10.76 13.24 9.75 12 9.75Z" fill="#292D32"/>
|
||||
<path d="M12 4.75C11.59 4.75 11.25 4.41 11.25 4V2C11.25 1.59 11.59 1.25 12 1.25C12.41 1.25 12.75 1.59 12.75 2V4C12.75 4.41 12.41 4.75 12 4.75Z" fill="#292D32"/>
|
||||
<path d="M4 12.75H2C1.59 12.75 1.25 12.41 1.25 12C1.25 11.59 1.59 11.25 2 11.25H4C4.41 11.25 4.75 11.59 4.75 12C4.75 12.41 4.41 12.75 4 12.75Z" fill="#292D32"/>
|
||||
<path d="M12 22.75C11.59 22.75 11.25 22.41 11.25 22V20C11.25 19.59 11.59 19.25 12 19.25C12.41 19.25 12.75 19.59 12.75 20V22C12.75 22.41 12.41 22.75 12 22.75Z" fill="#292D32"/>
|
||||
<path d="M22 12.75H20C19.59 12.75 19.25 12.41 19.25 12C19.25 11.59 19.59 11.25 20 11.25H22C22.41 11.25 22.75 11.59 22.75 12C22.75 12.41 22.41 12.75 22 12.75Z" fill="#292D32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.0002 22.76C10.5202 22.76 9.03018 22.2 7.87018 21.09C4.92018 18.25 1.66018 13.72 2.89018 8.33C4.00018 3.44 8.27018 1.25 12.0002 1.25C12.0002 1.25 12.0002 1.25 12.0102 1.25C15.7402 1.25 20.0102 3.44 21.1202 8.34C22.3402 13.73 19.0802 18.25 16.1302 21.09C14.9702 22.2 13.4802 22.76 12.0002 22.76ZM12.0002 2.75C9.09018 2.75 5.35018 4.3 4.36018 8.66C3.28018 13.37 6.24018 17.43 8.92018 20C10.6502 21.67 13.3602 21.67 15.0902 20C17.7602 17.43 20.7202 13.37 19.6602 8.66C18.6602 4.3 14.9102 2.75 12.0002 2.75Z" fill="#292D32"/>
|
||||
<path d="M14 13.71C13.81 13.71 13.62 13.64 13.47 13.49L9.50998 9.53C9.21998 9.24 9.21998 8.76 9.50998 8.47C9.79998 8.18 10.28 8.18 10.57 8.47L14.53 12.43C14.82 12.72 14.82 13.2 14.53 13.49C14.38 13.63 14.19 13.71 14 13.71Z" fill="#292D32"/>
|
||||
<path d="M9.99994 13.75C9.80994 13.75 9.61994 13.68 9.46994 13.53C9.17994 13.24 9.17994 12.76 9.46994 12.47L13.4299 8.51001C13.7199 8.22001 14.1999 8.22001 14.4899 8.51001C14.7799 8.80001 14.7799 9.28001 14.4899 9.57001L10.5299 13.53C10.3799 13.68 10.1899 13.75 9.99994 13.75Z" fill="#292D32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -132,6 +132,10 @@ class $AssetsIconsGen {
|
|||
/// File path: assets/icons/clock.svg
|
||||
SvgGenImage get clock => const SvgGenImage('assets/icons/clock.svg');
|
||||
|
||||
/// File path: assets/icons/close-circle.svg
|
||||
SvgGenImage get closeCircle =>
|
||||
const SvgGenImage('assets/icons/close-circle.svg');
|
||||
|
||||
/// File path: assets/icons/coin.svg
|
||||
SvgGenImage get coin => const SvgGenImage('assets/icons/coin.svg');
|
||||
|
||||
|
|
@ -211,6 +215,9 @@ class $AssetsIconsGen {
|
|||
SvgGenImage get globalSearch2 =>
|
||||
const SvgGenImage('assets/icons/global-search2.svg');
|
||||
|
||||
/// File path: assets/icons/gps.svg
|
||||
SvgGenImage get gps => const SvgGenImage('assets/icons/gps.svg');
|
||||
|
||||
/// File path: assets/icons/healthicons_fruits-outline.svg
|
||||
SvgGenImage get healthiconsFruitsOutline =>
|
||||
const SvgGenImage('assets/icons/healthicons_fruits-outline.svg');
|
||||
|
|
@ -258,6 +265,10 @@ class $AssetsIconsGen {
|
|||
/// File path: assets/icons/list.svg
|
||||
SvgGenImage get list => const SvgGenImage('assets/icons/list.svg');
|
||||
|
||||
/// File path: assets/icons/location-cross.svg
|
||||
SvgGenImage get locationCross =>
|
||||
const SvgGenImage('assets/icons/location-cross.svg');
|
||||
|
||||
/// File path: assets/icons/location-tick.svg
|
||||
SvgGenImage get locationTick =>
|
||||
const SvgGenImage('assets/icons/location-tick.svg');
|
||||
|
|
@ -493,6 +504,7 @@ class $AssetsIconsGen {
|
|||
checkAlternative,
|
||||
clander,
|
||||
clock,
|
||||
closeCircle,
|
||||
coin,
|
||||
cup,
|
||||
currentLoc,
|
||||
|
|
@ -515,6 +527,7 @@ class $AssetsIconsGen {
|
|||
girlClothes,
|
||||
globalSearch,
|
||||
globalSearch2,
|
||||
gps,
|
||||
healthiconsFruitsOutline,
|
||||
heart,
|
||||
hugeiconsBabyBoyDress,
|
||||
|
|
@ -528,6 +541,7 @@ class $AssetsIconsGen {
|
|||
like,
|
||||
link2,
|
||||
list,
|
||||
locationCross,
|
||||
locationTick,
|
||||
location,
|
||||
locationPopup,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class HuntState extends ChangeNotifier {
|
|||
|
||||
void startHunt() {
|
||||
if (_selectedCard != null) {
|
||||
_huntStartTime = DateTime.now();
|
||||
_gameState = HuntGameState.huntingActive;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ import 'dart:async';
|
|||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:geolocator/geolocator.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';
|
||||
|
|
@ -16,6 +18,8 @@ class HintCameraWidget extends StatefulWidget {
|
|||
final String hintDescription;
|
||||
final VoidCallback onHintFound;
|
||||
final VoidCallback onClose;
|
||||
final Duration? remainingTime;
|
||||
final String? cardTitle;
|
||||
|
||||
const HintCameraWidget({
|
||||
super.key,
|
||||
|
|
@ -24,6 +28,8 @@ class HintCameraWidget extends StatefulWidget {
|
|||
required this.hintDescription,
|
||||
required this.onHintFound,
|
||||
required this.onClose,
|
||||
this.remainingTime,
|
||||
this.cardTitle,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -35,6 +41,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
MobileScannerController? _controller;
|
||||
StreamSubscription<CompassEvent>? _compassSubscription;
|
||||
Timer? _locationTimer;
|
||||
Timer? _countdownTimer;
|
||||
|
||||
final MapController _miniMapController = MapController();
|
||||
|
||||
|
|
@ -44,11 +51,11 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
Position? _currentPosition;
|
||||
bool _isNearTarget = false;
|
||||
bool _isMapVisible = false;
|
||||
|
||||
Duration _currentRemainingTime = Duration.zero;
|
||||
|
||||
late AnimationController _pulseController;
|
||||
late AnimationController _rotationController;
|
||||
late AnimationController _scanController;
|
||||
late Animation<double> _pulseAnimation;
|
||||
late Animation<double> _rotationAnimation;
|
||||
late Animation<double> _scanAnimation;
|
||||
|
||||
|
|
@ -61,6 +68,31 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
_setupAnimations();
|
||||
_startCompassListening();
|
||||
_startLocationUpdates();
|
||||
_initializeTimer();
|
||||
}
|
||||
|
||||
void _initializeTimer() {
|
||||
if (widget.remainingTime != null) {
|
||||
_currentRemainingTime = widget.remainingTime!.inSeconds == 0
|
||||
? const Duration(hours: 12)
|
||||
: widget.remainingTime!;
|
||||
_startCountdownTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void _startCountdownTimer() {
|
||||
_countdownTimer?.cancel();
|
||||
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (_currentRemainingTime.inSeconds > 0) {
|
||||
_currentRemainingTime = Duration(seconds: _currentRemainingTime.inSeconds - 1);
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _initializeCamera() {
|
||||
|
|
@ -71,10 +103,6 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
}
|
||||
|
||||
void _setupAnimations() {
|
||||
_pulseController = AnimationController(
|
||||
duration: const Duration(milliseconds: 2000),
|
||||
vsync: this,
|
||||
)..repeat(reverse: true);
|
||||
_rotationController = AnimationController(
|
||||
duration: const Duration(seconds: 8),
|
||||
vsync: this,
|
||||
|
|
@ -83,9 +111,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
duration: const Duration(milliseconds: 3500),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
_pulseAnimation = Tween<double>(begin: 0.95, end: 1.05).animate(
|
||||
CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut),
|
||||
);
|
||||
|
||||
_rotationAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _rotationController, curve: Curves.linear),
|
||||
);
|
||||
|
|
@ -153,6 +179,24 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
}
|
||||
}
|
||||
|
||||
String _formatDistance(double distance) {
|
||||
if (distance >= 100) {
|
||||
return '${distance.round()}m';
|
||||
} else {
|
||||
return '${distance.toStringAsFixed(1)}m';
|
||||
}
|
||||
}
|
||||
|
||||
double _getDistanceFontSize(double distance) {
|
||||
if (distance >= 10000) {
|
||||
return 20;
|
||||
} else if (distance >= 1000) {
|
||||
return 26;
|
||||
} else {
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleMapVisibility() {
|
||||
setState(() {
|
||||
_isMapVisible = !_isMapVisible;
|
||||
|
|
@ -168,8 +212,8 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
void dispose() {
|
||||
_compassSubscription?.cancel();
|
||||
_locationTimer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
_controller?.dispose();
|
||||
_pulseController.dispose();
|
||||
_rotationController.dispose();
|
||||
_scanController.dispose();
|
||||
_miniMapController.dispose();
|
||||
|
|
@ -208,21 +252,21 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate: 'https://{s}.basemaps.cartocdn.com/dark_all/{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(
|
||||
markers: [
|
||||
Marker(
|
||||
point: userLocation,
|
||||
width: 80,
|
||||
height: 80,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: PulsingMarker(isUser: true),
|
||||
),
|
||||
Marker(
|
||||
point: targetLocation,
|
||||
width: 80,
|
||||
height: 80,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: PulsingMarker(isUser: false),
|
||||
),
|
||||
],
|
||||
|
|
@ -240,23 +284,132 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
onPressed: widget.onClose,
|
||||
icon: const Icon(Icons.close_rounded, color: Colors.white, size: 28),
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(kToolbarHeight + 10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.black.withOpacity(0.8),
|
||||
Colors.black.withOpacity(0.4),
|
||||
Colors.transparent,
|
||||
],
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
|
||||
child: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
toolbarHeight: kToolbarHeight + 10,
|
||||
leading: Container(
|
||||
margin: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.white.withOpacity(0.15),
|
||||
Colors.white.withOpacity(0.05),
|
||||
],
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: Colors.white.withOpacity(0.3),
|
||||
width: 1.5,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: widget.onClose,
|
||||
icon: SvgPicture.asset(Assets.icons.back.path, color: Colors.white,),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
title: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primary.withOpacity(0.3),
|
||||
AppColors.primary.withOpacity(0.1),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
border: Border.all(
|
||||
color: AppColors.primary.withOpacity(0.4),
|
||||
width: 1.5,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColors.primary.withOpacity(0.2),
|
||||
blurRadius: 15,
|
||||
spreadRadius: 2,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Text(
|
||||
'AR Hint',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 1.2,
|
||||
fontFamily: 'monospace'
|
||||
),
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.white.withOpacity(0.15),
|
||||
Colors.white.withOpacity(0.05),
|
||||
],
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: Colors.white.withOpacity(0.3),
|
||||
width: 1.5,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
},
|
||||
icon: SvgPicture.asset(Assets.icons.infoCircle.path, color: Colors.white,),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
title: const Text(
|
||||
'AR HINT',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2,
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
|
|
@ -273,6 +426,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
filter: ImageFilter.blur(sigmaX: 0.5, sigmaY: 0.5),
|
||||
child: Container(color: Colors.black.withOpacity(0.1)),
|
||||
),
|
||||
if (widget.remainingTime != null) _buildTimerWidget(),
|
||||
_buildAROverlay(),
|
||||
_buildMiniMap(),
|
||||
],
|
||||
|
|
@ -281,6 +435,64 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildTimerWidget() {
|
||||
if (widget.remainingTime == null) return const SizedBox.shrink();
|
||||
|
||||
final Duration timeToShow = _currentRemainingTime.inSeconds <= 0
|
||||
? (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;
|
||||
|
||||
return Positioned(
|
||||
top: kToolbarHeight + 60,
|
||||
right: 16,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 25, sigmaY: 25),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
isExpired
|
||||
? 'Expired'
|
||||
: hours > 0
|
||||
? '${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,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget _buildMapFAB() {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
|
|
@ -345,7 +557,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
return Stack(
|
||||
children: [
|
||||
CustomPaint(
|
||||
painter: HudPainter(animationValue: _pulseAnimation.value),
|
||||
painter: HudPainter(animationValue: 1.0),
|
||||
size: Size.infinite,
|
||||
),
|
||||
if (!isVisible)
|
||||
|
|
@ -362,16 +574,13 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
alignment: isLeft ? Alignment.centerLeft : Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: ScaleTransition(
|
||||
scale: _pulseAnimation,
|
||||
child: Icon(
|
||||
isLeft ? Icons.arrow_back_ios_new_rounded : Icons.arrow_forward_ios_rounded,
|
||||
color: AppColors.primary.withOpacity(0.8),
|
||||
size: 48,
|
||||
shadows: [
|
||||
Shadow(color: AppColors.primary.withOpacity(0.5), blurRadius: 15),
|
||||
],
|
||||
),
|
||||
child: Icon(
|
||||
isLeft ? Icons.arrow_back_ios_new_rounded : Icons.arrow_forward_ios_rounded,
|
||||
color: AppColors.primary.withOpacity(0.8),
|
||||
size: 48,
|
||||
shadows: [
|
||||
Shadow(color: AppColors.primary.withOpacity(0.5), blurRadius: 15),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -388,7 +597,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
bottom: 0,
|
||||
left: (1 + screenX) * (MediaQuery.of(context).size.width / 2) - 100,
|
||||
child: AnimatedBuilder(
|
||||
animation: Listenable.merge([_pulseAnimation, _rotationController, _scanAnimation]),
|
||||
animation: Listenable.merge([_rotationController, _scanAnimation]),
|
||||
builder: (context, child) {
|
||||
return SizedBox(
|
||||
width: 200,
|
||||
|
|
@ -397,7 +606,7 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
painter: AdvancedTargetPainter(
|
||||
isNear: _isNearTarget,
|
||||
distance: distance,
|
||||
pulseValue: _pulseAnimation.value,
|
||||
pulseValue: 1.0,
|
||||
rotationValue: _rotationController.value,
|
||||
scanValue: _scanAnimation.value,
|
||||
),
|
||||
|
|
@ -438,11 +647,11 @@ class _HintCameraWidgetState extends State<HintCameraWidget>
|
|||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'${distance.toStringAsFixed(1)}m',
|
||||
style: const TextStyle(
|
||||
_formatDistance(distance),
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 32,
|
||||
fontSize: _getDistanceFontSize(distance),
|
||||
letterSpacing: 0.5,
|
||||
fontFamily: 'monospace'
|
||||
),
|
||||
|
|
@ -501,10 +710,13 @@ class _PulsingMarkerState extends State<PulsingMarker>
|
|||
color: color.withOpacity(0.5),
|
||||
border: Border.all(color: color, width: 2),
|
||||
),
|
||||
child: Icon(
|
||||
widget.isUser ? Icons.my_location : Icons.star,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset(
|
||||
widget.isUser ? Assets.icons.gps.path : Assets.icons.locationCross.path,
|
||||
color: Colors.black,
|
||||
width: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:lba/gen/assets.gen.dart';
|
||||
import 'package:lba/res/colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../models/hunt_card.dart';
|
||||
import '../providers/hunt_provider.dart';
|
||||
import 'hunt_timer_widget.dart';
|
||||
import 'hint_camera_widget.dart';
|
||||
import 'dart:math';
|
||||
|
|
@ -100,6 +102,8 @@ class _HuntCardWidgetState extends State<HuntCardWidget>
|
|||
}
|
||||
|
||||
void _openARHint() {
|
||||
final huntState = context.read<HuntState>();
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
|
@ -107,6 +111,8 @@ class _HuntCardWidgetState extends State<HuntCardWidget>
|
|||
targetLatitude: widget.card.hintLatitude,
|
||||
targetLongitude: widget.card.hintLongitude,
|
||||
hintDescription: widget.card.hintDescription,
|
||||
remainingTime: huntState.timeRemaining,
|
||||
cardTitle: widget.card.category,
|
||||
onHintFound: () {
|
||||
// TODO: Handle what happens when the hint is found.
|
||||
// For example, show a success message or update state.
|
||||
|
|
|
|||
|
|
@ -250,8 +250,8 @@ class _LeaderboardWidgetState extends State<LeaderboardWidget>
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 4,
|
||||
height: 4,
|
||||
width: 6,
|
||||
height: 6,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.confirmButton,
|
||||
shape: BoxShape.circle,
|
||||
|
|
@ -592,9 +592,9 @@ class _LeaderboardWidgetState extends State<LeaderboardWidget>
|
|||
size: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 1),
|
||||
const SizedBox(height: 3),
|
||||
] else
|
||||
const SizedBox(height: 1),
|
||||
const SizedBox(height: 3),
|
||||
Container(
|
||||
width: 70,
|
||||
height: height,
|
||||
|
|
|
|||
Loading…
Reference in New Issue