You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dafl_music/Sources/dafl_project_flutter/lib/main.dart

631 lines
19 KiB

import 'dart:async';
import 'dart:ui';
import 'dart:math';
import './views/pages/home/p_home.dart';
import './views/pages/main/p_main.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:rive/rive.dart' as riv;
import '../controller/controller.dart';
import 'model/spot.dart';
import 'api/api.dart';
import 'dart:developer' as dev;
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
static Controller controller = Controller();
static Api api = Api();
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
Paint.enableDithering = true;
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: [SystemUiOverlay.top],
);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarIconBrightness: Brightness.dark, // For Android (dark icons)
statusBarBrightness: Brightness.dark, // For iOS (dark icons)
));
return ChangeNotifierProvider(
create: (context) => CardProvider(),
child: const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Dafl Music',
home: HomePage(),
));
}
}
enum CardStatus { like, disLike, discovery, message }
class CardProvider extends ChangeNotifier {
final List<Spot> _spotsList = MyApp.controller.currentUser.spots;
bool _isDragging = false;
double _angle = 0;
Offset _position = Offset.zero;
Size _screenSize = Size.zero;
List<Spot> get spotsList => _spotsList;
bool get isDragging => _isDragging;
Offset get position => _position;
double get angle => _angle;
void setScreenSize(Size screenSize) => _screenSize = screenSize;
void startPosition(DragStartDetails details) {
_isDragging = true;
notifyListeners();
}
void updatePosition(DragUpdateDetails details) {
_position += details.delta;
final x = _position.dx;
_angle = 45 * x / _screenSize.width;
notifyListeners();
}
void endPosition(context) {
_isDragging = false;
notifyListeners();
final status = getStatus(force: true);
switch (status) {
case CardStatus.like:
like(context);
break;
case CardStatus.disLike:
dislike();
break;
case CardStatus.discovery:
discovery(context);
break;
case CardStatus.message:
message(context);
break;
default:
resetPosition();
}
}
void resetPosition() {
_isDragging = false;
_position = Offset.zero;
_angle = 0;
notifyListeners();
}
double getStatusOpacity() {
const delta = 100;
final pos = max(_position.dx.abs(), _position.dy.abs());
final opacity = pos / delta;
return min(opacity, 1);
}
CardStatus? getStatus({bool force = false}) {
final x = _position.dx;
final y = _position.dy;
final forceDiscovery = x.abs() < 80;
if (force) {
const delta = 100;
if (x >= delta) {
return CardStatus.like;
} else if (x <= -delta) {
return CardStatus.disLike;
} else if (y <= -delta / 2 && forceDiscovery) {
return CardStatus.message;
} else if (y >= delta * 2 && x.abs() < 100) {
return CardStatus.discovery;
}
}
const delta = 20;
if (y <= -delta * 2 && forceDiscovery) {
return CardStatus.message;
} else if (y >= delta * 2 && x.abs() < 80) {
return CardStatus.discovery;
} else if (x >= delta) {
return CardStatus.like;
} else if (x <= -delta) {
return CardStatus.disLike;
}
return null;
}
void dislike() {
dev.log("dislike");
_angle = -20;
_position -= Offset(2 * _screenSize.width, 0);
_nextCard();
notifyListeners();
}
void discovery(BuildContext context) {
dev.log("discovery");
_angle = 0;
_position -= Offset(0, -_screenSize.height);
_discoveryCard();
dev.log("discovery");
showToastWidget(
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 30.0, sigmaY: 30.0),
child: Container(
width: 300.0,
height: 70.0,
decoration: BoxDecoration(
color: Colors.grey.shade900.withOpacity(0.7),
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MyApp.controller.currentUser.discovery.contains(
MyApp.controller.currentUser.spots.last.music)
? const Icon(
Icons.info_rounded,
size: 40,
color: Colors.grey,
)
: const Icon(
Icons.check_rounded,
size: 40,
color: Colors.grey,
),
const SizedBox(
width: 10,
),
MyApp.controller.currentUser.discovery.contains(
MyApp.controller.currentUser.spots.last.music)
? const Text(
"Déjà dans vos discovery",
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold,
fontSize: 17),
)
: const Text("Ajouté à discovery",
style: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold,
fontSize: 17))
]))))),
context: context,
animation: StyledToastAnimation.fade,
reverseAnimation: StyledToastAnimation.fade,
position: StyledToastPosition.top,
animDuration: const Duration(milliseconds: 400),
duration: const Duration(milliseconds: 1500),
curve: Curves.linear,
reverseCurve: Curves.linear,
);
if (!MyApp.controller.currentUser.discovery
.contains(MyApp.controller.currentUser.spots.last.music)) {
MyApp.controller.currentUser.spots.last.music.defineDate();
MyApp.controller.currentUser
.addDiscovery(MyApp.controller.currentUser.spots.last.music);
notifyListeners();
}
}
void message(context) {
dev.log("message");
_angle = 0;
_position -= Offset(0, _screenSize.height);
_messageCard();
showModalBottomSheet(
isDismissible: false,
useRootNavigator: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
context: context,
constraints: const BoxConstraints(
maxWidth: 600,
maxHeight: double.infinity,
),
builder: (context) => buildSheet(context),
);
notifyListeners();
}
Widget buildSheet(context) {
final messageTextField = TextEditingController();
return SingleChildScrollView(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 500,
width: 380,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.4),
offset: const Offset(
0,
0,
),
blurRadius: 10.0,
spreadRadius: 2.0),
BoxShadow(
color: Colors.white.withOpacity(0.3),
offset: const Offset(0.0, 0.0),
blurRadius: 0.0,
spreadRadius: 0.0)
],
color: const Color(0xFF232123),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Column(
children: [
Container(
height: 5,
width: 130,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: const Color(0xFF8A8A8A),
),
),
const SizedBox(
height: 30,
),
Container(
width: double.infinity,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: const Color(0xFF302C30),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: TextField(
keyboardAppearance: Brightness.dark,
controller: messageTextField,
maxLength: 300,
style: TextStyle(
fontFamily: 'DMSans',
color: Colors.white.withOpacity(1),
fontSize: 17,
fontWeight: FontWeight.w200),
expands: true,
maxLines: null,
textInputAction: TextInputAction.send,
decoration: const InputDecoration(
hintStyle: TextStyle(
color: Colors.white,
),
border: InputBorder.none,
hintText: "Mon message",
),
),
),
),
const SizedBox(
height: 20,
),
SizedBox(
width: double.infinity,
height: 70,
child: ElevatedButton(
onPressed: () {
sendMessage(messageTextField.text,
MyApp.controller.currentUser.spots.last.userId);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF3F1DC3),
textStyle: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(17)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Text("Envoyer"),
Opacity(
opacity: 0.2,
child: Image.asset(
"assets/images/send_logo.png",
),
)
],
),
),
)
],
),
),
),
);
}
void sendMessage(String message, String userId) {
dev.log(MyApp.controller.currentUser.spots.last.userId);
}
void like(context) {
dev.log("like");
_angle = 20;
_position += Offset(2 * _screenSize.width, 0);
_nextCard();
notifyListeners();
}
Future _nextCard() async {
dev.log(_spotsList.length.toString());
if (_spotsList.isEmpty) {
dev.log('dernier');
return;
} else {
await Future.delayed(const Duration(milliseconds: 200));
dev.log(_spotsList.last.music.name);
_spotsList.removeLast();
resetPosition();
}
}
Future _discoveryCard() async {
await Future.delayed(const Duration(milliseconds: 200));
resetPosition();
}
Future _messageCard() async {
await Future.delayed(const Duration(milliseconds: 200));
resetPosition();
}
}
class Splash extends StatefulWidget {
const Splash({Key? key}) : super(key: key);
@override
State<Splash> createState() => _SplashState();
}
class _SplashState extends State<Splash> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
Timer(const Duration(seconds: 2), () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => const MainPage()));
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF141414),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
SizedBox(
height: 300,
width: 300,
child:
riv.RiveAnimation.asset('assets/images/new_file (2).riv'),
),
SizedBox(height: 50),
])));
}
}
Object notify(int index, context, {bool isError = true}) {
double height = MediaQuery.of(context).size.height;
String message;
if (isError == true) {
switch (index) {
case 0:
{
message = "Ce nom d'utilisateur existe déjà ! Veuillez réessayer.";
break;
}
case 1:
{
message = "Mots de passe différents ! Veuillez réessayer.";
break;
}
case 2:
{
message = "Identifiant incorrect ! Veuillez réessayer.";
break;
}
case 3:
{
message =
"Mot de passe incorrect ! Votre mot de passe doit contenir 8 caractères minimum.";
break;
}
case 4:
{
message = "Mot de passe incorrect ! Veuillez réessayer.";
break;
}
case 5:
{
message =
"Une erreur est survenue lors de la liaison de votre compte. Veuillez réessayer.";
break;
}
default:
message =
"Une erreur est survenue pendant l'inscription. Veuillez réessayer.";
break;
}
return ScaffoldMessenger.of(context).showSnackBar(SnackBar(
dismissDirection: DismissDirection.down,
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.transparent,
elevation: 0,
content: Stack(
clipBehavior: Clip.none,
children: [
Container(
padding: EdgeInsets.fromLTRB(20, height / 110, 20, 0),
height: 90,
decoration: BoxDecoration(
image: const DecorationImage(
image: AssetImage("assets/images/backgroundNotify.png"),
fit: BoxFit.cover),
gradient: const LinearGradient(
colors: [Color(0xFF81052a), Color(0xFF810548)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
borderRadius: const BorderRadius.all(Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(4, 8), // Shadow position
),
],
),
child: Row(children: [
const SizedBox(
height: 48,
width: 48,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Ho ho !",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(message,
style: const TextStyle(),
overflow: TextOverflow.ellipsis,
maxLines: 2)
]))
])),
Positioned(
top: -50,
left: -20,
child: Container(
color: Colors.transparent,
height: 110,
width: 110,
child: const riv.RiveAnimation.asset(
"assets/images/error_icon.riv"),
)),
],
)));
} else {
switch (index) {
case 0:
{
message = "Vous avez changer votre identifiant avec succès";
break;
}
case 1:
{
message = "Vous avez changer votre mot de passe avec succès";
break;
}
case 2:
{
message = "Vous avez relié votre compte Spotify avec succès";
break;
}
default:
message = "L'opération a bien été éxécutée";
break;
}
return ScaffoldMessenger.of(context).showSnackBar(SnackBar(
dismissDirection: DismissDirection.down,
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.transparent,
elevation: 0,
content: Stack(
clipBehavior: Clip.none,
children: [
Container(
padding: EdgeInsets.fromLTRB(20, height / 110, 20, 0),
height: 90,
decoration: BoxDecoration(
image: const DecorationImage(
image: AssetImage("assets/images/valid_background.png"),
fit: BoxFit.cover),
gradient: const LinearGradient(
colors: [Color(0xFF81052a), Color(0xFF810548)],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
borderRadius: const BorderRadius.all(Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(4, 8), // Shadow position
),
],
),
child: Row(
children: [
const SizedBox(
height: 48,
width: 48,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Super !",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
message,
style: const TextStyle(),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
],
),
),
],
),
),
Positioned(
top: -50,
left: -20,
child: Container(
color: Colors.transparent,
height: 110,
width: 110,
child: const riv.RiveAnimation.asset(
"assets/images/valid_icon.riv"),
)),
],
)));
}
}