Skip to content

Commit

Permalink
responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
mo7amedaliEbaid committed Dec 15, 2023
1 parent 5fd71a0 commit 29dc4e0
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 318 deletions.
3 changes: 3 additions & 0 deletions lib/core/network/network_values.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ sealed class EndPoints {
static const String trending = "trending/movie/week";
static const String genre = 'genre/movie/list';


static String movie(id) => 'movie/$id';

static String searchMovie(query) => 'search/movie&query=$query';

static String casts(int id) => '/movie/$id/credits';
}

Expand Down
3 changes: 2 additions & 1 deletion lib/core/widgets/app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:movies_riverpod/core/extensions/build_context_extensions.dart';
import 'package:movies_riverpod/core/responsive/responsive.dart';

import 'package:movies_riverpod/features/notifications/presentation/screen/notification_screen.dart';
import 'package:movies_riverpod/features/notifications/presentation/screen/mobile_notification_screen.dart';

import '../../features/notifications/presentation/screen/desktop_notification_screen.dart';
import '../app/app_colors.dart';
import '../app/app_strings.dart';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ abstract class MoviesRemoteDataSource {
Future<Either<AppException, MoviesResponse>> getMovies(
{required String endPoint, required int page});

Future<Either<AppException, MoviesResponse>> getSearchedMovies(
{required String query, required int page});

Future<Either<AppException, GenreResponse>> getGenre();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ interface class MoviesRemoteDataSourceImpl extends MoviesRemoteDataSource {
});
}

@override
Future<Either<AppException, MoviesResponse>> getSearchedMovies(
{required String query, required int page}) async {
final response = await networkService.get(EndPoints.searchMovie(query), queryParams: {
Parameters.page: page,
});

return response.fold((l) => Left(l), (r) {
final jsonData = r.data;
if (jsonData == null) {
return Left(
AppException(
identifier: EndPoints.searchMovie(query),
statusCode: 0,
message: 'The data is not in the valid format',
which: 'http'),
);
}
final moviesResponse =
MoviesResponse.fromJson(jsonData, jsonData['results'] ?? []);
return Right(moviesResponse);
});
}

@override
Future<Either<AppException, GenreResponse>> getGenre() async {
final response = await networkService.get(EndPoints.genre);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ final trendingMoviesStateNotifier =
AutoDisposeStateNotifierProvider<MovieNotifier, MovieState>(
(ref) => MovieNotifier());

final searchedMoviesStateNotifier =
AutoDisposeStateNotifierProvider<MovieNotifier, MovieState>(
(ref) => MovieNotifier());

final genreStateNotifier =
AutoDisposeStateNotifierProvider<GenreNotifier, GenreState>(
(ref) => GenreNotifier()..getGenres());
33 changes: 33 additions & 0 deletions lib/features/movies/presentation/screens/search_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:movies_riverpod/core/responsive/responsive.dart';
import 'package:movies_riverpod/features/movie_detail/presentation/provider/movie_detail_state_notifier.dart';
import 'package:movies_riverpod/features/movie_detail/presentation/provider/state/movie_detail_state.dart';
import 'package:movies_riverpod/features/movie_detail/presentation/widget/desktop_movie_detail_body.dart';
import 'package:movies_riverpod/features/movie_detail/presentation/widget/mobile_movie_detail_body.dart';
import 'package:movies_riverpod/features/movie_detail/presentation/widget/mobile_movie_detail_header.dart';
import 'package:movies_riverpod/features/movies/presentation/providers/movies_state_notifier_provider.dart';

class SearchScreen extends ConsumerStatefulWidget {
const SearchScreen({super.key});

@override
ConsumerState<ConsumerStatefulWidget> createState() => _SearchScreenState();
}

class _SearchScreenState extends ConsumerState<SearchScreen> {
final TextEditingController _controller = TextEditingController();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TextField(
controller: _controller,
onSubmitted: (value) {},
)
],
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:movies_riverpod/core/extensions/build_context_extensions.dart';

import '../../../../core/app/app_dimensions.dart';
import '../provider/notification_provider.dart';
import '../widget/notification_item.dart';

void desktopNotificationSideSheet(BuildContext context) {
// double height = MediaQuery.sizeOf(context).height;
double width = MediaQuery.sizeOf(context).width;
showGeneralDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.5),
barrierDismissible: true,
barrierLabel: '',
transitionBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(1.0, 0.0);
const end = Offset(0.0, 0.0);
const curve = Curves.easeInOut;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

var offsetAnimation = animation.drive(tween);
return SlideTransition(position: offsetAnimation, child: child);
},
transitionDuration: const Duration(milliseconds: 400),
pageBuilder: (context, animation, secondaryAnimation) {
return Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: width * .25,
child: Material(
child: Consumer(
builder: (context, ref, child) {
Future(() {
ref
.read(notificationStateProvider.notifier)
.getAllNotifications();
});
final notificationsNotifier =
ref.watch(notificationStateProvider);
return ClipRRect(
borderRadius:
BorderRadius.vertical(top: Radius.circular(20.0)),
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Column(
children: [
const SizedBox(height: 8),
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(2),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Notifications',
style: context.textTheme.titleMedium,
),
),
Align(
alignment: Alignment.topRight,
child: InkWell(
onTap: () {
if (notificationsNotifier
.notifications.isNotEmpty) {
ref
.read(
notificationStateProvider.notifier)
.clearNotifications();
}
},
child: Padding(
padding: EdgeInsets.only(
top: AppDimensions.p10,
right: AppDimensions.p12,
bottom: AppDimensions.p12,
left: AppDimensions.p12,
),
child: Text('Clear All',
style: context.textTheme.bodySmall),
),
),
),
],
),
),
notificationsNotifier.notifications.isNotEmpty
? SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return NotificationItem(
notificationModel: notificationsNotifier
.notifications[index],
);
},
childCount:
notificationsNotifier.notifications.length,
),
)
: const SliverFillRemaining(
child: Center(
child: Text('No notification available'),
),
),
],
),
);
},
),
),
),
);
},
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:movies_riverpod/core/extensions/build_context_extensions.dart';
import 'package:movies_riverpod/features/notifications/presentation/provider/notification_provider.dart';
import 'package:movies_riverpod/features/notifications/presentation/widget/notification_item.dart';

import '../../../../core/app/app_dimensions.dart';
import '../../../../core/responsive/responsive.dart';

void mobileNotificationBottomSheet(BuildContext context) {
double height = MediaQuery.sizeOf(context).height;
double width = MediaQuery.sizeOf(context).width;
showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
constraints: Responsive.isDesktop(context)
? BoxConstraints(maxHeight: height * 0.85, maxWidth: width * 0.7)
: const BoxConstraints(),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)),
),
builder: (BuildContext context) {
return Consumer(
builder: (context, ref, child) {
Future(() {
ref.read(notificationStateProvider.notifier).getAllNotifications();
});
final notificationsNotifier = ref.watch(notificationStateProvider);
return ClipRRect(
borderRadius:
const BorderRadius.vertical(top: Radius.circular(20.0)),
child: SizedBox(
height: height * 0.7,
child: CustomScrollView(slivers: [
SliverToBoxAdapter(
child: Column(
children: [
const SizedBox(height: 8),
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(2),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Notifications',
style: context.textTheme.titleMedium,
),
),
Align(
alignment: Alignment.topRight,
child: InkWell(
onTap: () {
if (notificationsNotifier
.notifications.isNotEmpty) {
ref
.read(notificationStateProvider.notifier)
.clearNotifications();
}
},
child: Padding(
padding: EdgeInsets.only(
top: AppDimensions.p10,
right: AppDimensions.p12,
bottom: AppDimensions.p12,
left: AppDimensions.p12),
child: Text('Clear All',
style: context.textTheme.bodySmall),
)),
)
],
),
),
notificationsNotifier.notifications.isNotEmpty
? SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return NotificationItem(
notificationModel:
notificationsNotifier.notifications[index]);
},
childCount:
notificationsNotifier.notifications.length,
))
: const SliverFillRemaining(
child: Center(
child: Text('No notification available'),
),
)
])),
);
},
);
},
);
}

Loading

0 comments on commit 29dc4e0

Please sign in to comment.