After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 816 B |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 223 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 230 B |
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/Material.dart';
|
||||
|
||||
import '../values/constants.dart';
|
||||
|
||||
class BackButtonComponent extends StatefulWidget {
|
||||
const BackButtonComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<BackButtonComponent> createState() => _BackButtonComponentState();
|
||||
}
|
||||
|
||||
class _BackButtonComponentState extends State<BackButtonComponent> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: ClipOval(
|
||||
child: Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Colors.white,
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.arrow_back_outlined,
|
||||
color: bgColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/values/constants.dart';
|
||||
|
||||
class EditablePostComponent extends StatefulWidget {
|
||||
const EditablePostComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<EditablePostComponent> createState() => _EditablePostComponentState();
|
||||
}
|
||||
|
||||
class _EditablePostComponentState extends State<EditablePostComponent> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
child: Container(
|
||||
constraints: BoxConstraints(maxWidth: 400),
|
||||
width: double.infinity,
|
||||
color: warningBttnColor,
|
||||
child: Column(
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: 1 / 1,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
// add border
|
||||
border: Border.all(width: 3.0, color: grayColor),
|
||||
// set border radius
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
// implement image
|
||||
child: const Image(
|
||||
image: AssetImage("assets/images/exemple_cover.png"),
|
||||
fit: BoxFit.cover,
|
||||
width: double.infinity,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 25, 15, 25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
"France, Lyon",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white, fontSize: 13.sp),
|
||||
maxFontSize: 20,
|
||||
),
|
||||
Image(
|
||||
image: AssetImage("assets/images/camera_icon.png"),
|
||||
width: 30,
|
||||
),
|
||||
AutoSizeText(
|
||||
"10 Juil. 2023",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white, fontSize: 13.sp),
|
||||
maxFontSize: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 0, 10, 25),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: TextFormField(
|
||||
keyboardAppearance: Brightness.dark,
|
||||
minLines: 1,
|
||||
cursorColor: primaryColor,
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300),
|
||||
maxLines: 4,
|
||||
maxLength: 120,
|
||||
decoration: InputDecoration(
|
||||
counterStyle: GoogleFonts.plusJakartaSans(
|
||||
color: grayText, fontSize: 9),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(width: 0, color: Colors.transparent),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10))),
|
||||
contentPadding:
|
||||
const EdgeInsets.only(top: 0, bottom: 0, left: 0),
|
||||
fillColor: Colors.transparent,
|
||||
filled: true,
|
||||
focusColor: Colors.transparent,
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(width: 0, color: Colors.transparent),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10))),
|
||||
hintText: 'Description...',
|
||||
hintStyle: GoogleFonts.plusJakartaSans(
|
||||
color: grayText,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/components/play_button_component.dart';
|
||||
import 'package:text_scroll/text_scroll.dart';
|
||||
import '../model/Music.dart';
|
||||
|
||||
class MusicListComponent extends StatelessWidget {
|
||||
final Music music;
|
||||
const MusicListComponent({
|
||||
Key? key,
|
||||
required this.music,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(bottom: 14),
|
||||
child: Row(
|
||||
children: [
|
||||
LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
if (music.cover != null) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
child: music.cover != null
|
||||
? FadeInImage.assetNetwork(
|
||||
height: 60,
|
||||
width: 60,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: "assets/images/loadingPlaceholder.gif",
|
||||
image: music.cover!)
|
||||
: Container(
|
||||
height: 60,
|
||||
width: 60,
|
||||
color: Colors.grey,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Image(
|
||||
image: AssetImage("assets/images/exemple_cover.png"),
|
||||
height: 60,
|
||||
width: 60,
|
||||
);
|
||||
}
|
||||
}),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
flex: 10,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 8,
|
||||
child: ScrollConfiguration(
|
||||
behavior:
|
||||
ScrollBehavior().copyWith(scrollbars: false),
|
||||
child: TextScroll(
|
||||
music.title ?? "Unknown",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w700),
|
||||
mode: TextScrollMode.endless,
|
||||
pauseBetween: Duration(milliseconds: 2500),
|
||||
velocity: Velocity(pixelsPerSecond: Offset(30, 0)),
|
||||
intervalSpaces: 10,
|
||||
),
|
||||
)),
|
||||
Icon(
|
||||
Icons.explicit,
|
||||
color: Colors.grey.withOpacity(0.7),
|
||||
size: 17,
|
||||
),
|
||||
],
|
||||
),
|
||||
ScrollConfiguration(
|
||||
behavior: ScrollBehavior().copyWith(scrollbars: false),
|
||||
child: Text(
|
||||
music.artists.first.name ?? "Unknown",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.grey, fontWeight: FontWeight.w400),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
PlayButtonComponent(
|
||||
urlPreview: music.previewUrl,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:flutter_animated_play_button/flutter_animated_play_button.dart';
|
||||
import 'package:ionicons/ionicons.dart';
|
||||
|
||||
class PlayButtonComponent extends StatefulWidget {
|
||||
final String? urlPreview;
|
||||
const PlayButtonComponent({Key? key, required this.urlPreview})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<PlayButtonComponent> createState() => _PlayButtonComponentState();
|
||||
}
|
||||
|
||||
class _PlayButtonComponentState extends State<PlayButtonComponent> {
|
||||
bool isPlaying = true;
|
||||
final player = AudioPlayer();
|
||||
void switchStatePlaying() {
|
||||
setState(() {
|
||||
isPlaying = !isPlaying;
|
||||
});
|
||||
stopSong();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
player.onPlayerComplete.listen((event) {
|
||||
switchStatePlaying();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!isPlaying) {
|
||||
playSong();
|
||||
} else {}
|
||||
return isPlaying
|
||||
? GestureDetector(
|
||||
onTap: switchStatePlaying,
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: Icon(
|
||||
Ionicons.play_circle_outline,
|
||||
color: Colors.grey.withOpacity(0.3),
|
||||
size: 30,
|
||||
)),
|
||||
)
|
||||
: GestureDetector(
|
||||
onTap: switchStatePlaying,
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: AnimatedPlayButton(
|
||||
stopped: false,
|
||||
color: Colors.grey.withOpacity(0.3),
|
||||
onPressed: () {},
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> playSong() async {
|
||||
if (widget.urlPreview != null) {
|
||||
await player.play(UrlSource(widget.urlPreview ?? ""));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stopSong() async {
|
||||
await player.stop();
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class PostButtonComponent extends StatelessWidget {
|
||||
const PostButtonComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
constraints: BoxConstraints(maxWidth: 400),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(colors: [
|
||||
Color(0xFF141414),
|
||||
Color(0xFF272727),
|
||||
Color(0xFF141414)
|
||||
]),
|
||||
borderRadius: BorderRadius.circular(10000)),
|
||||
padding: EdgeInsets.symmetric(vertical: 25),
|
||||
width: double.infinity,
|
||||
child: Align(
|
||||
child: Text(
|
||||
"Publier la capsule",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Color(0xFF474747),
|
||||
fontWeight: FontWeight.w800,
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 24),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/components/statistics_component.dart';
|
||||
|
||||
import '../model/User.dart';
|
||||
|
||||
class ProfileComponent extends StatelessWidget {
|
||||
final User user;
|
||||
const ProfileComponent({Key? key, required this.user}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
ClipOval(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 200, maxHeight: 200),
|
||||
child: Image(
|
||||
image: AssetImage("assets/images/exemple_profile.png"),
|
||||
height: 100.w,
|
||||
width: 100.w,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
AutoSizeText(
|
||||
"@${user.pseudo}",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
fontSize: 15.sp,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400),
|
||||
maxFontSize: 30,
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
StatisticsComponent(
|
||||
user: user,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../values/constants.dart';
|
||||
|
||||
class SearchBarComponent extends StatefulWidget {
|
||||
final String? text;
|
||||
final VoidCallback? callback;
|
||||
const SearchBarComponent({Key? key, this.text, this.callback})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<SearchBarComponent> createState() => _SearchBarComponentState();
|
||||
}
|
||||
|
||||
class _SearchBarComponentState extends State<SearchBarComponent> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: widget.callback,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
child: Container(
|
||||
constraints: BoxConstraints(maxWidth: 600),
|
||||
color: searchBarColor,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.fromLTRB(defaultPadding, 16, defaultPadding, 16),
|
||||
child: Text(
|
||||
widget.text ?? "Chercher une musique...",
|
||||
style: GoogleFonts.plusJakartaSans(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/values/icons.dart';
|
||||
|
||||
import '../values/constants.dart';
|
||||
|
||||
class SettingPartComponent extends StatelessWidget {
|
||||
final JustMusicIcon icon;
|
||||
final String label;
|
||||
final bool important;
|
||||
const SettingPartComponent(
|
||||
{Key? key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
this.important = false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
color: important ? warningBttnColor : settingColor,
|
||||
borderOnForeground: false,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
print('InkWell was tapped!');
|
||||
},
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.white.withOpacity(0.08),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
defaultPadding, 19, defaultPadding, 19),
|
||||
child: Row(
|
||||
children: [
|
||||
Image(
|
||||
image: AssetImage(icon.imagePath),
|
||||
width: 13,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Expanded(
|
||||
flex: 10,
|
||||
child: Text(
|
||||
label,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white, fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Transform(
|
||||
alignment: Alignment.center,
|
||||
transform: Matrix4.rotationY(3.14159265),
|
||||
child: Image(
|
||||
image: AssetImage("assets/images/return_icon.png"),
|
||||
height: 11,
|
||||
opacity: const AlwaysStoppedAnimation(.5),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../model/User.dart';
|
||||
import '../values/constants.dart';
|
||||
|
||||
class StatisticsComponent extends StatelessWidget {
|
||||
final User user;
|
||||
const StatisticsComponent({Key? key, required this.user}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
AutoSizeText(
|
||||
user.followed.toString(),
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15.w),
|
||||
maxFontSize: 30,
|
||||
),
|
||||
AutoSizeText(
|
||||
"Suivis",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: grayText, fontSize: 12.w),
|
||||
maxFontSize: 30,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
user.followers.toString(),
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15.w),
|
||||
maxFontSize: 30,
|
||||
),
|
||||
AutoSizeText(
|
||||
"Followers",
|
||||
style:
|
||||
GoogleFonts.plusJakartaSans(color: grayText, fontSize: 12.w),
|
||||
maxFontSize: 30,
|
||||
)
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
user.capsules.toString(),
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15.w),
|
||||
maxFontSize: 30,
|
||||
),
|
||||
AutoSizeText(
|
||||
"Capsules",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: grayText, fontSize: 12.w),
|
||||
maxFontSize: 30,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:justmusic/screens/profile_screen.dart';
|
||||
|
||||
Route createRoute() {
|
||||
return PageRouteBuilder(
|
||||
pageBuilder: (context, animation, secondaryAnimation) =>
|
||||
const ProfileScreen(),
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
||||
const begin = Offset(1.0, 0.0);
|
||||
const end = Offset.zero;
|
||||
const curve = Curves.ease;
|
||||
|
||||
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
|
||||
|
||||
return SlideTransition(
|
||||
position: animation.drive(tween),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:justmusic/components/back_button.dart';
|
||||
import 'package:justmusic/screens/search_song_screen.dart';
|
||||
import '../components/editable_post_component.dart';
|
||||
import '../components/post_button_component.dart';
|
||||
import '../values/constants.dart';
|
||||
|
||||
class PostScreen extends StatefulWidget {
|
||||
const PostScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PostScreen> createState() => _PostScreenState();
|
||||
}
|
||||
|
||||
class _PostScreenState extends State<PostScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final scrollController = ScrollController();
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _animation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 400),
|
||||
);
|
||||
|
||||
_animation = Tween<double>(begin: 0.0, end: 400.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void openDetailPost() {
|
||||
showModalBottomSheet(
|
||||
transitionAnimationController: _controller,
|
||||
barrierColor: Colors.black.withOpacity(0.7),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 1,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600,
|
||||
),
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(20), topRight: Radius.circular(20))),
|
||||
builder: ((context) {
|
||||
return const ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
|
||||
child: SearchSongScreen());
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
backgroundColor: bgColor,
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: PreferredSize(
|
||||
preferredSize: Size(double.infinity, 80),
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: defaultPadding,
|
||||
right: defaultPadding,
|
||||
top: defaultPadding),
|
||||
child: Row(
|
||||
children: [BackButtonComponent()],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: defaultPadding, right: defaultPadding),
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("assets/images/background_justMusic.png"),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
ScrollConfiguration(
|
||||
behavior: ScrollBehavior().copyWith(scrollbars: false),
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100.h,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: openDetailPost,
|
||||
child: EditablePostComponent(),
|
||||
),
|
||||
SizedBox(
|
||||
height: 40.h,
|
||||
),
|
||||
PostButtonComponent(),
|
||||
SizedBox(
|
||||
height: 40.h,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/values/icons.dart';
|
||||
import '../components/profile_component.dart';
|
||||
import '../components/setting_part_component.dart';
|
||||
import '../main.dart';
|
||||
import '../values/constants.dart';
|
||||
|
||||
class ProfileScreen extends StatefulWidget {
|
||||
const ProfileScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||
}
|
||||
|
||||
class _ProfileScreenState extends State<ProfileScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: PreferredSize(
|
||||
preferredSize: Size(double.infinity, 58),
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
color: bgAppBar,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
|
||||
child: Stack(
|
||||
alignment: Alignment.centerLeft,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Container(
|
||||
height: 15,
|
||||
width: 15,
|
||||
child: Image(
|
||||
image: AssetImage("assets/images/return_icon.png"),
|
||||
height: 8,
|
||||
),
|
||||
)),
|
||||
Align(
|
||||
child: Text(
|
||||
"Profile",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
color: bgColor,
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: settingPadding),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 68.h, bottom: 40),
|
||||
child:
|
||||
ProfileComponent(user: MyApp.userViewModel.userCurrent),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(bottom: 12, left: defaultPadding),
|
||||
child: Text(
|
||||
"Compte",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: grayText,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 16),
|
||||
),
|
||||
),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Column(
|
||||
children: const [
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.profile,
|
||||
label: 'Compte',
|
||||
),
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.history,
|
||||
label: 'Historiques des capsules',
|
||||
),
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.spotify,
|
||||
label: 'Lier un compte Spotify',
|
||||
),
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.trash,
|
||||
label: 'Supprimer mon compte',
|
||||
),
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.cross,
|
||||
label: 'Déconnexion',
|
||||
important: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 12, left: defaultPadding, top: 40),
|
||||
child: Text(
|
||||
"Préférences",
|
||||
style: GoogleFonts.plusJakartaSans(
|
||||
color: grayText,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 16),
|
||||
),
|
||||
),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Column(
|
||||
children: const [
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.theme,
|
||||
label: 'Thême de l\'application',
|
||||
),
|
||||
SettingPartComponent(
|
||||
icon: JustMusicIcon.notification,
|
||||
label: 'Notifications',
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/Material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:justmusic/model/Music.dart';
|
||||
|
||||
import '../components/music_list_component.dart';
|
||||
import '../values/constants.dart';
|
||||
import '../main.dart';
|
||||
|
||||
class SearchSongScreen extends StatefulWidget {
|
||||
const SearchSongScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SearchSongScreen> createState() => _SearchSongScreenState();
|
||||
}
|
||||
|
||||
class _SearchSongScreenState extends State<SearchSongScreen> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final TextEditingController _textEditingController = TextEditingController();
|
||||
|
||||
Future<void> resetFullScreen() async {
|
||||
await SystemChannels.platform.invokeMethod<void>(
|
||||
'SystemChrome.restoreSystemUIOverlays',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController.addListener(_scrollListener);
|
||||
}
|
||||
|
||||
Future<void> _scrollListener() async {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
filteredData.addAll(await MyApp.musicViewModel.getMusicsWithName(
|
||||
_textEditingController.text,
|
||||
limit: 10,
|
||||
offset: filteredData.length));
|
||||
setState(() {
|
||||
filteredData = filteredData;
|
||||
});
|
||||
}
|
||||
if (_scrollController.offset >=
|
||||
_scrollController.position.maxScrollExtent &&
|
||||
!_scrollController.position.outOfRange) {
|
||||
setState(() {
|
||||
//you can do anything here
|
||||
});
|
||||
}
|
||||
if (_scrollController.offset <=
|
||||
_scrollController.position.minScrollExtent &&
|
||||
!_scrollController.position.outOfRange) {
|
||||
setState(() {
|
||||
Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
List<Music> filteredData = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenHeight = MediaQuery.of(context).size.height;
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
resetFullScreen();
|
||||
}
|
||||
},
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(
|
||||
sigmaX: 60.0,
|
||||
sigmaY: 60.0,
|
||||
),
|
||||
child: Container(
|
||||
color: bgAppBar.withOpacity(0.5),
|
||||
height: screenHeight - 50,
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
child: Container(
|
||||
width: 60,
|
||||
height: 5,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF3A3A3A).withOpacity(0.6),
|
||||
borderRadius: BorderRadius.circular(20))),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(bottom: 10, left: 20, right: 20),
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: _textEditingController,
|
||||
keyboardAppearance: Brightness.dark,
|
||||
onEditingComplete: resetFullScreen,
|
||||
onChanged: (value) async {
|
||||
if (_textEditingController.text.isEmpty) {
|
||||
} else if (value == " ") {
|
||||
print("popular");
|
||||
} else {
|
||||
filteredData = await MyApp.musicViewModel
|
||||
.getMusicsWithName(value);
|
||||
setState(() {
|
||||
filteredData = filteredData;
|
||||
});
|
||||
}
|
||||
},
|
||||
cursorColor: Colors.white,
|
||||
keyboardType: TextInputType.text,
|
||||
style: GoogleFonts.plusJakartaSans(color: grayText),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(
|
||||
Icons.search,
|
||||
color: grayColor,
|
||||
),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(width: 1, color: grayColor),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10))),
|
||||
contentPadding: const EdgeInsets.only(
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: defaultPadding,
|
||||
right: defaultPadding),
|
||||
fillColor: searchBarColor,
|
||||
filled: true,
|
||||
focusColor: grayText,
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(width: 1, color: grayColor),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10))),
|
||||
hintText: 'Chercher un son',
|
||||
hintStyle:
|
||||
GoogleFonts.plusJakartaSans(color: grayColor)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: ScrollConfiguration(
|
||||
behavior: ScrollBehavior().copyWith(scrollbars: true),
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: filteredData.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: MusicListComponent(music: filteredData[index]),
|
||||
);
|
||||
}),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
enum JustMusicIcon {
|
||||
profile,
|
||||
spotify,
|
||||
trash,
|
||||
cross,
|
||||
history,
|
||||
theme,
|
||||
notification
|
||||
}
|
||||
|
||||
extension MyIconExtension on JustMusicIcon {
|
||||
String get imagePath {
|
||||
switch (this) {
|
||||
case JustMusicIcon.profile:
|
||||
return 'assets/images/profile_icon.png';
|
||||
case JustMusicIcon.spotify:
|
||||
return 'assets/images/spotify_icon.png';
|
||||
case JustMusicIcon.trash:
|
||||
return 'assets/images/trash_icon.png';
|
||||
case JustMusicIcon.cross:
|
||||
return 'assets/images/cross_icon.png';
|
||||
case JustMusicIcon.history:
|
||||
return 'assets/images/history_icon.png';
|
||||
case JustMusicIcon.theme:
|
||||
return 'assets/images/theme_icon.png';
|
||||
case JustMusicIcon.notification:
|
||||
return 'assets/images/notification_icon.png';
|
||||
|
||||
default:
|
||||
throw 'assets/images/unknown.png';
|
||||
}
|
||||
}
|
||||
}
|