Skip to content

Commit

Permalink
feat: top to article button (#998)
Browse files Browse the repository at this point in the history
* feat: top to article button

* fix: set button to bottom right

* feat: isolate back to top button
  • Loading branch information
Sembauke authored Jun 20, 2023
1 parent 3f3c71c commit 9a3a51f
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 5 deletions.
20 changes: 16 additions & 4 deletions mobile-app/lib/ui/views/news/news-bookmark/news_bookmark_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:freecodecamp/models/news/bookmarked_tutorial_model.dart';
import 'package:freecodecamp/ui/views/news/news-tutorial/news_tutorial_viewmodel.dart';
import 'package:freecodecamp/ui/views/news/news-bookmark/news_bookmark_viewmodel.dart';
import 'package:freecodecamp/ui/views/news/widgets/back_to_top_button.dart';
import 'package:stacked/stacked.dart';

class NewsBookmarkTutorialView extends StatelessWidget {
Expand All @@ -19,12 +20,14 @@ class NewsBookmarkTutorialView extends StatelessWidget {
onViewModelReady: (model) async {
await model.initDB();
model.isTutorialBookmarked(tutorial);
model.goToTopButtonHandler();
},
onDispose: (model) => model.updateListView(),
builder: (context, model, child) => Scaffold(
backgroundColor: const Color(0xFF0a0a23),
body: SafeArea(
child: CustomScrollView(
controller: model.scrollController,
slivers: [
const SliverAppBar(
title: Text('BOOKMARKED TUTORIAL'),
Expand Down Expand Up @@ -61,13 +64,22 @@ class NewsBookmarkTutorialView extends StatelessWidget {
],
),
),
floatingActionButton: model.gotoTopButtonVisible
? BackToTopButton(
onPressed: () => model.goToTop(),
)
: null,
floatingActionButtonAnimator: null,
),
);
}

SliverList lazyLoadHtml(BuildContext context, BookmarkedTutorial tutorial) {
NewsTutorialViewModel model = NewsTutorialViewModel();
var htmlToList = model.initLazyLoading(
SliverList lazyLoadHtml(
BuildContext context,
BookmarkedTutorial tutorial,
) {
NewsTutorialViewModel localModel = NewsTutorialViewModel();
var htmlToList = localModel.initLazyLoading(
tutorial.tutorialText,
context,
tutorial,
Expand All @@ -79,7 +91,7 @@ class NewsBookmarkTutorialView extends StatelessWidget {
children: [
Expanded(
child: htmlToList[index],
)
),
],
);
}), childCount: htmlToList.length),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:freecodecamp/app/app.locator.dart';
import 'package:freecodecamp/app/app.router.dart';
import 'package:freecodecamp/models/news/bookmarked_tutorial_model.dart';
Expand All @@ -9,6 +10,9 @@ class NewsBookmarkViewModel extends BaseViewModel {
bool _isBookmarked = false;
bool get bookmarked => _isBookmarked;

bool _gotoTopButtonVisible = false;
bool get gotoTopButtonVisible => _gotoTopButtonVisible;

bool _userHasBookmarkedTutorials = false;
bool get userHasBookmarkedTutorials => _userHasBookmarkedTutorials;

Expand All @@ -21,6 +25,8 @@ class NewsBookmarkViewModel extends BaseViewModel {
final _navigationService = locator<NavigationService>();
final _databaseService = locator<BookmarksDatabaseService>();

ScrollController scrollController = ScrollController();

Future<void> initDB() async {
await _databaseService.initialise();
}
Expand Down Expand Up @@ -48,6 +54,30 @@ class NewsBookmarkViewModel extends BaseViewModel {
await hasBookmarkedTutorials();
}

Future goToTop() async {
await scrollController.animateTo(
0,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}

Future<void> goToTopButtonHandler() async {
scrollController.addListener(() {
if (scrollController.offset >= 100) {
if (!_gotoTopButtonVisible) {
_gotoTopButtonVisible = true;
notifyListeners();
}
} else {
if (_gotoTopButtonVisible) {
_gotoTopButtonVisible = false;
notifyListeners();
}
}
});
}

Future<void> insertTutorial(dynamic tutorial) async {
bool isInDatabase = await _databaseService.isBookmarked(tutorial);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';

import 'package:freecodecamp/models/news/tutorial_model.dart';
import 'package:freecodecamp/ui/views/news/news-bookmark/news_bookmark_widget.dart';
import 'package:freecodecamp/ui/views/news/widgets/back_to_top_button.dart';
import 'package:share_plus/share_plus.dart';
import 'package:stacked/stacked.dart';
import 'news_tutorial_viewmodel.dart';
Expand Down Expand Up @@ -89,7 +90,7 @@ class NewsTutorialView extends StatelessWidget {
child: Stack(
children: [
lazyLoadHtml(tutorial!.text!, context, tutorial, model),
bottomButtons(tutorial, model)
bottomButtons(tutorial, model),
],
),
)
Expand All @@ -104,6 +105,11 @@ class NewsTutorialView extends StatelessWidget {
);
},
),
floatingActionButton: model.showToTopButton
? BackToTopButton(
onPressed: () => model.goToTop(),
)
: null,
),
viewModelBuilder: () => NewsTutorialViewModel(),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ class NewsTutorialViewModel extends BaseViewModel {
final ScrollController _bottomButtonController = ScrollController();
ScrollController get bottomButtonController => _bottomButtonController;

bool _showToTopButton = false;
bool get showToTopButton => _showToTopButton;

set showToTopButton(bool value) {
_showToTopButton = value;
notifyListeners();
}

Future<Tutorial> readFromFiles() async {
String json = await rootBundle.loadString(
'assets/test_data/news_post.json',
Expand All @@ -41,6 +49,7 @@ class NewsTutorialViewModel extends BaseViewModel {

Future<Tutorial> initState(id) async {
handleBottomButtonAnimation();
handleToTopButton();

if (await _developerService.developmentMode()) {
return readFromFiles();
Expand All @@ -49,6 +58,28 @@ class NewsTutorialViewModel extends BaseViewModel {
}
}

Future<void> handleToTopButton() async {
_scrollController.addListener(() {
if (scrollController.offset >= 100) {
if (!showToTopButton) {
showToTopButton = true;
}
} else {
if (showToTopButton) {
showToTopButton = false;
}
}
});
}

Future<void> goToTop() async {
_scrollController.animateTo(
0,
duration: const Duration(milliseconds: 1000),
curve: Curves.easeInOut,
);
}

Future<void> handleBottomButtonAnimation() async {
_scrollController.addListener(() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Expand Down
33 changes: 33 additions & 0 deletions mobile-app/lib/ui/views/news/widgets/back_to_top_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';

class BackToTopButton extends StatelessWidget {
final VoidCallback onPressed;

const BackToTopButton({Key? key, required this.onPressed}) : super(key: key);

@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 128),
child: FloatingActionButton(
onPressed: onPressed,
shape: RoundedRectangleBorder(
side: const BorderSide(
width: 1,
color: Colors.white,
),
borderRadius: BorderRadius.circular(100),
),
backgroundColor: const Color.fromRGBO(0x2A, 0x2A, 0x40, 1),
child: const Icon(
Icons.keyboard_arrow_up,
size: 40,
color: Colors.white,
),
),
),
);
}
}

0 comments on commit 9a3a51f

Please sign in to comment.