import 'dart:ffi'; import 'dart:io'; import 'package:ambient/firebase.dart'; import 'package:ambient/services/spotify.dart'; import 'main.dart'; import 'package:vector_math/vector_math.dart'; import 'package:image_picker/image_picker.dart'; import 'package:flutter/material.dart'; import 'package:palette_generator/palette_generator.dart'; import 'package:flutter_color_models/flutter_color_models.dart'; class StateMoodPage extends StatefulWidget { const StateMoodPage({super.key}); @override State<StateMoodPage> createState() => MoodPage(); } enum Moods { none, happy, sad ,angry, noble, clean, courageous, fresh, compassionn, simple, dramatic} extension MoodsExtention on Moods { Color get color { switch (this) { case Moods.none: return Color.fromARGB(255, 75, 75, 75); case Moods.happy: return Color.fromARGB(255, 255, 255, 0); case Moods.sad: return Color.fromARGB(255, 0, 0, 255); case Moods.angry: return Color.fromARGB(255, 255, 0, 0); case Moods.noble: return Color.fromARGB(255, 127, 69, 216); case Moods.clean: return Color.fromARGB(255, 255, 255, 255); case Moods.courageous: return Color.fromARGB(255, 255, 165, 0); case Moods.fresh: return Color.fromARGB(255, 0, 255, 0); case Moods.compassionn: return Color.fromARGB(255, 255, 70, 253); case Moods.simple: return Color.fromARGB(255, 103, 64, 45); case Moods.dramatic: return Color.fromARGB(255, 0, 0, 0); } } } class MoodPage extends State<StateMoodPage> { final ImagePicker _picker = ImagePicker(); late PaletteGenerator paletteGenerator; Moods? currentMood = selectedMoodAsEnum; String imagePath = ""; //besorgt ein image file aus der galarie _getFromGallery() async { try { XFile? pickedFile = await _picker.pickImage( source: ImageSource.gallery, ); if (pickedFile != null) { musicCangable = true; imagePath = pickedFile.path; setState(() { usesPicture = true; currentMoodsImage = File(imagePath); }); } } catch (e) { print("could not load image: "); print(e); } } //sendet den befehl music zum passenden genre rauszusuchen _changeMusic() async { Spotify spotify = Spotify(); //code zum musik ändern String hexcode = selectedMood.red.toRadixString(16) + selectedMood.green.toRadixString(16) + selectedMood.blue.toRadixString(16); print(hexcode); String genre = await changeFirebase().getGenreByHex(hexcode); print("genre = " + genre); spotify.playGenre(genre); } //vergleicht zwei farben auf ähnlichkeit _getColorDistance(Color c1, Color c2) { LabColor labC1 = LabColor.fromColor(c1); LabColor labC2 = LabColor.fromColor(c2); double distance = 0; print("Lightness bild: " + labC1.lightness.toDouble().toString()); print("Lightness referenz: " + labC2.lightness.toDouble().toString()); Vector3 v1 = Vector3(labC1.lightness.toDouble(), labC1.a.toDouble(), labC1.b.toDouble()); Vector3 v2 = Vector3(labC2.lightness.toDouble(), labC2.a.toDouble(), labC2.b.toDouble()); distance = v1.distanceTo(v2).toDouble(); return distance; } _determineMoodToMatch(Color col) { double distance = 1000000.0; Moods newMood = Moods.none; if(musicCangable){ for (var value in Moods.values) { double colorDistance = _getColorDistance(col, value.color); if (colorDistance < distance && value != Moods.none) { distance = colorDistance; newMood = value; } } _updateColorPalete(col); selectedMoodAsEnum = newMood; selectedMood = newMood.color; _changeMusic(); musicCangable = false; return newMood; }else{ for (var value in Moods.values) { double colorDistance = _getColorDistance(selectedMood, value.color); if (colorDistance < distance && value != Moods.none) { distance = colorDistance; newMood = value; } } musicCangable = false; return newMood; } } _updateColorPalete(Color col){ if(!usesPicture){ if(col.value != Color.fromARGB(255, 0, 0, 0).value){ col = ligten(col, 0.2); } primaryColor = col; } backGroundColor = Color.fromARGB(col.alpha - 230, col.red, col.green, col.blue); primaryColor = col; onPrimary = darken(col, 0.5); Color shiftedColor = ligten(col,0.1);; primaryContainer = shiftedColor; onPrimaryContainer = darken(shiftedColor, 0.5); } //returend die liste mit den moods _getMoodList(){ return Column(children: <Widget>[ RadioListTile<Moods>( title: const Text( "Sad", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.sad, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.sad.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Angry", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.angry, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.angry.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Noble", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.noble, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.noble.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Clean", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.clean, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.clean.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Happy", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.happy, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.happy.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Courageous", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.courageous, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.courageous.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Fresh", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.fresh, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.fresh.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Compassionn", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.compassionn, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.compassionn.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Simple", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.simple, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.simple.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), RadioListTile<Moods>( title: const Text( "Dramatic", style: TextStyle( color: Color.fromARGB(255, 0, 0, 0), ), ), tileColor: backGroundColor, activeColor: primaryColor, value: Moods.dramatic, groupValue: currentMood, onChanged: (Moods? value) { setState(() { usesPicture = false; musicCangable = true; primaryColor = Moods.dramatic.color; _updateColorPalete(primaryColor); currentMood = value; }); }, ), ]); } // setzt das bild(falls vorhanden) in einem container ein der sich and die bildschirmgröße anpasst _getContainerTodisplay() { BoxDecoration deco = new BoxDecoration(); var image; image = _getImageTodisplay(); if (usesPicture) { deco = BoxDecoration( image: DecorationImage( fit: BoxFit.fitWidth, image: image, ), ); } else { deco = BoxDecoration( color: primaryColor, ); } return GestureDetector( onDoubleTap: (){ _getFromGallery(); }, child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.width * (9.0 / 16.0), decoration: deco, ), ); } //generiert ein image aus dem imagefile _getImageTodisplay() { var imageToShow; try { imageToShow = FileImage(currentMoodsImage); return imageToShow; } catch (e) { return null; } } // generiert einen paletegenerator vom aktiellen image Future<PaletteGenerator> _updatePaletteGenerator() async { if (imagePath != "") { paletteGenerator = await PaletteGenerator.fromImageProvider( _getImageTodisplay(), ); } return paletteGenerator; } //gibt dem widged den colorindicator zur momentan generierten Primärfarbe und die Moodliste mit dem aktuell auszuwählenden Mood zurück _getCollorIndicatorAndMoodList() { return FutureBuilder<PaletteGenerator>( future: _updatePaletteGenerator(), // async work builder: (BuildContext context, AsyncSnapshot<PaletteGenerator> snapshot) { switch (snapshot.connectionState) { case ConnectionState.waiting: return const Center(child: CircularProgressIndicator()); default: if (snapshot.hasError && usesPicture) { currentMood = _determineMoodToMatch(primaryColor); return Column( children: <Widget>[ PaletteSquare( color: primaryColor), _getMoodList(), ]); } else if(snapshot.hasError) { return Column( children: <Widget>[ PaletteSquare( color: primaryColor), _getMoodList(), ]); } else if (usesPicture){ Color? colorToUse = snapshot.data!.vibrantColor?.color; colorToUse ??= snapshot.data!.dominantColor?.color; currentMood = _determineMoodToMatch(colorToUse!); return Column( children: <Widget>[ PaletteSquare(color: colorToUse), _getMoodList(), ]); }else{ return Column( children: <Widget>[ PaletteSquare(color: primaryColor), _getMoodList(), ]); } } }); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SingleChildScrollView( child: Column( children: <Widget>[ _getContainerTodisplay(), _getCollorIndicatorAndMoodList(), //_getMoodList(), ], ), ), ), ); } } @immutable class PaletteSquare extends StatelessWidget { const PaletteSquare({ required this.color, super.key, }); final Color color; @override Widget build(BuildContext context) { Widget square = Container( decoration: BoxDecoration( color: color, border: Border.all(width: 1.0, color: color)), width: MediaQuery.of(context).size.width, height: 40, ); return square; } }