Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(favorites): Adicionado funcionalidade de favoritar #35

Merged
merged 1 commit into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
PODS:
- Flutter (1.0.0)
- path_provider_ios (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter

DEPENDENCIES:
- Flutter (from `Flutter`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)

EXTERNAL SOURCES:
Flutter:
:path: Flutter
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"

SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de

Expand Down
5 changes: 5 additions & 0 deletions lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:provider/provider.dart';

import 'package:tabnews/src/constants.dart';
import 'package:tabnews/src/providers/content.dart';
import 'package:tabnews/src/providers/favorites.dart';
import 'package:tabnews/src/providers/user.dart';
import 'package:tabnews/src/ui/layouts/tab.dart';

Expand All @@ -21,6 +22,10 @@ class App extends StatelessWidget {
lazy: false,
create: (_) => ContentProvider(),
),
ChangeNotifierProvider(
lazy: false,
create: (_) => FavoritesProvider(),
),
],
child: MaterialApp(
title: 'TabNews',
Expand Down
80 changes: 80 additions & 0 deletions lib/src/providers/favorites.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:tabnews/src/models/content.dart';
import 'package:tabnews/src/preferences.dart';

class FavoritesProvider extends ChangeNotifier {
static final FavoritesProvider _instance = FavoritesProvider._internal();

factory FavoritesProvider() {
return _instance;
}

FavoritesProvider._internal() {
_isLoading = false;
_isCreated = false;
_favorites = [];

_getSavedFavorites();
}

late bool _isLoading;
bool get isLoading => _isLoading;

late bool _isCreated;
bool get isCreated => _isCreated;

late List<Content> _favorites;
List<Content> get favorites => _favorites;

void _loading(bool value) {
_isLoading = value;
notifyListeners();
}

void _getSavedFavorites() async {
String savedFavorties = Preferences.getString('favorites') ?? '';

if (savedFavorties.isNotEmpty) {
List contents = jsonDecode(savedFavorties);
for (var favorite in contents) {
_favorites.add(Content.fromJson(favorite));
}
notifyListeners();
}
}

bool isFavorited(String id) {
bool isFavorite =
_favorites.where((element) => element.id == id).isNotEmpty;

if (isFavorite) {
return true;
}

return false;
}

void toggle(Content content) async {
_loading(true);
Content copyContent = content;

if (_favorites.isNotEmpty) {
if (_favorites.where((element) => element.id == content.id).isNotEmpty) {
_favorites.removeWhere((element) => element.id == content.id);
} else {
copyContent.body = null;
_favorites.add(copyContent);
}
} else {
copyContent.body = null;
_favorites.add(copyContent);
}

Preferences.setString('favorites', jsonEncode(_favorites));

_isLoading = false;
notifyListeners();
}
}
4 changes: 3 additions & 1 deletion lib/src/ui/layouts/page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ class PageLayout extends StatelessWidget {
final Widget body;
final bool isLoading;
final Future<void> Function() onRefresh;
final List<Widget>? actions;

const PageLayout({
super.key,
required this.body,
required this.onRefresh,
this.isLoading = false,
this.actions,
});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const AppTopBar(),
appBar: AppTopBar(actions: actions),
body: RefreshIndicator(
color: context.isDarkMode ? Colors.white : Colors.black,
onRefresh: onRefresh,
Expand Down
18 changes: 18 additions & 0 deletions lib/src/ui/pages/content.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tabnews/src/providers/favorites.dart';
import 'package:timeago/timeago.dart' as timeago;

import 'package:tabnews/src/extensions/dark_mode.dart';
Expand Down Expand Up @@ -53,6 +55,22 @@ class _ContentPageState extends State<ContentPage> {

return PageLayout(
onRefresh: _getContent,
actions: isLoading
? null
: [
Consumer<FavoritesProvider>(
builder: (context, provider, _) => IconButton(
onPressed: () => provider.toggle(
content,
),
icon: Icon(
provider.isFavorited(content.id!)
? Icons.favorite
: Icons.favorite_border,
),
),
),
],
body: isLoading
? const AppProgressIndicator()
: Padding(
Expand Down
26 changes: 23 additions & 3 deletions lib/src/ui/pages/favorites.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tabnews/src/models/content.dart';
import 'package:tabnews/src/providers/favorites.dart';
import 'package:tabnews/src/ui/widgets/item_content.dart';

class FavoritesPage extends StatefulWidget {
const FavoritesPage({super.key});
Expand All @@ -10,8 +14,24 @@ class FavoritesPage extends StatefulWidget {
class _FavoritesPageState extends State<FavoritesPage> {
@override
Widget build(BuildContext context) {
return const Center(
child: Text('Favoritos ainda em construção :3'),
);
return Consumer<FavoritesProvider>(builder: (context, provider, _) {
if (provider.favorites.isEmpty) {
return const Center(
child: Text('Você não possui favoritos!'),
);
} else {
List<Content> favorites = provider.favorites;

return ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: favorites.length,
itemBuilder: (context, index) {
return ItemContent(
content: favorites[index],
);
},
);
}
});
}
}
2 changes: 1 addition & 1 deletion lib/src/ui/pages/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class _HomePageState extends State<HomePage> {
scrollController: widget.scrollController,
builderDelegate: PagedChildBuilderDelegate<Content>(
itemBuilder: (context, item, index) {
return ItemContent(index: index, content: item);
return ItemContent(content: item);
},
firstPageProgressIndicatorBuilder: (_) =>
const AppProgressIndicator(),
Expand Down
1 change: 0 additions & 1 deletion lib/src/ui/pages/my_contents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ class _MyContentsPageState extends State<MyContentsPage> {
builderDelegate: PagedChildBuilderDelegate<Content>(
itemBuilder: (context, item, index) {
return ItemContent(
index: index,
content: item,
);
},
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ui/pages/profile_user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class _ProfileUserPageState extends State<ProfileUserPage> {
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<Content>(
itemBuilder: (context, item, index) {
return ItemContent(index: index, content: item);
return ItemContent(content: item);
},
firstPageProgressIndicatorBuilder: (_) =>
const AppProgressIndicator(),
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ui/pages/recents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class _RecentsPageState extends State<RecentsPage> {
scrollController: widget.scrollController,
builderDelegate: PagedChildBuilderDelegate<Content>(
itemBuilder: (context, item, index) {
return ItemContent(index: index, content: item);
return ItemContent(content: item);
},
firstPageProgressIndicatorBuilder: (_) =>
const AppProgressIndicator(),
Expand Down
30 changes: 6 additions & 24 deletions lib/src/ui/widgets/item_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ import 'package:tabnews/src/extensions/dark_mode.dart';
import 'package:tabnews/src/models/content.dart';

class ItemContent extends StatelessWidget {
final int index;
final Content content;

const ItemContent({
super.key,
required this.index,
required this.content,
});

Expand Down Expand Up @@ -47,28 +45,12 @@ class ItemContent extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'${index + 1}.',
style: const TextStyle().copyWith(
fontSize: 15.0,
fontWeight: FontWeight.w700,
),
),
const SizedBox(width: 10.0),
Flexible(
child: Text(
isComment ? '${content.body}' : '${content.title}',
style: const TextStyle().copyWith(
fontSize: 15.0,
fontWeight: FontWeight.w700,
),
),
),
],
Text(
isComment ? '${content.body}' : '${content.title}',
style: const TextStyle().copyWith(
fontSize: 15.0,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 15.0),
Column(
Expand Down
5 changes: 4 additions & 1 deletion lib/src/ui/widgets/top_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:tabnews/src/constants.dart';

class AppTopBar extends StatelessWidget with PreferredSizeWidget {
const AppTopBar({super.key});
final List<Widget>? actions;

const AppTopBar({super.key, this.actions});

@override
Widget build(BuildContext context) {
Expand All @@ -22,6 +24,7 @@ class AppTopBar extends StatelessWidget with PreferredSizeWidget {
),
elevation: 0,
backgroundColor: AppColors.primaryColor,
actions: actions,
);
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: tabnews
description: A new Flutter project.
description: TabNews App made with Flutter

# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
Expand Down