mirror of
https://github.com/ErfanRht/MovieLab.git
synced 2025-05-17 14:05:55 +08:00
Adding new features
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
@ -33,7 +34,7 @@ void main() async {
|
||||
Get.put(SearchBarController());
|
||||
Get.put(CacheData());
|
||||
|
||||
runApp(const App());
|
||||
runApp(const ProviderScope(child: App()));
|
||||
}
|
||||
|
||||
class App extends StatelessWidget {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:movielab/models/hive/models/show_preview.dart';
|
||||
import 'package:movielab/models/show_models/show_preview_model.dart';
|
||||
|
||||
@ -43,7 +44,10 @@ HiveShowPreview convertShowPreviewToHive(ShowPreview showPreview) {
|
||||
}
|
||||
|
||||
Future<HiveShowPreview> convertFullShowToHive(
|
||||
FullShow fullShow, String rank) async {
|
||||
{required FullShow fullShow,
|
||||
required String rank,
|
||||
DateTime? date,
|
||||
TimeOfDay? time}) async {
|
||||
String crew = "";
|
||||
await getShowCrew(fullShow: fullShow).then((value) => crew = value);
|
||||
return HiveShowPreview()
|
||||
@ -61,7 +65,9 @@ Future<HiveShowPreview> convertFullShowToHive(
|
||||
..domestic = fullShow.domestic
|
||||
..domesticLifetimeGross = fullShow.domesticLifetimeGross
|
||||
..foreign = fullShow.foreign
|
||||
..foreignLifetimeGross = fullShow.foreignLifetimeGross;
|
||||
..foreignLifetimeGross = fullShow.foreignLifetimeGross
|
||||
..watchDate = date
|
||||
..watchTime = time;
|
||||
}
|
||||
|
||||
Future<String> getShowCrew({required FullShow fullShow}) async {
|
||||
|
@ -14,4 +14,6 @@ class ShowPreviewFields {
|
||||
static const int domestic = 12;
|
||||
static const int foreignLifetimeGross = 13;
|
||||
static const int foreign = 14;
|
||||
static const int watchDate = 15;
|
||||
static const int watchTime = 16;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import '../hive_helper/fields/show_preview_fields.dart';
|
||||
import '../hive_helper/hive_adapters.dart';
|
||||
@ -37,4 +38,8 @@ class HiveShowPreview extends HiveObject {
|
||||
late String foreignLifetimeGross;
|
||||
@HiveField(ShowPreviewFields.foreign)
|
||||
late String foreign;
|
||||
@HiveField(ShowPreviewFields.watchDate)
|
||||
late DateTime? watchDate;
|
||||
@HiveField(ShowPreviewFields.watchTime)
|
||||
late TimeOfDay? watchTime;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Movie or TV show preview model class
|
||||
class ShowPreview {
|
||||
final String id;
|
||||
@ -17,6 +19,8 @@ class ShowPreview {
|
||||
final String domestic;
|
||||
final String foreignLifetimeGross;
|
||||
final String foreign;
|
||||
final DateTime? watchDate;
|
||||
final TimeOfDay? watchTime;
|
||||
|
||||
const ShowPreview({
|
||||
required this.id,
|
||||
@ -34,6 +38,8 @@ class ShowPreview {
|
||||
required this.domestic,
|
||||
required this.foreignLifetimeGross,
|
||||
required this.foreign,
|
||||
this.watchDate,
|
||||
this.watchTime,
|
||||
});
|
||||
|
||||
factory ShowPreview.fromJson(Map<String, dynamic> json) {
|
||||
|
5
lib/modules/capitalizer.dart
Normal file
5
lib/modules/capitalizer.dart
Normal file
@ -0,0 +1,5 @@
|
||||
extension StringExtension on String {
|
||||
String capitalize() {
|
||||
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import '../models/hive/convertor.dart';
|
||||
import '../models/hive/models/show_preview.dart';
|
||||
@ -16,10 +17,16 @@ class PreferencesShareholder {
|
||||
|
||||
// Add an item to a list in the shared preferences
|
||||
Future<bool> addShowToList(
|
||||
{required FullShow fullShow, required String listName}) async {
|
||||
{required FullShow fullShow,
|
||||
required String listName,
|
||||
DateTime? date,
|
||||
TimeOfDay? time}) async {
|
||||
Box<HiveShowPreview> list = Hive.box<HiveShowPreview>(listName);
|
||||
HiveShowPreview hiveShow =
|
||||
await convertFullShowToHive(fullShow, (list.length + 1).toString());
|
||||
HiveShowPreview hiveShow = await convertFullShowToHive(
|
||||
fullShow: fullShow,
|
||||
rank: (list.length + 1).toString(),
|
||||
date: date,
|
||||
time: time);
|
||||
list.put(list.length + 1, hiveShow);
|
||||
if (kDebugMode) {
|
||||
print("The item added to $listName");
|
||||
@ -48,18 +55,22 @@ class PreferencesShareholder {
|
||||
List<String> listNames = ["collection", "watchlist", "history"];
|
||||
Map<String, bool> result = {};
|
||||
for (String listName in listNames) {
|
||||
Box<HiveShowPreview> collection = Hive.box<HiveShowPreview>(listName);
|
||||
for (int i = 0; i < collection.length; i++) {
|
||||
if (collection.getAt(i)?.id == showId) {
|
||||
Box<HiveShowPreview> list = Hive.box<HiveShowPreview>(listName);
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
if (list.getAt(i)?.id == showId) {
|
||||
if (kDebugMode) {
|
||||
print("Item is in $listName");
|
||||
}
|
||||
result[listName] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result[listName] = false;
|
||||
}
|
||||
}
|
||||
if (result[listName] != true) {
|
||||
result[listName] = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,40 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import '../../../../../constants/colors.dart';
|
||||
import '../../../../../models/show_models/full_show_model.dart';
|
||||
import '../../../../../modules/preferences_shareholder.dart';
|
||||
import 'sections/lists_info/lists_info.dart';
|
||||
|
||||
class ShowPageBottonBar extends StatelessWidget {
|
||||
const ShowPageBottonBar({Key? key}) : super(key: key);
|
||||
class ShowPageBottonBar extends StatefulWidget {
|
||||
final FullShow show;
|
||||
final Map<String, bool> isThereInLists;
|
||||
const ShowPageBottonBar(
|
||||
{Key? key, required this.show, required this.isThereInLists})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<ShowPageBottonBar> createState() => _ShowPageBottonBarState();
|
||||
}
|
||||
|
||||
class _ShowPageBottonBarState extends State<ShowPageBottonBar>
|
||||
with TickerProviderStateMixin {
|
||||
final PreferencesShareholder _preferencesShareholder =
|
||||
PreferencesShareholder();
|
||||
late FToast fToast;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fToast = FToast();
|
||||
fToast.init(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (kDebugMode) {
|
||||
print(widget.isThereInLists);
|
||||
}
|
||||
return SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
@ -34,23 +62,12 @@ class ShowPageBottonBar extends StatelessWidget {
|
||||
)),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: kSecondaryColor,
|
||||
transitionAnimationController: AnimationController(
|
||||
duration: const Duration(milliseconds: 235), vsync: this),
|
||||
builder: (context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
height: 235,
|
||||
child: Column(
|
||||
children: [
|
||||
button(context,
|
||||
icon: FontAwesomeIcons.circle,
|
||||
text: 'Mark as watched'),
|
||||
button(context,
|
||||
icon: FontAwesomeIcons.bookmark,
|
||||
text: 'Add to watchlist'),
|
||||
button(context,
|
||||
icon: FontAwesomeIcons.rectangleList,
|
||||
text: 'Add to collection'),
|
||||
],
|
||||
),
|
||||
return ShowPageListsInfo(
|
||||
show: widget.show,
|
||||
isThereInLists: widget.isThereInLists,
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -108,44 +125,4 @@ class ShowPageBottonBar extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget button(BuildContext context,
|
||||
{required String text,
|
||||
required IconData icon,
|
||||
EdgeInsets margin = const EdgeInsets.symmetric(vertical: 7.5)}) {
|
||||
return Container(
|
||||
height: 50,
|
||||
margin: margin,
|
||||
width: MediaQuery.of(context).size.width - 100,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xff2a425f).withOpacity(0.75),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w800),
|
||||
),
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:movielab/modules/capitalizer.dart';
|
||||
import '../../../../../../../constants/colors.dart';
|
||||
import '../../../../../../../models/show_models/full_show_model.dart';
|
||||
import '../../../../../../../modules/preferences_shareholder.dart';
|
||||
import '../../../../../../../widgets/buttons/activeable_button.dart';
|
||||
import '../../../../../../../widgets/toast.dart';
|
||||
import '../../watchtime.dart';
|
||||
|
||||
class ShowPageListsInfo extends StatefulWidget {
|
||||
final FullShow show;
|
||||
final Map<String, bool> isThereInLists;
|
||||
const ShowPageListsInfo(
|
||||
{Key? key, required this.show, required this.isThereInLists})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<ShowPageListsInfo> createState() => _ShowPageListsInfoState();
|
||||
}
|
||||
|
||||
class _ShowPageListsInfoState extends State<ShowPageListsInfo>
|
||||
with TickerProviderStateMixin {
|
||||
final PreferencesShareholder _preferencesShareholder =
|
||||
PreferencesShareholder();
|
||||
late FToast fToast;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fToast = FToast();
|
||||
fToast.init(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
height: 235,
|
||||
child: Column(
|
||||
children: [
|
||||
ActiveableButton(
|
||||
icon: FontAwesomeIcons.circle,
|
||||
activeIcon: FontAwesomeIcons.solidCircle,
|
||||
text: 'Mark as watched',
|
||||
activeText: 'Watched',
|
||||
activeColor: kPrimaryColor,
|
||||
isActive: widget.isThereInLists['history'] ?? false,
|
||||
onTap: () async {
|
||||
if (widget.isThereInLists["history"] == false) {
|
||||
Navigator.pop(context);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(20),
|
||||
)),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: kSecondaryColor,
|
||||
transitionAnimationController: AnimationController(
|
||||
duration: const Duration(milliseconds: 225),
|
||||
vsync: this),
|
||||
builder: (context) {
|
||||
return ShowPageAddWatchDate(
|
||||
show: widget.show,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
handleOnTap(listName: "history");
|
||||
}
|
||||
}),
|
||||
ActiveableButton(
|
||||
icon: FontAwesomeIcons.bookmark,
|
||||
activeIcon: FontAwesomeIcons.solidBookmark,
|
||||
text: 'Add to watchlist',
|
||||
activeText: 'Listed on watchlist',
|
||||
activeColor: kAccentColor,
|
||||
isActive: widget.isThereInLists['watchlist'] ?? false,
|
||||
onTap: () {
|
||||
handleOnTap(listName: "watchlist");
|
||||
}),
|
||||
ActiveableButton(
|
||||
icon: FontAwesomeIcons.rectangleList,
|
||||
activeIcon: FontAwesomeIcons.bookBookmark,
|
||||
text: 'Add to collection',
|
||||
activeText: 'Collected',
|
||||
activeColor: kImdbColor,
|
||||
isActive: widget.isThereInLists['collection'] ?? false,
|
||||
onTap: () {
|
||||
handleOnTap(listName: "collection");
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleOnTap({
|
||||
required String listName,
|
||||
}) async {
|
||||
if (widget.isThereInLists[listName] == false) {
|
||||
_preferencesShareholder.addShowToList(
|
||||
fullShow: widget.show, listName: listName);
|
||||
setState(() {
|
||||
widget.isThereInLists[listName] = true;
|
||||
});
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(context);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
fToast.showToast(
|
||||
child: ToastWidget(
|
||||
mainText: "Saved to ${listName.capitalize()}",
|
||||
buttonText: "See list",
|
||||
buttonColor: kAccentColor,
|
||||
buttonOnTap: () {},
|
||||
),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastDuration: const Duration(seconds: 3),
|
||||
);
|
||||
} else {
|
||||
_preferencesShareholder.deleteFromList(
|
||||
showId: widget.show.id, listName: listName);
|
||||
setState(() {
|
||||
widget.isThereInLists[listName] = false;
|
||||
});
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(context);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
fToast.showToast(
|
||||
child: ToastWidget(
|
||||
mainText: "Ramoved from ${listName.capitalize()}",
|
||||
buttonText: "Undo",
|
||||
buttonColor: kPrimaryColor,
|
||||
buttonOnTap: () {}),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastDuration: const Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:movielab/constants/colors.dart';
|
||||
import 'package:movielab/models/show_models/full_show_model.dart';
|
||||
import 'package:movielab/widgets/buttons/glassmorphism_button.dart';
|
||||
import '../../../../../modules/preferences_shareholder.dart';
|
||||
import '../../../../../widgets/toast.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ShowPageAddWatchTime extends StatefulWidget {
|
||||
class ShowPageAddWatchDate extends ConsumerStatefulWidget {
|
||||
final FullShow show;
|
||||
const ShowPageAddWatchTime({Key? key, required this.show}) : super(key: key);
|
||||
const ShowPageAddWatchDate({Key? key, required this.show}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ShowPageAddWatchTime> createState() => _ShowPageAddWatchTimeState();
|
||||
ShowPageAddWatchDateState createState() => ShowPageAddWatchDateState();
|
||||
}
|
||||
|
||||
class _ShowPageAddWatchTimeState extends State<ShowPageAddWatchTime> {
|
||||
bool isOtherDateSectionOpen = false;
|
||||
bool showDateSelector = false;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
TimeOfDay selectedTime = TimeOfDay.now();
|
||||
List<String> months = [
|
||||
class ShowPageAddWatchDateState extends ConsumerState<ShowPageAddWatchDate> {
|
||||
final PreferencesShareholder _preferencesShareholder =
|
||||
PreferencesShareholder();
|
||||
late bool isOtherDateSectionOpen, showDateSelector;
|
||||
late TimeOfDay selectedTime;
|
||||
late DateTime selectedDate;
|
||||
late List<String> months;
|
||||
late FToast fToast;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isOtherDateSectionOpen = false;
|
||||
showDateSelector = false;
|
||||
|
||||
selectedTime = TimeOfDay.now();
|
||||
selectedDate = DateTime.now();
|
||||
|
||||
months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
@ -34,68 +50,8 @@ class _ShowPageAddWatchTimeState extends State<ShowPageAddWatchTime> {
|
||||
'December'
|
||||
];
|
||||
|
||||
Future<void> _selectDate(BuildContext context) async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
builder: (BuildContext context, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
dialogBackgroundColor: kSecondaryColor,
|
||||
primaryColor: kPrimaryColor,
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: kPrimaryColor,
|
||||
onPrimary: Colors.white,
|
||||
onSurface: Colors.white,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
primary: kPrimaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!);
|
||||
},
|
||||
initialDate: selectedDate,
|
||||
currentDate: DateTime.now(),
|
||||
selectableDayPredicate: (DateTime date) =>
|
||||
date.isAfter(DateTime.now()) ? false : true,
|
||||
firstDate: DateTime(1901),
|
||||
lastDate: DateTime(2101));
|
||||
if (picked != null && picked != selectedDate) {
|
||||
setState(() {
|
||||
selectedDate = picked;
|
||||
print(selectedDate);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _selectTime(BuildContext context) async {
|
||||
final TimeOfDay? timeOfDay = await showTimePicker(
|
||||
context: context,
|
||||
builder: (BuildContext context, child) {
|
||||
return Theme(
|
||||
data: ThemeData.dark().copyWith(
|
||||
primaryColor: kPrimaryColor,
|
||||
timePickerTheme: const TimePickerThemeData(
|
||||
backgroundColor: kSecondaryColor,
|
||||
dialTextColor: Colors.white,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
primary: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!);
|
||||
},
|
||||
initialTime: selectedTime,
|
||||
initialEntryMode: TimePickerEntryMode.dial,
|
||||
);
|
||||
if (timeOfDay != null && timeOfDay != selectedTime) {
|
||||
setState(() {
|
||||
selectedTime = timeOfDay;
|
||||
});
|
||||
}
|
||||
fToast = FToast();
|
||||
fToast.init(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -121,7 +77,9 @@ class _ShowPageAddWatchTimeState extends State<ShowPageAddWatchTime> {
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
markAsWatched(date: DateTime.now(), time: TimeOfDay.now());
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 25, vertical: 10)),
|
||||
@ -145,7 +103,11 @@ class _ShowPageAddWatchTimeState extends State<ShowPageAddWatchTime> {
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
markAsWatched(
|
||||
date: DateTime.parse(widget.show.releaseDate),
|
||||
time: TimeOfDay.fromDateTime(DateTime.parse("00:00")));
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 25, vertical: 10)),
|
||||
@ -332,4 +294,86 @@ class _ShowPageAddWatchTimeState extends State<ShowPageAddWatchTime> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _selectDate(BuildContext context) async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
builder: (BuildContext context, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
dialogBackgroundColor: kSecondaryColor,
|
||||
primaryColor: kPrimaryColor,
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: kPrimaryColor,
|
||||
onPrimary: Colors.white,
|
||||
onSurface: Colors.white,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
primary: kPrimaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!);
|
||||
},
|
||||
initialDate: selectedDate,
|
||||
currentDate: DateTime.now(),
|
||||
selectableDayPredicate: (DateTime date) =>
|
||||
date.isAfter(DateTime.now()) ? false : true,
|
||||
firstDate: DateTime(1901),
|
||||
lastDate: DateTime(2101));
|
||||
if (picked != null && picked != selectedDate) {
|
||||
setState(() {
|
||||
selectedDate = picked;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _selectTime(BuildContext context) async {
|
||||
final TimeOfDay? timeOfDay = await showTimePicker(
|
||||
context: context,
|
||||
builder: (BuildContext context, child) {
|
||||
return Theme(
|
||||
data: ThemeData.dark().copyWith(
|
||||
primaryColor: kPrimaryColor,
|
||||
timePickerTheme: const TimePickerThemeData(
|
||||
backgroundColor: kSecondaryColor,
|
||||
dialTextColor: Colors.white,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
primary: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!);
|
||||
},
|
||||
initialTime: selectedTime,
|
||||
initialEntryMode: TimePickerEntryMode.dial,
|
||||
);
|
||||
if (timeOfDay != null && timeOfDay != selectedTime) {
|
||||
setState(() {
|
||||
selectedTime = timeOfDay;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
markAsWatched({required DateTime date, required TimeOfDay time}) async {
|
||||
_preferencesShareholder.addShowToList(
|
||||
fullShow: widget.show, listName: "history", date: date, time: time);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(context);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
fToast.showToast(
|
||||
child: ToastWidget(
|
||||
mainText: "Saved to History}",
|
||||
buttonText: "See list",
|
||||
buttonColor: kAccentColor,
|
||||
buttonOnTap: () {},
|
||||
),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastDuration: const Duration(seconds: 3),
|
||||
);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import '../../../modules/preferences_shareholder.dart';
|
||||
import 'get_show_info.dart';
|
||||
import 'sections/bottom_bar/bottom_bar.dart';
|
||||
import 'sections/index.dart';
|
||||
import 'sections/watchtime.dart';
|
||||
import 'sections/bottom_bar/watchtime.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ShowPage extends StatefulWidget {
|
||||
@ -90,12 +90,15 @@ class _ShowPageState extends State<ShowPage> with TickerProviderStateMixin {
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
height: _isBottomAppBarVisible ? 60 : 0.0,
|
||||
child: const BottomAppBar(
|
||||
shape: CircularNotchedRectangle(),
|
||||
child: BottomAppBar(
|
||||
shape: const CircularNotchedRectangle(),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
notchMargin: 7.5,
|
||||
color: kSecondaryColor,
|
||||
child: ShowPageBottonBar()),
|
||||
child: ShowPageBottonBar(
|
||||
show: show,
|
||||
isThereInLists: _isThereInLists,
|
||||
)),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
@ -112,7 +115,7 @@ class _ShowPageState extends State<ShowPage> with TickerProviderStateMixin {
|
||||
duration: const Duration(milliseconds: 225),
|
||||
vsync: this),
|
||||
builder: (context) {
|
||||
return ShowPageAddWatchTime(
|
||||
return ShowPageAddWatchDate(
|
||||
show: show,
|
||||
);
|
||||
})
|
||||
|
67
lib/widgets/buttons/activeable_button.dart
Normal file
67
lib/widgets/buttons/activeable_button.dart
Normal file
@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ActiveableButton extends StatelessWidget {
|
||||
final String text;
|
||||
final String? activeText;
|
||||
final IconData icon;
|
||||
final IconData? activeIcon;
|
||||
final VoidCallback onTap;
|
||||
final bool isActive;
|
||||
final Color backgroundColor;
|
||||
final Color? activeColor;
|
||||
final EdgeInsets margin;
|
||||
const ActiveableButton(
|
||||
{Key? key,
|
||||
required this.isActive,
|
||||
required this.text,
|
||||
this.activeText,
|
||||
required this.icon,
|
||||
this.activeIcon,
|
||||
required this.onTap,
|
||||
this.activeColor,
|
||||
this.margin = const EdgeInsets.symmetric(vertical: 7.5),
|
||||
this.backgroundColor = const Color(0xff2a425f)})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
height: 50,
|
||||
margin: margin,
|
||||
width: MediaQuery.of(context).size.width - 100,
|
||||
decoration: BoxDecoration(
|
||||
color: isActive
|
||||
? activeColor?.withOpacity(0.75) ??
|
||||
backgroundColor.withOpacity(0.75)
|
||||
: backgroundColor.withOpacity(0.75),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
duration: const Duration(milliseconds: 150),
|
||||
child: TextButton(
|
||||
onPressed: onTap,
|
||||
style: TextButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25),
|
||||
child: Icon(
|
||||
isActive ? activeIcon ?? icon : icon,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isActive ? activeText ?? text : text,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w800),
|
||||
),
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
50
lib/widgets/toast.dart
Normal file
50
lib/widgets/toast.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class ToastWidget extends StatelessWidget {
|
||||
final String mainText;
|
||||
final String buttonText;
|
||||
final Color buttonColor;
|
||||
final VoidCallback buttonOnTap;
|
||||
const ToastWidget(
|
||||
{Key? key,
|
||||
required this.mainText,
|
||||
required this.buttonText,
|
||||
required this.buttonColor,
|
||||
required this.buttonOnTap})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
margin: EdgeInsets.zero,
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
color: Colors.white.withOpacity(0.95),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
mainText,
|
||||
style: GoogleFonts.ubuntu(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: buttonOnTap,
|
||||
style:
|
||||
TextButton.styleFrom(primary: buttonColor.withOpacity(0.5)),
|
||||
child: Text(
|
||||
buttonText,
|
||||
style: GoogleFonts.ubuntu(
|
||||
fontWeight: FontWeight.w600, color: buttonColor),
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
37
pubspec.lock
37
pubspec.lock
@ -15,6 +15,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
ansicolor:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: ansicolor
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -258,6 +265,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
flutter_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_riverpod
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_slidable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -289,6 +303,13 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
fluttertoast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fluttertoast
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.0.9"
|
||||
font_awesome_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -604,6 +625,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: riverpod
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -770,6 +798,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
state_notifier:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: state_notifier
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.2+1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -912,4 +947,4 @@ packages:
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
dart: ">=2.17.0-206.0.dev <3.0.0"
|
||||
flutter: ">=2.10.0-0"
|
||||
flutter: ">=3.0.0"
|
||||
|
@ -19,6 +19,7 @@ dependencies:
|
||||
font_awesome_flutter: ^10.1.0
|
||||
google_fonts: ^3.0.1
|
||||
ms_undraw: ^3.0.1+1
|
||||
fluttertoast: ^8.0.9
|
||||
flutter_spinkit: ^5.1.0
|
||||
flutter_rating_bar: ^4.0.0
|
||||
google_nav_bar: ^5.0.5
|
||||
@ -35,6 +36,9 @@ dependencies:
|
||||
http: ^0.13.4
|
||||
cached_network_image: ^3.2.0
|
||||
speech_to_text: ^5.6.0
|
||||
flutter_riverpod: ^1.0.4
|
||||
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -43,6 +47,7 @@ dev_dependencies:
|
||||
test: ^1.17.12
|
||||
build_runner: ^2.1.7
|
||||
hive_generator: ^1.1.2
|
||||
ansicolor: ^2.0.1
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
23
res/layout/toast_custom.xml
Normal file
23
res/layout/toast_custom.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginStart="50dp"
|
||||
android:background="@drawable/corner"
|
||||
android:layout_marginEnd="50dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#CC000000"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
tools:text="Toast should be short." />
|
||||
</FrameLayout>
|
Reference in New Issue
Block a user