Skip to content

Commit

Permalink
Feat: In Notice Navigation (#37)
Browse files Browse the repository at this point in the history
* Fix IOS BackSwipe

* Add Feat: In Notice Nav

* Fix GH workflow, change snackbar message

* Fix kotlin version in android
  • Loading branch information
pranavkonidena authored Mar 7, 2024
1 parent 1f5b5e4 commit 861dfb0
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.13.0'
flutter-version: '3.19.1'

- run: flutter pub get

Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ jobs:
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.13.0'
flutter-version: '3.19.1'

- run: flutter pub get

- run: flutter analyze .

- run: flutter build apk --release

- uses: actions/upload-artifact@v3
with:
name: NoticeBoard
path: build/app/outputs/apk/release/NoticeBoardApp.apk
2 changes: 1 addition & 1 deletion noticeboard/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.8.21'
ext.kotlin_version = '1.9.23'
repositories {
google()
jcenter()
Expand Down
31 changes: 26 additions & 5 deletions noticeboard/lib/bloc/list_notices_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'package:noticeboard/models/notice_detail_route_arguments.dart';
import 'package:noticeboard/models/paginated_info.dart';
import 'package:noticeboard/repository/list_notices_repository.dart';
import '../global/global_constants.dart';
Expand Down Expand Up @@ -91,7 +92,7 @@ class ListNoticesBloc {

_markReadStream.listen((object) async {
object.read = true;
if(!object.fromDeepLink){
if (!object.fromDeepLink) {
updateUi(object);
}
var obj = {
Expand Down Expand Up @@ -187,11 +188,28 @@ class ListNoticesBloc {
await fetchBookmarkedNotices();
}

void pushNoticeDetail(NoticeIntro noticeIntro) {
void pushNoticeDetail(NoticeIntro noticeIntro,
List<NoticeIntro?>? listOfNotices, ListNoticesBloc listNoticesBloc) {
if (!noticeIntro.read!) markReadSink.add(noticeIntro);
previousRoute = bottomNavigationRoute;
navigatorKey.currentState!
.pushNamed(noticeDetailRoute, arguments: noticeIntro)
.pushNamed(noticeDetailRoute,
arguments: NoticeDetailArgument(
noticeIntro, listOfNotices, listNoticesBloc , false))
.then((value) => updateUi(value as NoticeIntro?));
}

void swipeBetweenNoticeDetail(
NoticeIntro noticeIntro,
List<NoticeIntro?>? listOfNotices,
ListNoticesBloc listNoticesBloc,
bool goingToPrevNotice
) {
if (!noticeIntro.read!) markReadSink.add(noticeIntro);
navigatorKey.currentState!
.pushReplacementNamed(noticeDetailRoute,
arguments: NoticeDetailArgument(
noticeIntro, listOfNotices, listNoticesBloc , goingToPrevNotice))
.then((value) => updateUi(value as NoticeIntro?));
}

Expand Down Expand Up @@ -446,9 +464,12 @@ class ListNoticesBloc {
}

void updateUi(NoticeIntro? object) {
dynamicNoticeList![dynamicNoticeList!
.indexWhere((noticeIntro) => noticeIntro!.id == object!.id)] = object;
if(object != null){
dynamicNoticeList![dynamicNoticeList!
.indexWhere((noticeIntro) => noticeIntro!.id == object.id)] = object;
_listNoticesSink
.add(PaginatedInfo(list: dynamicNoticeList, hasMore: hasMore));
}

}
}
3 changes: 3 additions & 0 deletions noticeboard/lib/global/global_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ final GlobalKey<ScaffoldMessengerState> snackKey =

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
String previousRoute = "";

SnackBar noprevNoticeSnackBar =
const SnackBar(content: Text("You are already on the latest notice!"));
12 changes: 12 additions & 0 deletions noticeboard/lib/models/notice_detail_route_arguments.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:noticeboard/bloc/list_notices_bloc.dart';
import 'package:noticeboard/models/notice_intro.dart';

class NoticeDetailArgument {
NoticeIntro noticeIntro;
List<NoticeIntro?>? listOfNotices;
ListNoticesBloc listNoticesBloc;
bool goingtoPrevNotice = false;

NoticeDetailArgument(
this.noticeIntro, this.listOfNotices, this.listNoticesBloc , this.goingtoPrevNotice);
}
40 changes: 36 additions & 4 deletions noticeboard/lib/routes/routing.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:noticeboard/models/notice_detail_route_arguments.dart';
import 'package:noticeboard/models/notice_intro.dart';
import 'package:noticeboard/screens/bottom_navigation.dart';
import 'package:noticeboard/screens/profile.dart';
Expand Down Expand Up @@ -28,11 +29,42 @@ class MyRouter {
listNoticeMetaData: listNoticeMetaData,
));
case noticeDetailRoute:
NoticeIntro? noticeIntro = settings.arguments as NoticeIntro?;
return MaterialPageRoute(
NoticeDetailArgument noticeDetailArgument =
settings.arguments as NoticeDetailArgument;
if(!noticeDetailArgument.goingtoPrevNotice){
return MaterialPageRoute(
builder: (context) => NoticeDetail(
noticeIntro: noticeIntro,
));
noticeIntro: noticeDetailArgument.noticeIntro,
listOfNotices: noticeDetailArgument.listOfNotices,
listNoticesBloc: noticeDetailArgument.listNoticesBloc,
)
);
}
else{
return PageRouteBuilder(
transitionDuration: Duration(milliseconds: 100),
pageBuilder: (context, animation, secondaryAnimation) => NoticeDetail(
noticeIntro: noticeDetailArgument.noticeIntro,
listOfNotices: noticeDetailArgument.listOfNotices,
listNoticesBloc: noticeDetailArgument.listNoticesBloc,
),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var begin = Offset(-1.0, 0.0); // Start the animation from the left
var end = Offset.zero;
var curve = Curves.ease;

var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

var offsetAnimation = animation.drive(tween);

return SlideTransition(
position: offsetAnimation,
child: child,
);
},
);
}

default:
return MaterialPageRoute(builder: (context) => Launcher());
}
Expand Down
2 changes: 1 addition & 1 deletion noticeboard/lib/screens/list_notices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class _ListNoticesState extends State<ListNotices> {
}

void pushNoticeDetail(NoticeIntro noticeIntro) {
_listNoticesBloc.pushNoticeDetail(noticeIntro);
_listNoticesBloc.pushNoticeDetail(noticeIntro , _listNoticesBloc.dynamicNoticeList , _listNoticesBloc);
}

bool _handleScrollNotification(ScrollNotification scrollInfo) {
Expand Down
81 changes: 73 additions & 8 deletions noticeboard/lib/screens/notice_detail.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:noticeboard/bloc/connectivity_status_bloc.dart';
import 'package:noticeboard/bloc/list_notices_bloc.dart';
import 'package:noticeboard/bloc/notice_detail_bloc.dart';
import 'package:noticeboard/enum/current_widget_enum.dart';
import 'package:noticeboard/enum/notice_content_enum.dart';
Expand All @@ -15,9 +18,15 @@ import '../global/global_functions.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../styles/notice_detail_consts.dart';

// ignore: must_be_immutable
class NoticeDetail extends StatefulWidget {
final NoticeIntro? noticeIntro;
NoticeDetail({required this.noticeIntro});
List<NoticeIntro?>? listOfNotices;
ListNoticesBloc listNoticesBloc;
NoticeDetail(
{required this.noticeIntro,
required this.listOfNotices,
required this.listNoticesBloc});

@override
_NoticeDetailState createState() => _NoticeDetailState();
Expand All @@ -33,7 +42,10 @@ class _NoticeDetailState extends State<NoticeDetail> {
WebViewController _webViewController = WebViewController();
NoticeDetailBloc _noticeDetailBloc = NoticeDetailBloc();
bool pdfAlreadyOpened = false;
bool snackBarShown = false;
bool isGestureZoom = false;
late Timer _timer;
int currentIndex = 0;

@override
void initState() {
Expand All @@ -50,6 +62,18 @@ class _NoticeDetailState extends State<NoticeDetail> {
_webViewController.reload();
}
});
for (int i = 0; i < widget.listOfNotices!.length; i++) {
if (widget.listOfNotices?[i]?.id == widget.noticeIntro?.id) {
currentIndex = i;
}
}
if (currentIndex == widget.listOfNotices!.length - 1) {
widget.listNoticesBloc.loadMore().whenComplete(() {
setState(() {
widget.listOfNotices = widget.listNoticesBloc.dynamicNoticeList;
});
});
}
super.initState();
}

Expand Down Expand Up @@ -92,10 +116,20 @@ class _NoticeDetailState extends State<NoticeDetail> {
),
body: SizedBox.expand(
child: GestureDetector(
onPanUpdate: (details) {
// Can swipe anywhere and detects left swipe
if (details.delta.dx < 0 && Platform.isIOS) {
debugPrint("Left swipe occoured!");
onScaleUpdate: (details) async {
isGestureZoom = true;
await _webViewController.enableZoom(true);
return;
// Your zoom logic here
},
onScaleEnd: (details) {
isGestureZoom = false;
},
onHorizontalDragStart: (details) {
if (isGestureZoom) {
return;
}
if (details.localPosition.dx < 75.0 && Platform.isIOS) {
if (previousRoute == launchingRoute) {
navigatorKey.currentState!
.pushReplacementNamed(bottomNavigationRoute);
Expand All @@ -104,6 +138,34 @@ class _NoticeDetailState extends State<NoticeDetail> {
}
}
},
onHorizontalDragUpdate: (details) {
if (isGestureZoom) {
return;
}
if (details.delta.dx > 10) {
// Forward swipe. Have to show previous notice
if (currentIndex > 0)
widget.listNoticesBloc.swipeBetweenNoticeDetail(
widget.listOfNotices![currentIndex - 1]!,
widget.listOfNotices,
widget.listNoticesBloc,
true);
else {
if (!snackBarShown) {
ScaffoldMessenger.of(context)
.showSnackBar(noprevNoticeSnackBar);
snackBarShown = true;
}
}
} else if (details.delta.dx < -10) {
// Backward Swipe. Have to show next notice
widget.listNoticesBloc.swipeBetweenNoticeDetail(
widget.listOfNotices![currentIndex + 1]!,
widget.listOfNotices,
widget.listNoticesBloc,
false);
}
},
child: PopScope(
canPop: false,
onPopInvoked: (didPop) async {
Expand Down Expand Up @@ -161,7 +223,6 @@ class _NoticeDetailState extends State<NoticeDetail> {
encoding: Encoding.getByName('utf-8'),
);
_webViewController
..enableZoom(true)
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(onNavigationRequest: (navigation) async {
Expand All @@ -183,10 +244,14 @@ class _NoticeDetailState extends State<NoticeDetail> {
}
return NavigationDecision.navigate;
}))
..loadRequest(uri);
..loadRequest(uri).then((value) async {
await _webViewController.enableZoom(true);
});
return Container(
padding: EdgeInsets.all(10.0),
child: WebViewWidget(controller: _webViewController));
child: WebViewWidget(controller: _webViewController , gestureRecognizers: Set()
..add(Factory<PanGestureRecognizer>(() => PanGestureRecognizer()))
..add(Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer())),));
}

Container buildNoticeIntro(double _width) {
Expand Down

0 comments on commit 861dfb0

Please sign in to comment.