diff --git a/lib/services/navigation_service.dart b/lib/services/navigation_service.dart index 739760398..cc177b8d0 100644 --- a/lib/services/navigation_service.dart +++ b/lib/services/navigation_service.dart @@ -1,6 +1,3 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; import 'package:talawa/enums/enums.dart'; import 'package:talawa/widgets/talawa_error_dialog.dart'; @@ -21,11 +18,14 @@ import 'package:talawa/widgets/talawa_error_snackbar.dart'; class NavigationService { GlobalKey navigatorKey = GlobalKey(); - /// This function push the route to the navigator. + /// Pushes a Screen. + /// + /// **params**: + /// * `routeName`: Name of the Route + /// * `arguments`: Set of arguments /// - /// params: - /// * [routeName] - /// * [arguments] : necessary data for the route + /// **returns**: + /// * `Future`: resolves if the Screen was succesfully pushed. Future pushScreen(String routeName, {dynamic arguments}) { return navigatorKey.currentState! .pushNamed(routeName, arguments: arguments); @@ -33,9 +33,12 @@ class NavigationService { /// This function pop the initial route and push the new route to the navigator. /// - /// params: - /// * [routeName] - /// * [arguments] : necessary data for the route + /// **params**: + /// * `routeName`: Name of the Route + /// * `arguments`: Set of arguments + /// + /// **returns**: + /// * `Future`: resolves if the Screen was succesfully popAndPushed. Future popAndPushScreen(String routeName, {dynamic arguments}) { navigatorKey.currentState!.pop(); return pushScreen(routeName, arguments: arguments); @@ -43,28 +46,34 @@ class NavigationService { /// This function push the route and replace the screen. /// - /// params: - /// * [routeName] - /// * [arguments] : necessary data for the route + /// **params**: + /// * `routeName`: Name of the Route + /// * `arguments`: Set of arguments + /// + /// **returns**: + /// * `Future`: resolves if the Screen was succesfully pushedReplacementScreen. Future pushReplacementScreen(String routeName, {dynamic arguments}) { return navigatorKey.currentState! .pushReplacementNamed(routeName, arguments: arguments); } - void fromInviteLink(List routeNames, List arguments) { - int i = 0; - removeAllAndPush('/${routeNames[i]}', '/', arguments: arguments[i]); - for (i = 1; i < routeNames.length; i++) { - pushScreen('/${routeNames[i]}', arguments: arguments[i]); - } - } + // void fromInviteLink(List routeNames, List arguments) { + // int i = 0; + // removeAllAndPush('/${routeNames[i]}', '/', arguments: arguments[i]); + // for (i = 1; i < routeNames.length; i++) { + // pushScreen('/${routeNames[i]}', arguments: arguments[i]); + // } + // } /// This function remove all the routes till the particular route and add new route. /// - /// params: - /// * [routeName] : route that need to add - /// * [tillRoute] : remove all route until this route. - /// * [arguments] : necessary data for the route + /// **params**: + /// * `routeName`: Name of the Route + /// * `tillRoute`: Route till we want to remove + /// * `arguments`: Set of arguments + /// + /// **returns**: + /// * `Future`: resolves if the Screen was succesfully removeAllAndPushed. Future removeAllAndPush( String routeName, String tillRoute, { @@ -77,7 +86,13 @@ class NavigationService { ); } - /// This function is used to show the custom Dialog. + /// This function remove all the routes till the particular route and add new route. + /// + /// **params**: + /// * `dialog`: Widget to show + /// + /// **returns**: + /// None void pushDialog(Widget dialog) { showDialog( context: navigatorKey.currentContext!, diff --git a/lib/splash_screen.dart b/lib/splash_screen.dart index 0bdbc85f9..88d82dae1 100644 --- a/lib/splash_screen.dart +++ b/lib/splash_screen.dart @@ -1,27 +1,21 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:talawa/constants/routing_constants.dart'; import 'package:talawa/custom_painters/talawa_logo.dart'; -import 'package:talawa/enums/enums.dart'; import 'package:talawa/locator.dart'; -import 'package:talawa/models/events/event_model.dart'; import 'package:talawa/models/mainscreen_navigation_args.dart'; -import 'package:talawa/services/graphql_config.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/utils/app_localization.dart'; -import 'package:talawa/view_model/after_auth_view_models/event_view_models/explore_events_view_model.dart'; import 'package:uni_links/uni_links.dart'; -/// This widget return the SplashScreen. Splash Screen is the first screen that -/// we see when we run our application. It is also known as Launch Screen. +/// This widget return the SplashScreen. Splash Screen is the first screen that we see when we run our application. It is also known as Launch Screen. class SplashScreen extends StatefulWidget { const SplashScreen({required Key key, this.mainScreenIndex = 0}) : super(key: key); + + /// This is required if url requires us to push different Screen to Home Screen. final int mainScreenIndex; @override @@ -34,10 +28,18 @@ class _SplashScreenState extends State { Uri? _latestUri; late StreamSubscription _sub; - /// Flutter supports deep linking on iOS, Android, and web browsers. - /// Opening a URL displays that screen in your app. - /// `_handleInitialUri` is an async function that is used to hanlde - /// the initial uri of the application. + // / Flutter supports deep linking on iOS, Android, and web browsers. + // / Opening a URL displays that screen in your app. + // / `_handleInitialUri` is an async function that is used to hanlde + // / the initial uri of the application. + + /// Opening a URL displays that screen in your app, `_handleInitialUri` is an async function that is used to handle the initial uri of the application. + /// + /// **params**: + /// None + /// + /// **returns**: + /// * `Future`: resolves when the check for userLoggedin is complete or not Future _handleInitialUri() async { _sub = uriLinkStream.listen( (Uri? uri) { @@ -70,127 +72,136 @@ class _SplashScreenState extends State { } final bool userLoggedIn = await userConfig.userLoggedIn(); + _initialUri = null; + _latestUri = null; if (_latestUri == null && _initialUri == null) { _handleUserLogIn(userLoggedIn); return; } - if (_initialUri != null) { - await _handleDeepLinks(userLoggedIn); - } + // if (_initialUri != null) { + // await _handleDeepLinks(userLoggedIn); + // } } - Future _handleDeepLinks(bool userLoggedIn) async { - final keys = _initialUri!.queryParameters.keys; - final values = _initialUri!.queryParameters.values; + // Future _handleDeepLinks(bool userLoggedIn) async { + // final keys = _initialUri!.queryParameters.keys; + // final values = _initialUri!.queryParameters.values; - final fromInviteLink = navigationService.fromInviteLink; - final showSnackBar = navigationService.showTalawaErrorSnackBar; - final pushReplacementScreen = navigationService.pushReplacementScreen; + // final fromInviteLink = navigationService.fromInviteLink; + // final showSnackBar = navigationService.showTalawaErrorSnackBar; + // final pushReplacementScreen = navigationService.pushReplacementScreen; - final orgURI = GraphqlConfig.orgURI!; - final mainScreenArgs = - MainScreenArgs(mainScreenIndex: widget.mainScreenIndex); + // final orgURI = GraphqlConfig.orgURI!; + // final mainScreenArgs = + // MainScreenArgs(mainScreenIndex: widget.mainScreenIndex); - if (_initialUri!.pathSegments[1] == 'invite') { - if (!userLoggedIn) { - fromInviteLink( - keys.toList(growable: false), - values.toList(growable: false), - ); - return; - } + // if (_initialUri!.pathSegments[1] == 'invite') { + // if (!userLoggedIn) { + // fromInviteLink( + // keys.toList(growable: false), + // values.toList(growable: false), + // ); + // return; + // } - final setUrl = values.toList(growable: false)[1]; - if (setUrl.compareTo(orgURI) != 0) { - showSnackBar( - 'Organisation on different server! Logout and open link again', - MessageType.error, - ); - return; - } + // final setUrl = values.toList(growable: false)[1]; + // if (setUrl.compareTo(orgURI) != 0) { + // showSnackBar( + // 'Organisation on different server! Logout and open link again', + // MessageType.error, + // ); + // return; + // } - if (keys.last.compareTo('selectOrg') != 0) { - showSnackBar('Invalid url', MessageType.error); - return; - } + // if (keys.last.compareTo('selectOrg') != 0) { + // showSnackBar('Invalid url', MessageType.error); + // return; + // } - final routeNames = [ - Routes.mainScreen.split('/').last, - Routes.joinOrg.split('/').last, - ]; - final arguments = [ - mainScreenArgs, - values.last, - ]; - fromInviteLink(routeNames, arguments); - return; - } - if (_initialUri!.pathSegments[1] == 'eventInvite') { - if (!userLoggedIn) { - pushReplacementScreen( - Routes.languageSelectionRoute, - arguments: 'en', - ); - return; - } + // final routeNames = [ + // Routes.mainScreen.split('/').last, + // Routes.joinOrg.split('/').last, + // ]; + // final arguments = [ + // mainScreenArgs, + // values.last, + // ]; + // fromInviteLink(routeNames, arguments); + // return; + // } + // if (_initialUri!.pathSegments[1] == 'eventInvite') { + // if (!userLoggedIn) { + // pushReplacementScreen( + // Routes.languageSelectionRoute, + // arguments: 'en', + // ); + // return; + // } - final setUrl = values.toList(growable: false)[0]; - if (setUrl.compareTo(orgURI) != 0) { - Clipboard.setData(ClipboardData(text: setUrl)); - showSnackBar( - 'Organisation on different server! Url copied to clipboard.', - MessageType.error, - ); - pushReplacementScreen( - Routes.mainScreen, - arguments: mainScreenArgs, - ); - return; - } + // final setUrl = values.toList(growable: false)[0]; + // if (setUrl.compareTo(orgURI) != 0) { + // Clipboard.setData(ClipboardData(text: setUrl)); + // showSnackBar( + // 'Organisation on different server! Url copied to clipboard.', + // MessageType.error, + // ); + // pushReplacementScreen( + // Routes.mainScreen, + // arguments: mainScreenArgs, + // ); + // return; + // } - final currentOrgId = userConfig.currentOrg.id!; - if (values.toList()[1].compareTo(currentOrgId) != 0) { - pushReplacementScreen(Routes.joinOrg, arguments: values.toList()[1]); - return; - } + // final currentOrgId = userConfig.currentOrg.id!; + // if (values.toList()[1].compareTo(currentOrgId) != 0) { + // pushReplacementScreen(Routes.joinOrg, arguments: values.toList()[1]); + // return; + // } - final routeNames = [ - Routes.mainScreen.split('/').last, - Routes.eventInfoPage.split('/').last, - ]; + // final routeNames = [ + // Routes.mainScreen.split('/').last, + // Routes.eventInfoPage.split('/').last, + // ]; - final model = locator(); - await model.initialise(); + // final model = locator(); + // await model.initialise(); - await Future.delayed(Duration.zero); - Event? event; - for (final ele in model.events) { - if (ele.id == values.last) event = ele; - } + // await Future.delayed(Duration.zero); + // Event? event; + // for (final ele in model.events) { + // if (ele.id == values.last) event = ele; + // } - if (event == null) { - showSnackBar('Event not found', MessageType.error); - pushReplacementScreen( - Routes.mainScreen, - arguments: mainScreenArgs, - ); - return; - } + // if (event == null) { + // showSnackBar('Event not found', MessageType.error); + // pushReplacementScreen( + // Routes.mainScreen, + // arguments: mainScreenArgs, + // ); + // return; + // } - final arguments = [ - MainScreenArgs(mainScreenIndex: 1), - { - "event": event, - "exploreEventViewModel": model, - }, - ]; + // final arguments = [ + // MainScreenArgs(mainScreenIndex: 1), + // { + // "event": event, + // "exploreEventViewModel": model, + // }, + // ]; - fromInviteLink(routeNames, arguments); - return; - } - } + // fromInviteLink(routeNames, arguments); + // return; + // } + // } + /// Handles User Login. + /// + /// **params**: + /// * `userLoggedIn`: Bool for if user is logged in already or not + /// + /// **returns**: + /// None void _handleUserLogIn(bool userLoggedIn) { Future.delayed(const Duration(milliseconds: 750)).then((value) async { final pushReplacementScreen = navigationService.pushReplacementScreen; @@ -230,9 +241,6 @@ class _SplashScreenState extends State { super.dispose(); } - /// Describes the part of the user interface represented by this widget. - /// BuildContext is a locator that is used to track each widget in a tree - /// and locate them and their position in the tree. @override Widget build(BuildContext context) { sizeConfig.init(context); diff --git a/lib/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart b/lib/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart index 07ef94972..157ac6742 100644 --- a/lib/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart +++ b/lib/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart @@ -1,22 +1,14 @@ -// ignore_for_file: talawa_api_doc, avoid_dynamic_calls -// ignore_for_file: talawa_good_doc_comments - import 'package:currency_picker/currency_picker.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:hive/hive.dart'; import 'package:qr_flutter/qr_flutter.dart'; -import 'package:social_share/social_share.dart'; import 'package:talawa/constants/constants.dart'; -import 'package:talawa/custom_painters/telegram_logo.dart'; -import 'package:talawa/custom_painters/whatsapp_logo.dart'; import 'package:talawa/enums/enums.dart'; import 'package:talawa/locator.dart'; import 'package:talawa/models/organization/org_info.dart'; import 'package:talawa/models/user/user_info.dart'; -import 'package:talawa/services/graphql_config.dart'; import 'package:talawa/services/navigation_service.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/services/user_config.dart'; @@ -25,8 +17,7 @@ import 'package:talawa/view_model/lang_view_model.dart'; import 'package:talawa/widgets/custom_alert_dialog.dart'; import 'package:talawa/widgets/custom_progress_dialog.dart'; -/// ProfilePageViewModel class helps to interact with model to serve data -/// and react to user's input in Profile Page view. +/// ProfilePageViewModel class helps to interact with model to serve data and react to user's input in Profile Page view. /// /// Methods include: /// * `logout` @@ -35,20 +26,50 @@ class ProfilePageViewModel extends BaseModel { final _userConfig = locator(); final _navigationService = locator(); final _appLanguageService = locator(); + + /// GlobalKey for scaffoldKey. final GlobalKey scaffoldKey = GlobalKey(); + + /// FocusNode for donationField. final FocusNode donationField = FocusNode(); + + /// Text Controller for donation Amount. TextEditingController donationAmount = TextEditingController(); + + /// Hive Box of user. late final Box user; + + /// Hive Box of url. late final Box url; + + /// Hive Box of organisation. late final Box organisation; + + /// Holds Current Organization. late OrgInfo currentOrg; + + /// Holds Current user. late User currentUser; + + /// Size of Bottom Sheet Height. double bottomSheetHeight = SizeConfig.screenHeight! * 0.68; + + /// donationCurrency. String donationCurrency = "USD"; + + /// Currency Symbol. String donationCurrencySymbol = "\$"; + + /// denomination. final List denomination = ['1', '5', '10']; - // initializer + /// First function to initialize the viewmodel. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None void initialize() { setState(ViewState.busy); currentOrg = _userConfig.currentOrg; @@ -56,8 +77,13 @@ class ProfilePageViewModel extends BaseModel { setState(ViewState.idle); } - /// This method destroys the user's session or sign out the user from app. - /// The function asks for the confimation in Custom Alert Dialog. + /// This method destroys the user's session or sign out the user from app, The function asks for the confimation in Custom Alert Dialog. + /// + /// **params**: + /// * `context`: BuildContext of the widget + /// + /// **returns**: + /// * `Future`: Resolves when user logout Future logout(BuildContext context) async { // push custom alert dialog with the confirmation message. navigationService.pushDialog( @@ -111,7 +137,17 @@ class ProfilePageViewModel extends BaseModel { } /// This method changes the currency of the user for donation purpose. - void changeCurrency(BuildContext context, Function setter) { + /// + /// **params**: + /// * `context`: BuildContext of the widget + /// * `setter`: Setter Function + /// + /// **returns**: + /// None + void changeCurrency( + BuildContext context, + void Function(void Function()) setter, + ) { showCurrencyPicker( context: context, currencyFilter: supportedCurrencies, @@ -124,16 +160,21 @@ class ProfilePageViewModel extends BaseModel { ); } - /// This function generates the organization invitation link in a Dialog Box. - /// Dialog box contains the QR-code of organization invite link and social media sharing options. + /// This Function creates a QR Code for latest release . + /// + /// **params**: + /// * `context`: Build Context + /// + /// **returns**: + /// None void invite(BuildContext context) { _appLanguageService.initialize(); // organization url - final String url = - 'https://cyberwake.github.io/applink/invite?selectLang=${_appLanguageService.appLocal.languageCode}&setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}'; + // final String url = + // 'https://cyberwake.github.io/applink/invite?selectLang=${_appLanguageService.appLocal.languageCode}&setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}'; // QR - final String qrData = - '${GraphqlConfig.orgURI}?orgid=${userConfig.currentOrg.id!}'; + const String qrData = + 'https://github.com/PalisadoesFoundation/talawa/releases/download/automated/app-release.apk'; print(url); print(qrData); showModalBottomSheet( @@ -176,48 +217,48 @@ class ProfilePageViewModel extends BaseModel { SizedBox( height: SizeConfig.screenHeight! * 0.02, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - iconButton( - const FaIcon( - FontAwesomeIcons.twitter, - size: 35, - color: Color(0xFF1DA1F2), - ), - () async => SocialShare.shareTwitter('Join us', url: url), - ), - iconButton( - CustomPaint( - size: const Size( - 50, - 50 * 1.004, - ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically - painter: WhatsappLogo(), - ), - () async => SocialShare.shareWhatsapp(url), - ), - iconButton( - CustomPaint( - size: Size( - 45, - (45 * 1).toDouble(), - ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically - painter: TelegramLogo(), - ), - () async => SocialShare.shareTelegram(url), - ), - iconButton( - const FaIcon( - FontAwesomeIcons.shareNodes, - size: 30, - color: Color(0xff40c351), - ), - () async => SocialShare.shareOptions(url), - ), - ], - ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + // mainAxisSize: MainAxisSize.min, + // children: [ + // iconButton( + // const FaIcon( + // FontAwesomeIcons.twitter, + // size: 35, + // color: Color(0xFF1DA1F2), + // ), + // () async => SocialShare.shareTwitter('Join us', url: url), + // ), + // iconButton( + // CustomPaint( + // size: const Size( + // 50, + // 50 * 1.004, + // ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically + // painter: WhatsappLogo(), + // ), + // () async => SocialShare.shareWhatsapp(url), + // ), + // iconButton( + // CustomPaint( + // size: Size( + // 45, + // (45 * 1).toDouble(), + // ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically + // painter: TelegramLogo(), + // ), + // () async => SocialShare.shareTelegram(url), + // ), + // iconButton( + // const FaIcon( + // FontAwesomeIcons.shareNodes, + // size: 30, + // color: Color(0xff40c351), + // ), + // () async => SocialShare.shareOptions(url), + // ), + // ], + // ), ], ), ), @@ -228,10 +269,13 @@ class ProfilePageViewModel extends BaseModel { /// This widget returns the button for social media sharing option. /// - /// params: - /// * [icon] : This is `Widget` type with icon details. - /// * [onTap] : This is `Function`, which invoke on tap. - Widget iconButton(Widget icon, Function onTap) { + /// **params**: + /// * `icon`: This is Widget type with icon details. + /// * `onTap`: This is Function which invoke on tap. + /// + /// **returns**: + /// * `Widget`: Icon Button + Widget iconButton(Widget icon, void Function() onTap) { return Stack( children: [ IconButton( @@ -247,13 +291,17 @@ class ProfilePageViewModel extends BaseModel { /// This widget returns button for domination. /// - /// params: - /// * [amount] : donation Amount. - /// * [setter] : `Function` type, which on tap set the amount to `donationAmount`. + /// **params**: + /// * `amount`: donation Amount. + /// * `context`: BuildContext. + /// * `setter`: `Function` type, which on tap set the amount to `donationAmount`. + /// + /// **returns**: + /// * `Widget`: Icon Button Widget dominationButton( String amount, BuildContext context, - Function setter, + void Function(void Function()) setter, ) { return InkWell( onTap: () { @@ -280,8 +328,14 @@ class ProfilePageViewModel extends BaseModel { ); } - // Listener on `donationField` widget focus. - void attachListener(Function setter) { + /// This widget returns button for domination. + /// + /// **params**: + /// * `setter`: SetState holder. + /// + /// **returns**: + /// None + void attachListener(void Function(void Function()) setter) { donationField.addListener(() { if (donationField.hasFocus) { setter(() { @@ -299,18 +353,36 @@ class ProfilePageViewModel extends BaseModel { }); } - // pop the route from `navigationService`. + /// pop the route from `navigationService`. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None void popBottomSheet() { _navigationService.pop(); } - // to update the bottom sheet height. + /// to update the bottom sheet height. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None void updateSheetHeight() { bottomSheetHeight = SizeConfig.screenHeight! * 0.65; notifyListeners(); } - // show message on Snack Bar. + /// show message on Snack Bar. + /// + /// **params**: + /// * `message`: String Message to show on snackbar + /// + /// **returns**: + /// None void showSnackBar(String message) { _navigationService.showTalawaErrorDialog(message, MessageType.error); } diff --git a/lib/view_model/main_screen_view_model.dart b/lib/view_model/main_screen_view_model.dart index d75783b2a..ff45e91fb 100644 --- a/lib/view_model/main_screen_view_model.dart +++ b/lib/view_model/main_screen_view_model.dart @@ -638,13 +638,13 @@ class MainScreenViewModel extends BaseModel { 'To help your organization grow you can support them financially from here', ), ); - targets.add( - focusTarget( - keySPInvite, - 'keySPInvite', - 'Wanna invite colleague, invite them from here', - ), - ); + // targets.add( + // focusTarget( + // keySPInvite, + // 'keySPInvite', + // 'Wanna invite colleague, invite them from here', + // ), + // ); targets.add( focusTarget( keySPPalisadoes, diff --git a/lib/view_model/widgets_view_models/like_button_view_model.dart b/lib/view_model/widgets_view_models/like_button_view_model.dart index dc47e146c..f2ff2ce9f 100644 --- a/lib/view_model/widgets_view_models/like_button_view_model.dart +++ b/lib/view_model/widgets_view_models/like_button_view_model.dart @@ -7,8 +7,8 @@ import 'package:talawa/services/post_service.dart'; import 'package:talawa/services/user_config.dart'; import 'package:talawa/view_model/base_view_model.dart'; -/// LikeButtonViewModel class helps to serve the data and -/// to react to user's input for Like Button Widget. +/// LikeButtonViewModel class helps to serve the data and to react to user's input for Like Button Widget. +/// /// /// Methods include: /// * `toggleIsLiked` @@ -32,7 +32,15 @@ class LikeButtonViewModel extends BaseModel { bool get isLiked => _isLiked; List get likedBy => _likedBy; int get likesCount => _likedBy.length; - // initialize + + /// First function to initialize the ViewModel. + /// + /// **params**: + /// * `likedBy`: List of LikedBy Objects + /// * `postID`: Post Id of the Post + /// + /// **returns**: + /// None void initialize(List likedBy, String postID) { _postID = postID; _user = _userConfig.currentUser; @@ -43,23 +51,38 @@ class LikeButtonViewModel extends BaseModel { _postService.updatedPostStream.listen((post) => updatePost(post)); } - /// This function add like to the post if not liked and - /// remove the like from the post if liked. + /// function to toggleisLiked boolean. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None void toggleIsLiked() { if (!_isLiked) { _postService.addLike(_postID); } } - /// This function set `_isLike` to true. + /// function to set isLiked boolean. + /// + /// **params**: + /// * `val`: value to set bool to. + /// + /// **returns**: + /// None void setIsLiked({bool val = true}) { _isLiked = val; notifyListeners(); } - /*TODO: This function must be removed bec the checking, that the user - has liked the post or not must be send from the backend and not - the processing should be done in front end.*/ + /// function to set isLiked boolean and check. + /// + /// **params**: + /// None + /// + /// **returns**: + /// None void checkAndSetTheIsLiked() { setIsLiked(val: false); for (var i = 0; i < _likedBy.length; i++) { @@ -69,10 +92,13 @@ class LikeButtonViewModel extends BaseModel { } } - /// This function updates the Post. + /// function to update the Post. + /// + /// **params**: + /// * `post`: Post Object /// - /// params: - /// `post` : `Post` type, the post that need to be updated. + /// **returns**: + /// None void updatePost(Post post) { if (_postID == post.sId) { _likedBy = post.likedBy!; diff --git a/lib/views/after_auth_screens/events/event_info_page.dart b/lib/views/after_auth_screens/events/event_info_page.dart index cdb44760b..262674b31 100644 --- a/lib/views/after_auth_screens/events/event_info_page.dart +++ b/lib/views/after_auth_screens/events/event_info_page.dart @@ -1,10 +1,5 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; -import 'package:social_share/social_share.dart'; import 'package:talawa/locator.dart'; -import 'package:talawa/services/graphql_config.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/utils/app_localization.dart'; import 'package:talawa/view_model/after_auth_view_models/event_view_models/event_info_view_model.dart'; @@ -15,6 +10,8 @@ import 'package:talawa/views/base_view.dart'; /// EventInfoPage returns a widget that has mutable state _EventInfoPageState. class EventInfoPage extends StatefulWidget { const EventInfoPage({super.key, required this.args}); + + /// Takes in Arguments for the Page. final Map args; @override _EventInfoPageState createState() => _EventInfoPageState(); @@ -37,15 +34,15 @@ class _EventInfoPageState extends State { AppLocalizations.of(context)! .strictTranslate('Event Details'), ), - actions: [ - IconButton( - // Button to share the event in the social medias. - icon: const Icon(Icons.share), - onPressed: () => SocialShare.shareOptions( - 'https://cyberwake.github.io/applink/eventInvite?setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}&eventId=${model.event.id}', - ), - ), - ], + // actions: [ + // IconButton( + // // Button to share the event in the social medias. + // icon: const Icon(Icons.share), + // onPressed: () => SocialShare.shareOptions( + // 'https://cyberwake.github.io/applink/eventInvite?setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}&eventId=${model.event.id}', + // ), + // ), + // ], pinned: true, expandedHeight: SizeConfig.screenWidth, flexibleSpace: FlexibleSpaceBar( diff --git a/lib/views/after_auth_screens/profile/profile_page.dart b/lib/views/after_auth_screens/profile/profile_page.dart index 17225bb54..8736f9264 100644 --- a/lib/views/after_auth_screens/profile/profile_page.dart +++ b/lib/views/after_auth_screens/profile/profile_page.dart @@ -3,7 +3,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_braintree/flutter_braintree.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:talawa/constants/routing_constants.dart'; +import 'package:talawa/enums/enums.dart'; import 'package:talawa/locator.dart'; +import 'package:talawa/models/options/options.dart'; import 'package:talawa/plugins/talawa_plugin_provider.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/utils/app_localization.dart'; @@ -11,6 +13,7 @@ import 'package:talawa/view_model/after_auth_view_models/profile_view_models/pro import 'package:talawa/view_model/main_screen_view_model.dart'; import 'package:talawa/views/base_view.dart'; import 'package:talawa/widgets/custom_avatar.dart'; +import 'package:talawa/widgets/custom_list_tile.dart'; import 'package:talawa/widgets/from_palisadoes.dart'; import 'package:talawa/widgets/raised_round_edge_button.dart'; @@ -262,27 +265,27 @@ class ProfilePage extends StatelessWidget { /// `Donation` acts as plugin. If visible is true the it will be always visible. /// even if it's uninstalled by the admin (for development purposes) //TODO: custom tile for Invitation. - // CustomListTile( - // key: homeModel!.keySPInvite, - // index: 3, - // type: TileType.option, - // option: Options( - // icon: Icon( - // Icons.share, - // color: - // Theme.of(context).colorScheme.secondary, - // size: 30, - // ), - // // title - // title: AppLocalizations.of(context)! - // .strictTranslate('Invite'), - // // subtitle - // subtitle: AppLocalizations.of(context)! - // .strictTranslate('Invite to org'), - // ), - // // on tap call the invite function - // onTapOption: () => model.invite(context), - // ), + CustomListTile( + key: homeModel!.keySPInvite, + index: 3, + type: TileType.option, + option: Options( + icon: Icon( + Icons.share, + color: + Theme.of(context).colorScheme.secondary, + size: 30, + ), + // title + title: AppLocalizations.of(context)! + .strictTranslate('Invite'), + // subtitle + subtitle: AppLocalizations.of(context)! + .strictTranslate('Invite to org'), + ), + // on tap call the invite function + onTapOption: () => model.invite(context), + ), SizedBox( height: SizeConfig.screenHeight! * 0.05, ), diff --git a/lib/widgets/invite_child.dart b/lib/widgets/invite_child.dart index 3b973b711..e76deab1b 100644 --- a/lib/widgets/invite_child.dart +++ b/lib/widgets/invite_child.dart @@ -1,29 +1,28 @@ -// ignore_for_file: talawa_api_doc, avoid_dynamic_calls -// ignore_for_file: talawa_good_doc_comments - import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart'; -import 'package:social_share/social_share.dart'; -import 'package:talawa/custom_painters/telegram_logo.dart'; -import 'package:talawa/custom_painters/whatsapp_logo.dart'; import 'package:talawa/locator.dart'; -import 'package:talawa/services/graphql_config.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/view_model/lang_view_model.dart'; /// Creating an instance of AppLangauge() to set up localized values for each locale that our app supports. final _appLanguageService = locator(); -/// This widget gives us various options to invite someone to an organization. -/// We can use QR code scanner, social media platforms like twitter, whatsapp, telegram and many more. +/// We can use QR code scanner, social media platforms like twitter, whatsapp, telegram and many more.. +/// +/// more_info_if_required +/// +/// **params**: +/// * `context`: Build Context +/// +/// **returns**: +/// * `Widget`: Returns Column with QR Code Widget invite(BuildContext context) { _appLanguageService.initialize(); - final String url = - 'https://cyberwake.github.io/applink/invite?selectLang=${_appLanguageService.appLocal.languageCode}&setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}'; - final String qrData = - '${GraphqlConfig.orgURI}?orgid=${userConfig.currentOrg.id!}'; + // final String url = + // 'https://cyberwake.github.io/applink/invite?selectLang=${_appLanguageService.appLocal.languageCode}&setUrl=${GraphqlConfig.orgURI}&selectOrg=${userConfig.currentOrg.id!}'; + const String qrData = + 'https://github.com/PalisadoesFoundation/talawa/releases/download/automated/app-release.apk'; // print(url); // print(qrData); @@ -52,60 +51,67 @@ Widget invite(BuildContext context) { height: SizeConfig.screenHeight! * 0.02, ), //Tap on the Twitter icon to join the organization through Twitter. - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - iconButton( - "Twitter", - const FaIcon( - FontAwesomeIcons.twitter, - size: 35, - color: Color(0xFF1DA1F2), - ), - () async => SocialShare.shareTwitter('Join us', url: url), - ), - //Tap on the Whatsapp icon to join the organization through Whatsapp. - iconButton( - "WhatsApp", - CustomPaint( - size: const Size( - 50, - 50 * 1.004, - ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically - painter: WhatsappLogo(), - ), - () async => SocialShare.shareWhatsapp(url), - ), - iconButton( - "Telegram", - CustomPaint( - size: Size( - 45, - (45 * 1).toDouble(), - ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically - painter: TelegramLogo(), - ), - () async => SocialShare.shareTelegram(url), - ), - iconButton( - "Alt", - const FaIcon( - FontAwesomeIcons.shareNodes, - size: 30, - color: Color(0xff40c351), - ), - () async => SocialShare.shareOptions(url), - ), - ], - ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + // mainAxisSize: MainAxisSize.min, + // children: [ + // iconButton( + // "Twitter", + // const FaIcon( + // FontAwesomeIcons.twitter, + // size: 35, + // color: Color(0xFF1DA1F2), + // ), + // () async => SocialShare.shareTwitter('Join us', url: url), + // ), + // //Tap on the Whatsapp icon to join the organization through Whatsapp. + // iconButton( + // "WhatsApp", + // CustomPaint( + // size: const Size( + // 50, + // 50 * 1.004, + // ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically + // painter: WhatsappLogo(), + // ), + // () async => SocialShare.shareWhatsapp(url), + // ), + // iconButton( + // "Telegram", + // CustomPaint( + // size: Size( + // 45, + // (45 * 1).toDouble(), + // ), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically + // painter: TelegramLogo(), + // ), + // () async => SocialShare.shareTelegram(url), + // ), + // iconButton( + // "Alt", + // const FaIcon( + // FontAwesomeIcons.shareNodes, + // size: 30, + // color: Color(0xff40c351), + // ), + // () async => SocialShare.shareOptions(url), + // ), + // ], + // ), ], ); } -/// This function is for debugging purposes. /// It prints "tapped" in the console for the developer to know that the button was tapped. -Widget iconButton(String key, Widget icon, Function onTap) { +/// +/// **params**: +/// * `key`: Key of the Widget +/// * `icon`: Icon to be displayed +/// * `onTap`: on tap function +/// +/// **returns**: +/// * `Widget`: returns IconButton. +Widget iconButton(String key, Widget icon, void Function() onTap) { return Stack( children: [ IconButton( diff --git a/test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_tests.dart b/test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_test.dart similarity index 60% rename from test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_tests.dart rename to test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_test.dart index ba2ac49dd..298fb919c 100644 --- a/test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_tests.dart +++ b/test/view_model_tests/after_auth_view_model_tests/profile_view_model_tests/profile_page_view_model_test.dart @@ -4,10 +4,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; +import 'package:talawa/enums/enums.dart'; import 'package:talawa/services/graphql_config.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/view_model/after_auth_view_models/profile_view_models/profile_page_view_model.dart'; - import '../../../helpers/test_helpers.dart'; import '../../../helpers/test_locator.dart'; @@ -58,7 +58,12 @@ void main() { model.initialize(); model.showSnackBar("fake_message"); - verify(navigationService.showSnackBar("fake_message")); + verify( + navigationService.showTalawaErrorDialog( + "fake_message", + MessageType.error, + ), + ); model.popBottomSheet(); verify(navigationService.pop()); @@ -94,7 +99,13 @@ void main() { const String amt = "test_amt"; await tester.pumpWidget( MaterialApp( - home: Scaffold(body: model.dominationButton(amt, mockContext, () {})), + home: Scaffold( + body: model.dominationButton( + amt, + mockContext, + (void Function() callback) {}, + ), + ), ), ); final containerFinder = find.byType(Container); @@ -119,5 +130,70 @@ void main() { //Ensures that naviagation service was called verifyInteraction(mocknav, mockName: "NavigationService"); }); + + testWidgets('Test changeCurrency function', (WidgetTester tester) async { + // Mock data + final model = ProfilePageViewModel(); + model.initialize(); + // Set up a MaterialApp for testing + await tester.pumpWidget( + MaterialApp( + home: Builder( + builder: (BuildContext context) { + return TextButton( + child: Container(), + // You might need a button to trigger the changeCurrency function + onPressed: () { + model.changeCurrency(context, (Function callback) {}); + }, + ); + }, + ), + ), + ); + + // Trigger the button press to invoke changeCurrency + await tester.tap(find.byType(TextButton)); + await tester.pump(); + }); + + testWidgets('Test attachListener function', (WidgetTester tester) async { + // Mock data + final model = ProfilePageViewModel(); + model.initialize(); + final TextEditingController donationField = TextEditingController(); + // Set up a MaterialApp for testing + await tester.pumpWidget( + MaterialApp( + home: Builder( + builder: (BuildContext context) { + return Material( + child: TextFormField( + controller: donationField, + ), + ); + }, + ), + ), + ); + + // Attach the listener + model.attachListener( + (p0) => p0(), + ); + + // Trigger the listener by focusing on the TextFormField + await tester.tap(find.byType(TextFormField)); + await tester.pump(); + + // Now you can check if bottomSheetHeight is updated when the field has focus + expect(model.bottomSheetHeight, 465.12000000000006); + + // Trigger the listener by removing focus from the TextFormField after a delay + await tester.pump(const Duration(milliseconds: 300)); + + // Now you can check if bottomSheetHeight is updated after losing focus + expect(model.bottomSheetHeight, SizeConfig.screenHeight! * 0.68); + }); }); } diff --git a/test/widget_tests/after_auth_screens/events/event_info_page_test.dart b/test/widget_tests/after_auth_screens/events/event_info_page_test.dart index c10e697e8..ca898eb34 100644 --- a/test/widget_tests/after_auth_screens/events/event_info_page_test.dart +++ b/test/widget_tests/after_auth_screens/events/event_info_page_test.dart @@ -81,18 +81,18 @@ void main() { unregisterViewModels(); }); group('Test EventInfoPage', () { - testWidgets('Test Share button', (tester) async { - mockNetworkImages(() async { - await tester.pumpWidget(createEventInfoPage(true, true)); - await tester.pumpAndSettle(); - - final shareButton = find.byIcon(Icons.share); - expect(shareButton, findsOneWidget); - - await tester.tap(shareButton); - await tester.pumpAndSettle(); - }); - }); + // testWidgets('Test Share button', (tester) async { + // mockNetworkImages(() async { + // await tester.pumpWidget(createEventInfoPage(true, true)); + // await tester.pumpAndSettle(); + + // final shareButton = find.byIcon(Icons.share); + // expect(shareButton, findsOneWidget); + + // await tester.tap(shareButton); + // await tester.pumpAndSettle(); + // }); + // }); testWidgets('Test FloatingActionButton', (tester) async { mockNetworkImages(() async { diff --git a/test/widget_tests/widgets/invite_child_test.dart b/test/widget_tests/widgets/invite_child_test.dart deleted file mode 100644 index 124cdd2b7..000000000 --- a/test/widget_tests/widgets/invite_child_test.dart +++ /dev/null @@ -1,87 +0,0 @@ -// ignore_for_file: talawa_api_doc -// ignore_for_file: talawa_good_doc_comments - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:talawa/widgets/invite_child.dart'; - -import '../../helpers/test_locator.dart'; - -class CreateInviteChild extends StatelessWidget { - @override - Widget build(BuildContext context) { - sizeConfig.test(); //init(context); - return MaterialApp(home: Scaffold(body: invite(context))); - } -} - -void main() { - testSetupLocator(); - - testWidgets("QR Code Checking", (WidgetTester tester) async { - // finding the widgets - - // QR code can be tested only using links - final qr = find.byKey(const ValueKey("QRcode")); - - // execute the test - await tester.pumpWidget(CreateInviteChild()); - await tester.tap(qr); - await tester.pump(); - - // checking the output - expect(qr, findsOneWidget); - }); - - testWidgets("Tapping On Twitter Button", (WidgetTester tester) async { - // finding the widgets - final twitter = find.byKey(const ValueKey("Twitter")); - - // execute the test - await tester.pumpWidget(CreateInviteChild()); - await tester.tap(twitter); - await tester.pump(); - - // checking the output - expect(twitter, findsOneWidget); - }); - - testWidgets("Tapping On WhatsApp Button", (WidgetTester tester) async { - // finding the widgets - final whatsapp = find.byKey(const ValueKey("WhatsApp")); - - // execute the test - await tester.pumpWidget(CreateInviteChild()); - await tester.tap(whatsapp); - await tester.pump(); - - // checking the output - expect(whatsapp, findsOneWidget); - }); - - testWidgets("Tapping On Telegram Button", (WidgetTester tester) async { - // finding the widgets - final telegram = find.byKey(const ValueKey("Telegram")); - - // execute the test - await tester.pumpWidget(CreateInviteChild()); - await tester.tap(telegram); - await tester.pump(); - - // checking the output - expect(telegram, findsOneWidget); - }); - - testWidgets("Tapping On Alt Button", (WidgetTester tester) async { - // finding the widgets - final alt = find.byKey(const ValueKey("Alt")); - - // execute the test - await tester.pumpWidget(CreateInviteChild()); - await tester.tap(alt); - await tester.pump(); - - // checking the output - expect(alt, findsOneWidget); - }); -}