From e309aa357ae426b49642b51e487d846f60b388ee Mon Sep 17 00:00:00 2001 From: noman2002 Date: Wed, 16 Mar 2022 10:19:23 +0530 Subject: [PATCH 1/2] removed subscribed to mail data for others profile --- lib/ui/views/profile/profile_view.dart | 36 +++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/ui/views/profile/profile_view.dart b/lib/ui/views/profile/profile_view.dart index 98cfdbee..49d0dcf8 100644 --- a/lib/ui/views/profile/profile_view.dart +++ b/lib/ui/views/profile/profile_view.dart @@ -113,6 +113,37 @@ class _ProfileViewState extends State { return Container(); } + Widget _buildSubscribeToMailComponent() { + var _attrs = _model.user?.data.attributes; + + var _localStorageService = locator(); + if (_localStorageService.isLoggedIn && + userId == _localStorageService.currentUser!.data.id) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 4), + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + style: Theme.of(context).textTheme.bodyText1, + children: [ + TextSpan( + text: 'Subscribed to mails : ', + style: Theme.of(context).textTheme.bodyText1?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: _attrs?.subscribed.toString(), + ) + ], + ), + ), + ); + } + + return Container(); + } + Widget _buildProfileCard() { var _attrs = _model.user?.data.attributes; @@ -153,10 +184,7 @@ class _ProfileViewState extends State { 'Educational Institute', _attrs?.educationalInstitute, ), - _buildProfileComponent( - 'Subscribed to mails', - _attrs?.subscribed.toString(), - ), + _buildSubscribeToMailComponent(), _buildEditProfileButton() ], ), From 4d723e9cd864ae8b3b108511c081ac592c97683b Mon Sep 17 00:00:00 2001 From: Aman Date: Sun, 5 Jun 2022 06:09:35 +0530 Subject: [PATCH 2/2] rfac: refactor the implementation logic Signed-off-by: Aman --- analysis_options.yaml | 8 + lib/models/user.dart | 2 +- .../views/ib/builders/ib_webview_builder.dart | 31 ++-- lib/ui/views/ib/ib_landing_view.dart | 10 +- lib/ui/views/profile/profile_view.dart | 60 ++------ lib/viewmodels/ib/ib_page_viewmodel.dart | 2 +- lib/viewmodels/profile/profile_viewmodel.dart | 22 ++- pubspec.lock | 143 +++--------------- pubspec.yaml | 17 +-- test/ui_tests/profile/profile_view_test.dart | 5 +- .../profile/profile_viewmodel_test.dart | 6 +- 11 files changed, 102 insertions(+), 204 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 718e36d6..8c5b0110 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -11,3 +11,11 @@ linter: non_constant_identifier_names: false constant_identifier_names: false + + no_leading_underscores_for_local_identifiers: false + + library_private_types_in_public_api: false + + depend_on_referenced_packages: false + + use_build_context_synchronously: false diff --git a/lib/models/user.dart b/lib/models/user.dart index 80a48898..5c00313e 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -61,7 +61,7 @@ class UserAttributes { this.educationalInstitute, }); String? name; - String email; + String? email; bool subscribed; DateTime? createdAt; DateTime? updatedAt; diff --git a/lib/ui/views/ib/builders/ib_webview_builder.dart b/lib/ui/views/ib/builders/ib_webview_builder.dart index 9350767e..bd003015 100644 --- a/lib/ui/views/ib/builders/ib_webview_builder.dart +++ b/lib/ui/views/ib/builders/ib_webview_builder.dart @@ -13,21 +13,24 @@ class IbWebViewBuilder extends MarkdownElementBuilder { return Html( data: textContent, - customRender: { - 'iframe': (RenderContext context, Widget child) { - final width = MediaQuery.of(context.buildContext).size.width; - final height = (width * 9) / 16; + customRenders: { + tagMatcher('iframe'): CustomRender.widget( + widget: (context, child) { + final width = MediaQuery.of(context.buildContext).size.width; + final height = (width * 9) / 16; - return SizedBox( - width: width, - height: height, - child: WebView( - initialUrl: context.tree.element?.attributes['src'], - javascriptMode: JavascriptMode.unrestricted, - initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow, - ), - ); - }, + return SizedBox( + width: width, + height: height, + child: WebView( + initialUrl: context.tree.element?.attributes['src'], + javascriptMode: JavascriptMode.unrestricted, + initialMediaPlaybackPolicy: + AutoMediaPlaybackPolicy.always_allow, + ), + ); + }, + ), }, ); } diff --git a/lib/ui/views/ib/ib_landing_view.dart b/lib/ui/views/ib/ib_landing_view.dart index 86743f63..c7f8591e 100644 --- a/lib/ui/views/ib/ib_landing_view.dart +++ b/lib/ui/views/ib/ib_landing_view.dart @@ -85,19 +85,19 @@ class _IbLandingViewState extends State { ? Showcase( key: _model.toc, description: 'Show Table of Contents', - child: IconButton( - icon: const Icon(Icons.menu_book_rounded), - onPressed: value as VoidCallback, - ), onTargetClick: () { _model.onShowCased('toc'); if (_key.currentState!.isDrawerOpen) Get.back(); Future.delayed( const Duration(milliseconds: 200), - value, + value as VoidCallback, ); }, disposeOnTap: true, + child: IconButton( + icon: const Icon(Icons.menu_book_rounded), + onPressed: value as VoidCallback, + ), ) : Container(); }, diff --git a/lib/ui/views/profile/profile_view.dart b/lib/ui/views/profile/profile_view.dart index 49d0dcf8..e3d36845 100644 --- a/lib/ui/views/profile/profile_view.dart +++ b/lib/ui/views/profile/profile_view.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:mobile_app/cv_theme.dart'; -import 'package:mobile_app/locator.dart'; import 'package:mobile_app/models/user.dart'; -import 'package:mobile_app/services/local_storage_service.dart'; import 'package:mobile_app/ui/components/cv_tab_bar.dart'; import 'package:mobile_app/ui/views/base_view.dart'; import 'package:mobile_app/ui/views/profile/user_favourites_view.dart'; @@ -26,14 +24,6 @@ class ProfileView extends StatefulWidget { class _ProfileViewState extends State { late ProfileViewModel _model; - String? userId; - - @override - void initState() { - super.initState(); - userId = - widget.userId ?? locator().currentUser?.data.id; - } Widget _buildProfileImage() { return Padding( @@ -84,9 +74,7 @@ class _ProfileViewState extends State { } Widget _buildEditProfileButton() { - var _localStorageService = locator(); - if (_localStorageService.isLoggedIn && - userId == _localStorageService.currentUser!.data.id) { + if (_model.isLoggedIn && _model.isPersonalProfile) { return ElevatedButton( style: ElevatedButton.styleFrom( primary: CVTheme.primaryColor, @@ -113,37 +101,6 @@ class _ProfileViewState extends State { return Container(); } - Widget _buildSubscribeToMailComponent() { - var _attrs = _model.user?.data.attributes; - - var _localStorageService = locator(); - if (_localStorageService.isLoggedIn && - userId == _localStorageService.currentUser!.data.id) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 4), - alignment: Alignment.centerLeft, - child: RichText( - text: TextSpan( - style: Theme.of(context).textTheme.bodyText1, - children: [ - TextSpan( - text: 'Subscribed to mails : ', - style: Theme.of(context).textTheme.bodyText1?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - TextSpan( - text: _attrs?.subscribed.toString(), - ) - ], - ), - ), - ); - } - - return Container(); - } - Widget _buildProfileCard() { var _attrs = _model.user?.data.attributes; @@ -184,7 +141,11 @@ class _ProfileViewState extends State { 'Educational Institute', _attrs?.educationalInstitute, ), - _buildSubscribeToMailComponent(), + if (_model.isLoggedIn && _model.isPersonalProfile) + _buildProfileComponent( + 'Subscribed to mails', + _attrs?.subscribed.toString(), + ), _buildEditProfileButton() ], ), @@ -196,7 +157,7 @@ class _ProfileViewState extends State { } Widget _buildProjectsTabBar() { - if (userId == null) return Container(); + if (_model.userId == null) return Container(); return Expanded( child: Card( shape: RoundedRectangleBorder( @@ -224,8 +185,8 @@ class _ProfileViewState extends State { ), body: TabBarView( children: [ - UserProjectsView(userId: userId!), - UserFavouritesView(userId: userId!), + UserProjectsView(userId: _model.userId!), + UserFavouritesView(userId: _model.userId!), ], ), ), @@ -239,7 +200,8 @@ class _ProfileViewState extends State { return BaseView( onModelReady: (model) { _model = model; - _model.fetchUserProfile(userId); + _model.userId = widget.userId; + _model.fetchUserProfile(); }, builder: (context, model, child) => Scaffold( appBar: widget.userId != null diff --git a/lib/viewmodels/ib/ib_page_viewmodel.dart b/lib/viewmodels/ib/ib_page_viewmodel.dart index 7784c8ce..1e975566 100644 --- a/lib/viewmodels/ib/ib_page_viewmodel.dart +++ b/lib/viewmodels/ib/ib_page_viewmodel.dart @@ -64,7 +64,7 @@ class IbPageViewModel extends BaseModel { if (!state.tocButton) _list.add(keysMap['toc']); if (_list.isNotEmpty) { - WidgetsBinding.instance!.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { Future.delayed(const Duration(milliseconds: 800), () { showCaseWidgetState.startShowCase(_list); }); diff --git a/lib/viewmodels/profile/profile_viewmodel.dart b/lib/viewmodels/profile/profile_viewmodel.dart index aa1e7dfb..0510b89e 100644 --- a/lib/viewmodels/profile/profile_viewmodel.dart +++ b/lib/viewmodels/profile/profile_viewmodel.dart @@ -4,6 +4,7 @@ import 'package:mobile_app/models/failure_model.dart'; import 'package:mobile_app/models/projects.dart'; import 'package:mobile_app/models/user.dart'; import 'package:mobile_app/services/API/users_api.dart'; +import 'package:mobile_app/services/local_storage_service.dart'; import 'package:mobile_app/viewmodels/base_viewmodel.dart'; class ProfileViewModel extends BaseModel { @@ -11,6 +12,16 @@ class ProfileViewModel extends BaseModel { String FETCH_USER_PROFILE = 'fetch_user_profile'; final UsersApi _usersApi = locator(); + final LocalStorageService _localStorageService = + locator(); + + String? _userId; + + String? get userId => _userId; + + set userId(String? id) { + _userId = id ?? _localStorageService.currentUser?.data.id; + } User? _user; @@ -21,6 +32,11 @@ class ProfileViewModel extends BaseModel { notifyListeners(); } + bool get isLoggedIn => _localStorageService.isLoggedIn; + + bool get isPersonalProfile => + _localStorageService.currentUser?.data.id == _userId; + Project? _updatedProject; Project? get updatedProject => _updatedProject; @@ -30,11 +46,11 @@ class ProfileViewModel extends BaseModel { notifyListeners(); } - Future? fetchUserProfile(String? userId) async { - if (userId == null) return; + Future? fetchUserProfile() async { + if (_userId == null) return; setStateFor(FETCH_USER_PROFILE, ViewState.Busy); try { - user = await _usersApi.fetchUser(userId); + user = await _usersApi.fetchUser(_userId!); setStateFor(FETCH_USER_PROFILE, ViewState.Success); } on Failure catch (f) { diff --git a/pubspec.lock b/pubspec.lock index 6178cccf..b05f3bd2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -120,20 +120,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" - chewie: - dependency: transitive - description: - name: chewie - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - chewie_audio: - dependency: transitive - description: - name: chewie_audio - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" cli_util: dependency: transitive description: @@ -161,7 +147,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: @@ -217,7 +203,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: @@ -271,7 +257,7 @@ packages: name: flutter_html url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.0.0-alpha.3" flutter_keyboard_visibility: dependency: "direct main" description: @@ -293,20 +279,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" - flutter_layout_grid: - dependency: transitive - description: - name: flutter_layout_grid - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" flutter_lints: dependency: "direct dev" description: name: flutter_lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -327,7 +306,7 @@ packages: name: flutter_math_fork url: "https://pub.dartlang.org" source: hosted - version: "0.5.0" + version: "0.6.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -390,7 +369,7 @@ packages: name: flutter_svg url: "https://pub.dartlang.org" source: hosted - version: "0.23.0+1" + version: "1.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -402,7 +381,7 @@ packages: name: flutter_typeahead url: "https://pub.dartlang.org" source: hosted - version: "3.2.4" + version: "4.0.0" flutter_web_auth: dependency: transitive description: @@ -575,7 +554,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: transitive description: @@ -589,7 +568,7 @@ packages: name: lints url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "2.0.0" logging: dependency: transitive description: @@ -617,7 +596,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.4" meta: dependency: transitive description: @@ -673,21 +652,21 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" path_drawing: dependency: transitive description: name: path_drawing url: "https://pub.dartlang.org" source: hosted - version: "0.5.1+1" + version: "1.0.0" path_parsing: dependency: transitive description: name: path_parsing url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "1.0.0" path_provider: dependency: transitive description: @@ -750,16 +729,14 @@ packages: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "5.0.0" photo_view: dependency: "direct main" description: - path: "." - ref: HEAD - resolved-ref: b0668f46e808f6ad708ecc3e9671ac4ca31bb938 - url: "https://github.com/bluefireteam/photo_view.git" - source: git - version: "0.13.0" + name: photo_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.0" platform: dependency: transitive description: @@ -829,7 +806,7 @@ packages: name: scroll_to_index url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "3.0.1" share: dependency: "direct main" description: @@ -939,7 +916,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -981,7 +958,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.9" theme_provider: dependency: "direct main" description: @@ -1086,77 +1063,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" - video_player: - dependency: transitive - description: - name: video_player - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.18" - video_player_android: - dependency: transitive - description: - name: video_player_android - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.17" - video_player_avfoundation: - dependency: transitive - description: - name: video_player_avfoundation - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.18" - video_player_platform_interface: - dependency: transitive - description: - name: video_player_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "5.0.2" - video_player_web: - dependency: transitive - description: - name: video_player_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7" - wakelock: - dependency: transitive - description: - name: wakelock - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.6" - wakelock_macos: - dependency: transitive - description: - name: wakelock_macos - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.0" - wakelock_platform_interface: - dependency: transitive - description: - name: wakelock_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.0" - wakelock_web: - dependency: transitive - description: - name: wakelock_web - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.0" - wakelock_windows: - dependency: transitive - description: - name: wakelock_windows - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0" + version: "2.1.2" watcher: dependency: transitive description: @@ -1219,7 +1126,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "6.1.0" yaml: dependency: transitive description: @@ -1228,5 +1135,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.15.0 <3.0.0" - flutter: ">=2.10.0" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9092aa6c..d9dcfa53 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: flutter: sdk: flutter flutter_facebook_auth: ^4.0.1 - flutter_html: ^2.0.0 + flutter_html: ^3.0.0-alpha.3 flutter_keyboard_visibility: ^5.0.2 flutter_localizations: sdk: flutter @@ -32,10 +32,10 @@ dependencies: git: url: https://github.com/CircuitVerse/packages.git path: packages/flutter_markdown - flutter_math_fork: ^0.5.0 + flutter_math_fork: ^0.6.2 flutter_summernote: ^1.0.0 - flutter_svg: ^0.23.0+1 - flutter_typeahead: ^3.1.3 + flutter_svg: ^1.1.0 + flutter_typeahead: ^4.0.0 fluttericon: ^2.0.0 get: ^4.6.1 get_it: ^7.2.0 @@ -48,9 +48,9 @@ dependencies: intl: ^0.17.0 mockito: ^5.0.17 oauth2_client: ^2.2.2 - photo_view: ^0.13.0 + photo_view: ^0.14.0 provider: ^6.0.2 - scroll_to_index: ^2.1.1 + scroll_to_index: ^3.0.1 share: ^2.0.4 shared_preferences: ^2.0.12 showcaseview: ^1.1.4 @@ -61,7 +61,7 @@ dependencies: dev_dependencies: build_runner: ^2.1.7 - flutter_lints: ^1.0.4 + flutter_lints: ^2.0.1 flutter_test: sdk: flutter hive_generator: ^1.1.2 @@ -69,9 +69,6 @@ dev_dependencies: dependency_overrides: mime: ^1.0.1 plugin_platform_interface: ^2.1.2 - photo_view: - git: - url: https://github.com/bluefireteam/photo_view.git flutter_icons: android: "launcher_icon" diff --git a/test/ui_tests/profile/profile_view_test.dart b/test/ui_tests/profile/profile_view_test.dart index f9ee3398..8d2f4063 100644 --- a/test/ui_tests/profile/profile_view_test.dart +++ b/test/ui_tests/profile/profile_view_test.dart @@ -39,10 +39,13 @@ void main() { var _profileViewModel = MockProfileViewModel(); locator.registerSingleton(_profileViewModel); + when(_profileViewModel.userId).thenAnswer((_) => 'userId'); + when(_profileViewModel.isLoggedIn).thenAnswer((_) => true); + when(_profileViewModel.isPersonalProfile).thenAnswer((_) => true); when(_profileViewModel.FETCH_USER_PROFILE) .thenAnswer((_) => 'fetch_user_profile'); - when(_profileViewModel.fetchUserProfile(any)).thenReturn(null); + when(_profileViewModel.fetchUserProfile()).thenReturn(null); when(_profileViewModel.isSuccess(_profileViewModel.FETCH_USER_PROFILE)) .thenReturn(true); diff --git a/test/viewmodel_tests/profile/profile_viewmodel_test.dart b/test/viewmodel_tests/profile/profile_viewmodel_test.dart index 94e03cea..27c1338a 100644 --- a/test/viewmodel_tests/profile/profile_viewmodel_test.dart +++ b/test/viewmodel_tests/profile/profile_viewmodel_test.dart @@ -22,7 +22,8 @@ void main() { .thenAnswer((_) => Future.value(_user)); var _model = ProfileViewModel(); - await _model.fetchUserProfile('1'); + _model.userId = '1'; + await _model.fetchUserProfile(); // verify API call is made.. verify(_mockUsersApi.fetchUser('1')); @@ -38,7 +39,8 @@ void main() { .thenThrow(Failure('Some Error Occurred!')); var _model = ProfileViewModel(); - await _model.fetchUserProfile('1'); + _model.userId = '1'; + await _model.fetchUserProfile(); // verify Error ViewState with proper error message.. expect(_model.stateFor(_model.FETCH_USER_PROFILE), ViewState.Error);