Skip to content
This repository has been archived by the owner on May 12, 2024. It is now read-only.

Commit

Permalink
feat: added about page
Browse files Browse the repository at this point in the history
  • Loading branch information
oppahansi committed Dec 27, 2023
1 parent e92c3ac commit d0c2c82
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 47 deletions.
7 changes: 6 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';

// Project Imports
import 'package:fis_app/src/app/themes.dart';
import 'package:fis_app/src/features/about/about_screen.dart';
import 'package:fis_app/src/features/search/presentation/photos/photo_search_screen.dart';
import 'package:fis_app/src/utils/theme_provider.dart';

Expand All @@ -19,12 +20,16 @@ class MyApp extends ConsumerWidget {
final themeMode = ref.watch(themeModeProvider);

return MaterialApp(
initialRoute: SearchScreen.route,
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: lightTheme,
darkTheme: darkTheme,
themeMode: themeMode,
home: const SearchScreen(),
routes: {
SearchScreen.route: (context) => const SearchScreen(),
AboutScreen.route: (context) => const AboutScreen(),
},
);
}
}
193 changes: 193 additions & 0 deletions lib/src/features/about/about_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Flutter Imports
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

// Package Imports
import 'package:url_launcher/url_launcher.dart';

// Project Imports
import 'package:fis_app/src/features/shared/nav_items.dart';
import 'package:fis_app/src/features/shared/theme_toggle.dart';
import 'package:fis_app/src/utils/ui_helpers.dart';

class AboutScreen extends StatelessWidget {
const AboutScreen({super.key});

static const String route = '/about';

static const pageSize = 30;

@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const NavItems(),
actions: const [
ThemeToggle(),
],
),
body: Center(
child: SizedBox(
width: halfScreenWidth(context),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
verticalSpaceMedium,
_aboutContent(context),
],
),
),
),
),
);
}

RichText _aboutContent(BuildContext context) {
return RichText(
text: TextSpan(
text: "About\n\n",
style: Theme.of(context).textTheme.titleLarge,
children: [
TextSpan(
text: "Welcome to Free Image Search, your ultimate destination for "
"simplified access to a diverse array of license-free photos!"
"\n\nWe've harnessed the power of leading image repositories, ",
style: Theme.of(context).textTheme.bodyLarge,
children: [
_linkTextSpan(context, "Pexels", "https://www.pexels.com/"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Unsplash",
"https://www.unsplash.com/?utm_source=free_image_search&utm_medium=referral"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Pixabay", "https://www.pixabay.com/"),
const TextSpan(
text: ", to bring you a streamlined search experience "
"without the need to navigate multiple sites.",
),
TextSpan(
text: "\n\nKey Features\n\n",
style: Theme.of(context).textTheme.titleLarge,
),
TextSpan(
text: "Centralized Search",
style: Theme.of(context).textTheme.titleMedium,
),
TextSpan(
text:
"\nSave time and effort by searching for license-free photos "
"across ",
style: Theme.of(context).textTheme.bodyLarge,
children: [
_linkTextSpan(context, "Pexels", "https://www.pexels.com/"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Unsplash",
"https://www.unsplash.com/?utm_source=free_image_search&utm_medium=referral"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Pixabay", "https://www.pixabay.com/"),
const TextSpan(
text: " simultaneously. Our "
"platform combines the results, shuffling them at the end to"
" ensure an unbiased selection. Explore a vast collection of "
"images in one convenient place."),
],
),
TextSpan(
text: "\n\nShuffeled Results",
style: Theme.of(context).textTheme.titleMedium,
),
TextSpan(
text:
"\nWe believe in fairness. To avoid any bias, the search results"
" are shuffled, providing an unbiased and varied selection of "
"images for your creative projects.",
style: Theme.of(context).textTheme.bodyLarge,
),
TextSpan(
text: "\n\nSeamless Redirect",
style: Theme.of(context).textTheme.titleMedium,
),
TextSpan(
text:
"\nDiscover the perfect images effortlessly. While we don't "
"provide direct download links, we seamlessly redirect you to"
" the respective websites (",
style: Theme.of(context).textTheme.bodyLarge,
children: [
_linkTextSpan(context, "Pexels", "https://www.pexels.com/"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Unsplash",
"https://www.unsplash.com/?utm_source=free_image_search&utm_medium=referral"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Pixabay", "https://www.pixabay.com/"),
TextSpan(
text:
") where you can easily access and download the images you desire.",
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
TextSpan(
text: "\n\nLicense Information",
style: Theme.of(context).textTheme.titleMedium,
),
TextSpan(
text: "\nEnsuring transparency, we redirect you to the "
"respective API licenses of ",
style: Theme.of(context).textTheme.bodyLarge,
children: [
_linkTextSpan(context, "Pexels License",
"https://www.pexels.com/license/"),
const TextSpan(
text: ", ",
),
_linkTextSpan(context, "Unsplash License",
"https://www.unsplash.com/license/?utm_source=free_image_search&utm_medium=referral"),
const TextSpan(
text: ", and ",
),
_linkTextSpan(context, "Pixabay License",
"https://www.pixabay.com/service/license-summary/"),
TextSpan(
text: ". You can review the licensing details "
"directly from the source, giving you confidence "
"in using the images for your personal and commercial projects.",
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
],
),
],
),
);
}

TextSpan _linkTextSpan(BuildContext context, String text, String url) {
return TextSpan(
text: text,
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () {
launchUrl(Uri.parse(url));
},
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import 'package:fis_app/src/utils/ui_helpers.dart';
class SearchScreen extends ConsumerWidget {
const SearchScreen({super.key});

static const String route = '/';

static const pageSize = 30;

@override
Expand Down Expand Up @@ -48,48 +50,49 @@ class SearchScreen extends ConsumerWidget {
verticalSpaceMedium,
const PhotoSearchBar(),
verticalSpaceMedium,
query.isNotEmpty
? Expanded(
child: MasonryGridView.count(
crossAxisCount: 3,
mainAxisSpacing: 5,
crossAxisSpacing: 5,
itemBuilder: (context, index) {
final page = index ~/ pageSize + 1;
final indexInPage = index % pageSize;
query.isNotEmpty ? _photoGrid(ref, query) : Container()
],
),
);
}

final moviesList = ref.watch(
fetchPhotosProvider(
pagination:
PhotosPagination(page: page, query: query),
),
);
Expanded _photoGrid(WidgetRef ref, String query) {
return Expanded(
child: MasonryGridView.count(
crossAxisCount: 3,
mainAxisSpacing: 5,
crossAxisSpacing: 5,
itemBuilder: (context, index) {
final page = index ~/ pageSize + 1;
final indexInPage = index % pageSize;

return moviesList.when(
error: (err, stack) => Text('Error $err $stack'),
loading: () => const PhotoTileShimmer(),
data: (searchResults) {
if (indexInPage >= searchResults.photos!.length) {
return const PhotoTileShimmer();
}
final moviesList = ref.watch(
fetchPhotosProvider(
pagination: PhotosPagination(page: page, query: query),
),
);

final photo = searchResults.photos![indexInPage];
return moviesList.when(
error: (err, stack) => Text('Error $err $stack'),
loading: () => const PhotoTileShimmer(),
data: (searchResults) {
if (indexInPage >= searchResults.photos!.length) {
return const PhotoTileShimmer();
}

return PhotoListTile(
photo: photo,
searchSource: _sourceToSearchSource(
photo,
searchResults.sourceSearches,
)!,
debugIndex: index,
);
},
);
},
),
)
: Container()
],
final photo = searchResults.photos![indexInPage];

return PhotoListTile(
photo: photo,
searchSource: _sourceToSearchSource(
photo,
searchResults.sourceSearches,
)!,
debugIndex: index,
);
},
);
},
),
);
}
Expand Down
20 changes: 12 additions & 8 deletions lib/src/features/shared/nav_items.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Flutter Imports
import 'package:flutter/material.dart';

// Project Imports
import 'package:fis_app/src/features/about/about_screen.dart';
import 'package:fis_app/src/features/search/presentation/photos/photo_search_screen.dart';

class NavItems extends StatelessWidget {
const NavItems({
super.key,
Expand All @@ -18,23 +22,23 @@ class NavItems extends StatelessWidget {
),
const Spacer(),
TextButton(
onPressed: () {},
onPressed:
ModalRoute.of(context)?.settings.name != SearchScreen.route
? () => Navigator.pop(context)
: null,
child: const Text(
'Home',
),
),
TextButton(
onPressed: () {},
onPressed:
ModalRoute.of(context)?.settings.name != AboutScreen.route
? () => Navigator.pushNamed(context, AboutScreen.route)
: null,
child: const Text(
'About',
),
),
TextButton(
onPressed: () {},
child: const Text(
'Contact',
),
),
],
),
);
Expand Down

0 comments on commit d0c2c82

Please sign in to comment.