Fix some bugs

This commit is contained in:
Erfan Rahmati
2022-05-11 20:25:51 +04:30
parent 07c643a4e2
commit fd26deabca
16 changed files with 240 additions and 92 deletions

25
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "movielab",
"request": "launch",
"type": "dart"
},
{
"name": "movielab (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "movielab (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

View File

@ -1,3 +1,9 @@
// ignore_for_file: constant_identifier_names
enum SystemUIOverlayStyle { DARK, LIGHT, RED }
enum ImdbList { TOP_250_MOVIES, TOP_250_TVS, TOP_RATED, MOST_POPULAR, SEARCH }
enum RequestResult {
LOADING,
SUCCESS,
FAILURE_USER_PROBLEM,
FAILURE_SERVER_PROBLEM
}

View File

@ -209,12 +209,14 @@ class SearchResult {
final String title;
final String image;
final String description;
final String resultType;
const SearchResult({
required this.id,
required this.title,
required this.image,
required this.description,
required this.resultType,
});
factory SearchResult.fromJson(Map<String, dynamic> json) {
@ -225,6 +227,7 @@ class SearchResult {
"._V1_UX128_CR0,3,128,176_AL_.jpg", "._V1_Ratio0.6716_AL_.jpg"),
description:
json['description'].replaceAll("(", "").replaceAll(")", "") ?? "",
resultType: json['resultType'] ?? "",
);
}
}

View File

@ -13,13 +13,12 @@ class APIRequester {
static const String apiKey = "k_y9zcdoq3";
// static const String apiKey = "";
// Get recently popular movies from the IMDB API
Future<bool> getPopularMovies() async {
Future<RequestResult> getPopularMovies() async {
final response = await http.get(
Uri.parse('https://imdb-api.com/en/API/MostPopularMovies/$apiKey'));
if (response.statusCode == 200) {
if (jsonDecode(response.body)["errorMessage"] == "Invalid API Key") {
print("Invalid API Key Error");
return false;
if (jsonDecode(response.body)["errorMessage"] != "") {
return RequestResult.FAILURE_SERVER_PROBLEM;
}
var json = jsonDecode(response.body)["items"];
List<ShowPreview> popularMovies = [];
@ -28,21 +27,20 @@ class APIRequester {
}
Get.find<HomeDataController>()
.updatePopularMovies(popularMovies: popularMovies);
return true;
return RequestResult.SUCCESS;
} else {
return false;
return RequestResult.FAILURE_SERVER_PROBLEM;
}
}
// Get recently popular TV shows from the IMDB API
Future<bool> getPopularTVShows() async {
Future<RequestResult> getPopularTVShows() async {
final response = await http
.get(Uri.parse('https://imdb-api.com/en/API/MostPopularTVs/$apiKey'));
if (response.statusCode == 200) {
if (jsonDecode(response.body)["errorMessage"] == "Invalid API Key") {
print("Invalid API Key Error");
return false;
if (jsonDecode(response.body)["errorMessage"] != "") {
return RequestResult.FAILURE_SERVER_PROBLEM;
}
var json = jsonDecode(response.body)["items"];
@ -52,9 +50,9 @@ class APIRequester {
}
Get.find<HomeDataController>()
.updatePopularShows(popularShows: popularShows);
return true;
return RequestResult.SUCCESS;
} else {
return false;
return RequestResult.FAILURE_SERVER_PROBLEM;
}
}
@ -102,7 +100,7 @@ class APIRequester {
Future<bool> search({required expression}) async {
expression ??= Get.find<SearchBarController>().fieldText;
final response = await http.get(
Uri.parse('https://imdb-api.com/en/API/Search/$apiKey/$expression'));
Uri.parse('https://imdb-api.com/en/API/SearchAll/$apiKey/$expression'));
if (response.statusCode == 200) {
var json = jsonDecode(response.body)["results"];

View File

@ -4,7 +4,7 @@ import 'package:movielab/pages/main/bookmarks/bookmarks_controller.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PreferencesShareholder {
// Get all bookmarks from the shared preferences
// Get all bookmarks from the shared preferences
Future<bool> getBookmarks() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final bookmarksString = prefs.getString('bookmarks');
@ -17,7 +17,7 @@ class PreferencesShareholder {
return true;
}
// Delete all bookmarks from the shared preferences
// Delete all bookmarks from the shared preferences
Future<bool> deleteBookmarks() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('bookmarks');
@ -26,7 +26,7 @@ class PreferencesShareholder {
return true;
}
// Add a movie to the bookmarks list in the shared preferences
// Add a movie to the bookmarks list in the shared preferences
Future<bool> addBookmark({required FullShow fullShow}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final bookmarksJson = prefs.getString("bookmarks");
@ -60,7 +60,7 @@ class PreferencesShareholder {
return true;
}
// Delete a movie or tv show from the bookmarks list in the shared preferences
// Delete a movie or tv show from the bookmarks list in the shared preferences
Future<bool> deleteBookmark({FullShow? fullShow, ShowPreview? show}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<ShowPreview> bookmarks = Get.find<BookmarksPageController>().bookmarks;
@ -89,7 +89,7 @@ class PreferencesShareholder {
return true;
}
// Get a bool value that is there any bookmarks in the shared preferences or not
// Get a bool value that is there any bookmarks in the shared preferences or not
Future<bool> isThereInBookmarks({required String showId}) async {
List<ShowPreview> bookmarks = Get.find<BookmarksPageController>().bookmarks;
bool isThere = false;

View File

@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:movielab/constants/colors.dart';
import 'package:ms_undraw/ms_undraw.dart';
class SuggestionsPage extends StatelessWidget {
const SuggestionsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kBackgroundColor,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 100),
Text("There are no suggestions for you right now!",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 15,
fontWeight: FontWeight.w600)),
SizedBox(
height: MediaQuery.of(context).size.width,
child: UnDraw(
color: kGreyColor,
illustration: UnDrawIllustration.no_data,
padding: const EdgeInsets.all(65),
placeholder: const Center(
child: SpinKitThreeBounce(
color: Colors.white,
size: 30,
),
),
),
),
],
),
);
}
}

View File

@ -4,7 +4,7 @@ import 'package:get/get.dart';
import 'package:movielab/constants/colors.dart';
import 'package:movielab/pages/main/bookmarks/bookmarks_page.dart';
import 'package:movielab/pages/main/main_controller.dart';
import 'package:movielab/pages/main/profile/profile_page.dart';
import 'Suggestions/Suggestions.dart';
import 'home/home_page.dart';
import 'package:google_nav_bar/google_nav_bar.dart';
import 'search/search_page.dart';
@ -61,8 +61,8 @@ class MainPage extends StatelessWidget {
text: 'Bookmarks',
),
GButton(
icon: Icons.person_outline_rounded,
text: 'Profile',
icon: Icons.podcasts_rounded,
text: 'Suggestions',
),
],
selectedIndex: _.selectedIndex,
@ -82,5 +82,5 @@ const List<Widget> pages = <Widget>[
HomePage(),
SearchPage(),
BookmarksPage(),
ProfilePage()
SuggestionsPage()
];

View File

@ -1,13 +0,0 @@
import 'package:flutter/material.dart';
import 'package:movielab/constants/colors.dart';
class ProfilePage extends StatelessWidget {
const ProfilePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
backgroundColor: kBackgroundColor,
);
}
}

View File

@ -1,13 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:movielab/constants/colors.dart';
import 'package:movielab/modules/api_requester.dart';
import 'package:movielab/pages/main/search/search_bar/voice_search.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
import '../../../../constants/colors.dart';
import '../../../../modules/api_requester.dart';
import 'voice_search.dart';
import 'search_bar_controller.dart';
class SearchBar extends StatelessWidget {

View File

@ -1,11 +1,12 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:movielab/models/models.dart';
import 'package:movielab/pages/show/show_box/show_box_common.dart';
import 'package:movielab/pages/actor/actor_page/actor_page.dart';
import 'package:movielab/pages/show/show_page/show_page.dart';
import 'package:page_transition/page_transition.dart';
import '../../../models/models.dart';
import '../../../pages/show/show_box/show_box_common.dart';
class SearchShowBox extends StatelessWidget {
SearchResult show;
@ -17,11 +18,19 @@ class SearchShowBox extends StatelessWidget {
String image = show.image;
String description = show.description;
String id = show.id;
String resultType = show.resultType;
return Padding(
padding: const EdgeInsets.only(left: 10, right: 10, top: 5, bottom: 5),
child: InkWell(
onTap: () async {
openShowPage(context, id);
Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
duration: const Duration(milliseconds: 500),
child: resultType == "Name"
? ActorPage(id: id)
: ShowPage(id: id)));
},
borderRadius: BorderRadius.circular(15),
child: Container(
@ -71,13 +80,18 @@ class SearchShowBox extends StatelessWidget {
padding: const EdgeInsets.only(top: 10),
child: Row(
children: [
Text(
description,
softWrap: true,
style: GoogleFonts.ubuntu(
color: Colors.white.withOpacity(0.8),
fontSize: 13.5,
fontWeight: FontWeight.w500),
Flexible(
flex: 2,
child: RichText(
//overflow: TextOverflow.ellipsis,
softWrap: true,
text: TextSpan(
style: GoogleFonts.ubuntu(
color: Colors.white.withOpacity(0.8),
fontSize: 13.5,
fontWeight: FontWeight.w500),
text: description),
),
),
],
),

View File

@ -1,27 +1,25 @@
import 'package:get/get.dart';
import 'package:movielab/constants/types.dart';
import 'package:movielab/pages/main/home/home_data_controller.dart';
import '../../modules/preferences_shareholder.dart';
import '../../modules/api_requester.dart';
Future<bool> getInitialData() async {
bool? error;
Future<RequestResult> getInitialData() async {
final apiRequester = APIRequester();
final preferencesShareholder = PreferencesShareholder();
await apiRequester.getPopularMovies().then((value) => {
if (value = false) {error = true}
});
await apiRequester.getPopularTVShows().then((value) => {
if (value = false) {error = true}
});
await preferencesShareholder.getBookmarks().then((value) => {
if (value = false) {error = true}
});
try {
await apiRequester.getPopularMovies();
await apiRequester.getPopularTVShows();
await preferencesShareholder.getBookmarks();
} catch (e) {
await Future.delayed(const Duration(seconds: 1));
return RequestResult.FAILURE_USER_PROBLEM;
}
if (Get.find<HomeDataController>().popularMovies.isNotEmpty ||
Get.find<HomeDataController>().popularShows.isNotEmpty) {
return true;
return RequestResult.SUCCESS;
}
return false;
return RequestResult.FAILURE_SERVER_PROBLEM;
}

View File

@ -3,7 +3,6 @@ import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:movielab/constants/colors.dart';
import 'package:movielab/constants/routes.dart';
import 'package:movielab/constants/types.dart';
import 'package:movielab/modules/cache/cache_data.dart';
import 'package:movielab/modules/system_ui_overlay_style.dart';
@ -15,18 +14,29 @@ import 'package:movielab/pages/main/search/search_bar/search_bar_controller.dart
import 'package:page_transition/page_transition.dart';
import 'get_initial_data.dart';
class SplashScreen extends StatelessWidget {
class SplashScreen extends StatefulWidget {
const SplashScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
RequestResult _loadingStatus = RequestResult.LOADING;
@override
void initState() {
super.initState();
setSystemUIOverlayStyle(systemUIOverlayStyle: SystemUIOverlayStyle.DARK);
Get.put(MainController());
Get.put(HomeDataController());
Get.put(SearchBarController());
Get.put(CacheData());
Get.put(BookmarksPageController());
getInitialData();
_pass(context);
_loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kBackgroundColor,
body: SafeArea(
@ -54,27 +64,87 @@ class SplashScreen extends StatelessWidget {
const SizedBox(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
SpinKitRipple(
color: Colors.white,
size: 100,
borderWidth: 10,
)
],
children: [_loadErrorSwitch()],
),
],
),
));
}
}
_pass(BuildContext context) {
Future.delayed(const Duration(seconds: 4), () {
Navigator.pushReplacement(
context,
PageTransition(
type: PageTransitionType.fade,
duration: const Duration(milliseconds: 500),
child: const MainPage()));
});
Widget _loadErrorSwitch() {
switch (_loadingStatus) {
case RequestResult.LOADING:
return const Center(
child: SpinKitRipple(
color: Colors.white,
size: 100,
borderWidth: 10,
),
);
default:
return Padding(
padding: const EdgeInsets.only(top: 25, bottom: 25),
child: InkWell(
onTap: () {
setState(() {
_loadingStatus = RequestResult.LOADING;
});
_loadData();
},
borderRadius: BorderRadius.circular(10),
child: Container(
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: kGreyColor.withOpacity(0.2),
),
child: Column(
children: [
Text(
_loadingStatus == RequestResult.FAILURE_SERVER_PROBLEM
? 'An unexpected error occurred while loading data.'
: 'Your internet connection is not working.',
style: GoogleFonts.ubuntu(
color: Colors.white,
fontSize: 12.5,
fontWeight: FontWeight.w600),
),
const SizedBox(height: 5),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(
'Try again',
style: GoogleFonts.ubuntu(
color: Colors.white,
fontSize: 12.5,
fontWeight: FontWeight.w600),
),
const Icon(
Icons.refresh,
color: Colors.white,
size: 15,
)
])
],
),
)),
);
}
}
Future _loadData() async {
getInitialData().then((result) {
if (result == RequestResult.SUCCESS) {
Navigator.pushReplacement(
context,
PageTransition(
type: PageTransitionType.fade,
duration: const Duration(milliseconds: 500),
child: const MainPage()));
} else {
setState(() {
_loadingStatus = result;
});
}
});
}
}

View File

@ -78,6 +78,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
circular_check_box:
dependency: "direct main"
description:
name: circular_check_box
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
cli_util:
dependency: transitive
description:

View File

@ -26,6 +26,7 @@ dependencies:
page_transition: ^2.0.5
flutter_slidable: ^1.2.0
avatar_glow: ^2.0.2
circular_check_box: ^1.0.4
dev_dependencies:
flutter_test:

View File

@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:movielab/constants/types.dart';
import 'package:movielab/pages/main/home/home_data_controller.dart';
import 'package:test/test.dart';
import 'package:movielab/modules/api_requester.dart';
@ -10,7 +11,7 @@ void main() {
var result = await apiRequester.getPopularMovies();
expect(result, isNotNull);
if (result) {
if (result == RequestResult.SUCCESS) {
expect(Get.find<HomeDataController>().popularMovies, isNotEmpty);
}
});
@ -20,7 +21,7 @@ void main() {
var result = await apiRequester.getPopularTVShows();
expect(result, isNotNull);
if (result) {
if (result == RequestResult.SUCCESS) {
expect(Get.find<HomeDataController>().popularShows, isNotEmpty);
}
});

View File

@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:movielab/constants/types.dart';
import 'package:movielab/pages/main/bookmarks/bookmarks_controller.dart';
import 'package:movielab/pages/main/home/home_data_controller.dart';
import 'package:movielab/pages/splash/get_Initial_data.dart';
@ -11,7 +12,7 @@ void main() {
var result = await getInitialData();
expect(result, isNotNull);
if (result) {
if (result == RequestResult.SUCCESS) {
expect(Get.find<HomeDataController>().popularMovies, isNotEmpty);
expect(Get.find<HomeDataController>().popularShows, isNotEmpty);
}