diff --git a/android/app/build.gradle b/android/app/build.gradle index be8fc176..d8d45f76 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -27,7 +27,7 @@ if (flutterVersionName == null) { android { namespace "org.aossie.monumento" - compileSdk 34 + compileSdk 35 ndkVersion flutter.ndkVersion compileOptions { diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e1ca574e..aa49780c 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index e957b1ae..b083ba05 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false + id "com.android.application" version "8.2.1" apply false // START: FlutterFire Configuration id "com.google.gms.google-services" version "4.3.15" apply false // END: FlutterFire Configuration diff --git a/firepit-log.txt b/firepit-log.txt new file mode 100644 index 00000000..d02878d8 --- /dev/null +++ b/firepit-log.txt @@ -0,0 +1,24 @@ +Welcome to firepit v1.1.0! +Doing JSON parses for version checks at /snapshot/firepit/vendor/node_modules/firebase-tools/package.json +is-ci,mime,rc,yaml,abbrev,abort-controller,accepts,agent-base,aggregate-error,ajv,ajv-formats,ansi-align,ansi-escapes,ansi-regex,ansi-styles,any-promise,anymatch,archiver,archiver-utils,argparse,array-flatten,arrify,as-array,ast-types,async,async-lock,asynckit,b4a,balanced-match,bare-events,base64-js,basic-auth,basic-auth-connect,basic-ftp,bignumber.js,binary-extensions,bl,body-parser,boxen,brace-expansion,braces,buffer,buffer-crc32,buffer-equal-constant-time,bytes,cacache,call-bind-apply-helpers,call-bound,call-me-maybe,camelcase,chalk,char-regex,chardet,chokidar,chownr,ci-info,cjson,clean-stack,cli-boxes,cli-cursor,cli-highlight,cli-spinners,cli-table3,cli-width,cliui,clone,color,color-convert,color-name,color-string,colorette,colorspace,combined-stream,commander,compress-commons,compressible,compression,concat-map,config-chain,configstore,connect,content-disposition,content-type,cookie,cookie-signature,core-util-is,cors,crc-32,crc32-stream,cross-env,cross-spawn,crypto-random-string,csv-parse,data-uri-to-buffer,debug,deep-equal-in-any-order,deep-extend,deep-freeze,deep-is,defaults,degenerator,delayed-stream,depd,destroy,discontinuous-range,dot-prop,dunder-proto,duplexify,eastasianwidth,ecdsa-sig-formatter,ee-first,emoji-regex,emojilib,enabled,encodeurl,encoding,end-of-stream,env-paths,environment,err-code,es-define-property,es-errors,es-object-atoms,es-set-tostringtag,escalade,escape-goat,escape-html,escape-string-regexp,escodegen,esprima,estraverse,esutils,etag,event-target-shim,events,events-listener,exegesis,exegesis-express,exponential-backoff,express,extend,external-editor,fast-deep-equal,fast-fifo,fast-uri,fecha,figures,filesize,fill-range,finalhandler,firebase-tools,fn.name,foreground-child,form-data,forwarded,fresh,fs-extra,fs-minipass,function-bind,fuzzy,gaxios,gcp-metadata,get-caller-file,get-intrinsic,get-proto,get-stdin,get-uri,glob,glob-parent,glob-slash,glob-slasher,global-dirs,google-auth-library,google-gax,google-logging-utils,googleapis-common,gopd,graceful-fs,gtoken,has-flag,has-symbols,has-tostringtag,has-yarn,hasown,heap-js,highlight.js,http-cache-semantics,http-errors,http-proxy-agent,https-proxy-agent,iconv-lite,ieee754,import-lazy,imurmurhash,indent-string,inherits,ini,inquirer,inquirer-autocomplete-prompt,install-artifact-from-github,ip-address,ip-regex,ipaddr.js,is-arrayish,is-binary-path,is-buffer,is-extglob,is-fullwidth-code-point,is-glob,is-installed-globally,is-interactive,is-lambda,is-npm,is-number,is-obj,is-path-inside,is-promise,is-stream,is-stream-ended,is-typedarray,is-unicode-supported,is-url,is-wsl,is-yarn-global,is2,isarray,isexe,isomorphic-fetch,jackspeak,jju,join-path,js-yaml,jsbn,json-bigint,json-parse-helpfulerror,json-ptr,json-schema-traverse,jsonfile,jsonwebtoken,jwa,jws,kind-of,kuler,lazystream,leven,libsodium,libsodium-wrappers,lodash,lodash._objecttypes,lodash.camelcase,lodash.includes,lodash.isboolean,lodash.isinteger,lodash.isnumber,lodash.isobject,lodash.isplainobject,lodash.isstring,lodash.mapvalues,lodash.once,lodash.snakecase,log-symbols,logform,long,lru-cache,lsofi,make-dir,make-fetch-happen,marked,marked-terminal,math-intrinsics,media-typer,merge-descriptors,methods,mime-db,mime-types,mimic-fn,minimatch,minimist,minipass,minipass-collect,minipass-fetch,minipass-flush,minipass-pipeline,minipass-sized,minizlib,mkdirp,moo,morgan,ms,mute-stream,mz,nan,nearley,negotiator,netmask,node-emoji,node-fetch,node-gyp,nopt,normalize-path,object-assign,object-hash,object-inspect,on-finished,on-headers,once,one-time,onetime,open,openapi3-ts,ora,os-tmpdir,p-defer,p-limit,p-map,p-throttle,pac-proxy-agent,pac-resolver,package-json-from-dist,parse5,parse5-htmlparser2-tree-adapter,parseurl,path-key,path-scurry,path-to-regexp,pg,pg-cloudflare,pg-connection-string,pg-int8,pg-pool,pg-protocol,pg-types,pgpass,picocolors,picomatch,portfinder,postgres-array,postgres-bytea,postgres-date,postgres-interval,proc-log,process,process-nextick-args,progress,promise-breaker,promise-retry,proto-list,proto3-json-serializer,protobufjs,proxy-addr,proxy-agent,proxy-from-env,pupa,qs,railroad-diagrams,randexp,range-parser,raw-body,re2,readable-stream,readdir-glob,readdirp,registry-auth-token,registry-url,require-directory,require-from-string,restore-cursor,ret,retry,retry-request,router,run-async,rxjs,safe-buffer,safe-stable-stringify,safer-buffer,semver,semver-diff,send,serve-static,setprototypeof,shebang-command,shebang-regex,side-channel,side-channel-list,side-channel-map,side-channel-weakmap,signal-exit,simple-swizzle,skin-tone,smart-buffer,socks,socks-proxy-agent,sort-any,source-map,split2,sprintf-js,sql-formatter,ssri,stack-trace,statuses,stream-chain,stream-events,stream-json,stream-shift,streamx,string-width,string-width-cjs,string_decoder,strip-ansi,strip-ansi-cjs,strip-json-comments,stubs,superstatic,supports-color,supports-hyperlinks,tar,tar-stream,tcp-port-used,teeny-request,text-decoder,text-hex,thenify,thenify-all,through,through2,tmp,to-regex-range,toidentifier,toxic,tr46,triple-beam,tslib,tsscmp,type-fest,type-is,typedarray-to-buffer,undici-types,unicode-emoji-modifier-base,unique-filename,unique-slug,unique-string,universal-analytics,universalify,unpipe,update-notifier-cjs,url-join,url-template,util-deprecate,utils-merge,uuid,valid-url,vary,wcwidth,webidl-conversions,whatwg-fetch,whatwg-url,which,widest-line,winston,winston-transport,wrap-ansi,wrap-ansi-cjs,wrappy,write-file-atomic,ws,xdg-basedir,xtend,y18n,yallist,yargs,yargs-parser,yocto-queue,zip-stream,@apidevtools,@colors,@dabh,@electric-sql,@google-cloud,@googleapis,@grpc,@isaacs,@js-sdsl,@jsdevtools,@npmcli,@opentelemetry,@pkgjs,@pnpm,@protobufjs,@sindresorhus,@tootallnate,@types +Installed ft@13.34.0 and packaged ft@13.34.0 +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Runtime binaries created. +/usr/local/bin/firebase +/usr/local/bin/firebase,/snapshot/firepit/firepit.js,--version +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /home/shridhar/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +ShellJSInternalError: ENOENT: no such file or directory, stat '/home/shridhar/.cache/firebase/runtime/node' \ No newline at end of file diff --git a/lib/application/authentication/authentication_bloc.dart b/lib/application/authentication/authentication_bloc.dart index 9ab04b34..684c8268 100644 --- a/lib/application/authentication/authentication_bloc.dart +++ b/lib/application/authentication/authentication_bloc.dart @@ -44,13 +44,20 @@ class AuthenticationBloc _mapLoggedInToState( AuthenticationEvent event, Emitter emit) async { - final (userLoggedIn, user) = await _authRepository.getUser(); - - if (userLoggedIn && user != null) { - emit(Authenticated(user.toEntity())); - } else if (userLoggedIn && user == null) { - emit(OnboardingIncomplete()); - } else { + try { + await Future.delayed(const Duration(milliseconds: 500)); + final (userLoggedIn, user) = await _authRepository.getUser(); + log('User: $userLoggedIn, $user'); + if (userLoggedIn && user != null) { + emit(Uninitialized()); + emit(Authenticated(user.toEntity())); + } else if (userLoggedIn && user == null) { + emit(OnboardingIncomplete()); + } else { + emit(Unauthenticated()); + } + } catch (e) { + log('Error in _mapLoggedInToState: $e'); emit(Unauthenticated()); } } diff --git a/lib/application/profile/follow/follow_bloc.dart b/lib/application/profile/follow/follow_bloc.dart index fa7de9c3..e15c3053 100644 --- a/lib/application/profile/follow/follow_bloc.dart +++ b/lib/application/profile/follow/follow_bloc.dart @@ -5,14 +5,19 @@ import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:monumento/domain/entities/user_entity.dart'; import 'package:monumento/domain/repositories/social_repository.dart'; +import 'package:monumento/application/authentication/authentication_bloc.dart'; +import 'package:monumento/domain/repositories/authentication_repository.dart'; part 'follow_event.dart'; part 'follow_state.dart'; class FollowBloc extends Bloc { final SocialRepository _socialRepository; + final AuthenticationBloc _authenticationBloc; + final AuthenticationRepository _authenticationRepository; + bool _currentFollowStatus = false; - FollowBloc(this._socialRepository) : super(FollowInitial()) { + FollowBloc(this._socialRepository, this._authenticationBloc, this._authenticationRepository) : super(FollowInitial()) { on(_mapFollowUserToState); on(_mapUnfollowUserToState); on(_mapGetFollowStatusToState); @@ -23,10 +28,20 @@ class FollowBloc extends Bloc { try { emit(LoadingFollowState()); await _socialRepository.followUser(targetUser: event.targetUser); - add(GetFollowStatus(targetUser: event.targetUser)); + _currentFollowStatus = true; + emit(FollowStatusRetrieved(following: _currentFollowStatus)); + + // Update authentication state + _authenticationBloc.add(LoggedIn()); + + // Get the current user's following and followers lists + final (userLoggedIn, user) = await _authenticationRepository.getUser(); + if (userLoggedIn && user != null) { + add(LoadUser(following: user.following)); + add(LoadUser(following: user.followers)); + } } catch (e) { log('${e.toString()} follow'); - emit(FollowStateError(e.toString())); } } @@ -34,12 +49,21 @@ class FollowBloc extends Bloc { _mapUnfollowUserToState(UnfollowUser event, Emitter emit) async { try { emit(LoadingFollowState()); - await _socialRepository.unfollowUser(targetUser: event.targetUser); - add(GetFollowStatus(targetUser: event.targetUser)); + _currentFollowStatus = false; + emit(FollowStatusRetrieved(following: _currentFollowStatus)); + + // Update authentication state + _authenticationBloc.add(LoggedIn()); + + // Get the current user's following and followers lists + final (userLoggedIn, user) = await _authenticationRepository.getUser(); + if (userLoggedIn && user != null) { + add(LoadUser(following: user.following)); + add(LoadUser(following: user.followers)); + } } catch (e) { log('${e.toString()} unfollow'); - emit(FollowStateError(e.toString())); } } @@ -48,12 +72,11 @@ class FollowBloc extends Bloc { GetFollowStatus event, Emitter emit) async { try { emit(LoadingFollowState()); - bool following = + _currentFollowStatus = await _socialRepository.getFollowStatus(targetUser: event.targetUser); - emit(FollowStatusRetrieved(following: following)); + emit(FollowStatusRetrieved(following: _currentFollowStatus)); } catch (e) { log('${e.toString()} status'); - emit(FollowStateError(e.toString())); } } @@ -71,7 +94,6 @@ class FollowBloc extends Bloc { emit(LoadedFollowUserListState(userData: userDataEntity)); } catch (e) { log('${e.toString()} follow'); - emit(FollowUserListErrorState(message: e.toString())); } } diff --git a/lib/presentation/profile_screen/desktop/profile_screen_desktop.dart b/lib/presentation/profile_screen/desktop/profile_screen_desktop.dart index 766d308e..1443dfb0 100644 --- a/lib/presentation/profile_screen/desktop/profile_screen_desktop.dart +++ b/lib/presentation/profile_screen/desktop/profile_screen_desktop.dart @@ -5,6 +5,7 @@ import 'package:monumento/application/authentication/authentication_bloc.dart'; import 'package:monumento/application/popular_monuments/bookmark_monuments/bookmark_monuments_bloc.dart'; import 'package:monumento/application/profile/profile_posts/profile_posts_bloc.dart'; import 'package:monumento/domain/entities/post_entity.dart'; +import 'package:monumento/domain/entities/monument_entity.dart'; import 'package:monumento/presentation/notification/desktop/notification_view_desktop.dart'; import 'package:monumento/presentation/popular_monuments/desktop/monument_details_view_desktop.dart'; import 'package:monumento/presentation/profile_screen/desktop/widgets/user_details_card_widget.dart'; @@ -48,6 +49,13 @@ class _ProfileScreenDesktopState extends State { super.initState(); } + Future _refreshData() async { + // Reload user data and posts + locator().add(AppStarted()); + locator().add(const LoadInitialProfilePosts()); + locator().add(const GetBookmarkedMonuments()); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -94,146 +102,196 @@ class _ProfileScreenDesktopState extends State { ), ), ), - body: BlocBuilder( - bloc: locator(), - builder: (context, state) { - state as Authenticated; - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox( - height: 20, - ), - UserDetailsCardWidget( - isAccountOwner: true, - user: state.user, - onPostsTap: () { - _jumpToPage(0); - }, - onBookmarksTap: () { - _jumpToPage(1); - }, - currentPage: _currentPage, - ), - Expanded( - child: PageView( - controller: _pageController, - children: [ - BlocBuilder( - bloc: locator(), - builder: (context, postsState) { - if (postsState is InitialProfilePostsLoaded) { - posts = []; - posts.insertAll( - posts.length, - postsState.initialPosts - .where((e) => e.postType == 0)); - } - if (postsState is MoreProfilePostsLoaded) { - posts.insertAll(posts.length, - postsState.posts as Iterable); - } - return posts.isEmpty - ? const Center( - child: Text("No posts to display"), - ) - : GridView.builder( - padding: const EdgeInsets.symmetric( - horizontal: 40, - vertical: 20, - ), - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 4, - crossAxisSpacing: 20, - mainAxisSpacing: 20, + body: RefreshIndicator( + onRefresh: _refreshData, + color: AppColor.appPrimary, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: BlocBuilder( + bloc: locator(), + builder: (context, state) { + state as Authenticated; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 20, + ), + UserDetailsCardWidget( + isAccountOwner: true, + user: state.user, + onPostsTap: () { + _jumpToPage(0); + }, + onBookmarksTap: () { + _jumpToPage(1); + }, + currentPage: _currentPage, + ), + SizedBox( + height: MediaQuery.of(context).size.height - 200, + child: PageView( + controller: _pageController, + children: [ + BlocBuilder( + bloc: locator(), + builder: (context, state) { + if (state is LoadingInitialProfilePosts) { + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + AppColor.appPrimary, + ), ), - itemCount: posts.length, - itemBuilder: (context, index) { - return CachedNetworkImage( - imageUrl: posts[index].imageUrl ?? - defaultProfilePicture, - imageBuilder: (context, imageProvider) => - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - image: DecorationImage( - image: imageProvider, - fit: BoxFit.cover, - ), - ), - ), - ); - }, ); - }, - ), - BlocBuilder( - bloc: locator(), - builder: (context, state) { - if (state is BookmarkedMonumentsLoading) { - return const Center( - child: CircularProgressIndicator(), - ); - } else if (state is BookmarkedMonumentsLoaded) { - return GridView.builder( - padding: const EdgeInsets.symmetric( - horizontal: 40, - vertical: 20, - ), - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 20, - mainAxisSpacing: 20, - childAspectRatio: 2, - ), - itemCount: state.bookmarkedMonuments.length, - itemBuilder: (context, index) { - return InkWell( - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => - MonumentDetailsViewDesktop( - isBookmarked: true, - monument: - state.bookmarkedMonuments[index], + } + if (state is InitialProfilePostsLoaded) { + posts = state.initialPosts; + } + return posts.isEmpty + ? Center( + child: Text( + 'No posts yet', + style: AppTextStyles.s16( + color: AppColor.appSecondary, + fontType: FontType.MEDIUM, + isDesktop: true, ), ), - ); - }, - child: CachedNetworkImage( - imageUrl: - state.bookmarkedMonuments[index].imageUrl, - imageBuilder: (context, imageProvider) => - Container( - width: 600, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - image: DecorationImage( - image: imageProvider, - fit: BoxFit.cover, - ), + ) + : GridView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 40, + vertical: 20, ), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + crossAxisSpacing: 20, + mainAxisSpacing: 20, + ), + itemCount: posts.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + MonumentDetailsViewDesktop( + monument: MonumentEntity( + id: posts[index].postId, + name: posts[index].title, + city: posts[index].location ?? '', + country: '', + imageUrl: posts[index].imageUrl ?? defaultProfilePicture, + image_1x1_: '', + wiki: '', + rating: 0, + coordinates: [0, 0], + wikiPageId: '', + ), + ), + ), + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(12), + image: DecorationImage( + image: NetworkImage( + posts[index].imageUrl ?? + defaultProfilePicture, + ), + fit: BoxFit.cover, + ), + ), + ), + ); + }, + ); + }, + ), + BlocBuilder( + bloc: locator(), + builder: (context, state) { + if (state is BookmarkedMonumentsLoading) { + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + AppColor.appPrimary, ), ), ); - }, - ); - } else { - return const Center( - child: Text("No bookmarks to display"), - ); - } - }, + } + if (state is BookmarkedMonumentsLoaded) { + return state.bookmarkedMonuments.isEmpty + ? Center( + child: Text( + 'No bookmarks yet', + style: AppTextStyles.s16( + color: AppColor.appSecondary, + fontType: FontType.MEDIUM, + isDesktop: true, + ), + ), + ) + : GridView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 40, + vertical: 20, + ), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + crossAxisSpacing: 20, + mainAxisSpacing: 20, + ), + itemCount: state.bookmarkedMonuments.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + MonumentDetailsViewDesktop( + monument: state.bookmarkedMonuments[index], + ), + ), + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(12), + image: DecorationImage( + image: NetworkImage( + state.bookmarkedMonuments[index] + .imageUrl ?? + defaultProfilePicture, + ), + fit: BoxFit.cover, + ), + ), + ), + ); + }, + ); + } + return const SizedBox(); + }, + ), + ], ), - ], - ), - ), - ], - ); - }, + ), + ], + ); + }, + ), + ), ), ); } diff --git a/lib/presentation/profile_screen/mobile/profile_screen_mobile.dart b/lib/presentation/profile_screen/mobile/profile_screen_mobile.dart index f3279343..0634c670 100644 --- a/lib/presentation/profile_screen/mobile/profile_screen_mobile.dart +++ b/lib/presentation/profile_screen/mobile/profile_screen_mobile.dart @@ -4,6 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:monumento/application/authentication/authentication_bloc.dart'; +import 'package:monumento/application/profile/profile_posts/profile_posts_bloc.dart'; import 'package:monumento/gen/assets.gen.dart'; import 'package:monumento/presentation/notification/desktop/notification_view_desktop.dart'; import 'package:monumento/presentation/profile_screen/mobile/user_connections_screen.dart'; @@ -33,206 +34,232 @@ class _ProfileScreenMobileState extends State super.initState(); } + Future _refreshData() async { + // Reload user data and posts + locator().add(AppStarted()); + locator().add(LoggedIn()); + locator().add(const LoadInitialProfilePosts()); + } + @override Widget build(BuildContext context) { bool isAccountOwner = true; return Scaffold( - appBar: CustomMobileAppBar( - logoPath: Assets.mobile.logoProfile.path, - actions: [ - IconButton( - onPressed: () async { - await Navigator.push( - context, - MaterialPageRoute( - builder: (ctx) { - return const NotificationViewDesktop(); - }, - ), - ); - }, - icon: const Icon( - Icons.notifications_outlined, - color: AppColor.appBlack, - ), + appBar: CustomMobileAppBar( + logoPath: Assets.mobile.logoProfile.path, + actions: [ + IconButton( + onPressed: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (ctx) { + return const NotificationViewDesktop(); + }, + ), + ); + }, + icon: const Icon( + Icons.notifications_outlined, + color: AppColor.appBlack, ), - IconButton( - onPressed: () { - SettingsBottomSheet().settingsBottomSheet(context); - }, - icon: const Icon( - Icons.settings_outlined, - color: AppColor.appBlack, - ), + ), + IconButton( + onPressed: () { + SettingsBottomSheet().settingsBottomSheet(context); + }, + icon: const Icon( + Icons.settings_outlined, + color: AppColor.appBlack, ), - ], - ), - body: BlocBuilder( - bloc: locator(), - builder: (context, state) { - state as Authenticated; - log(state.user.posts.length.toString()); - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20.0, vertical: 30), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + ), + ], + ), + body: RefreshIndicator( + onRefresh: _refreshData, + color: AppColor.appPrimary, + child: BlocBuilder( + bloc: locator(), + builder: (context, state) { + if (state is! Authenticated) { + return const Center(child: CircularProgressIndicator()); + } + return SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20.0, + vertical: 30, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + CircleAvatar( + radius: 40, + backgroundImage: CachedNetworkImageProvider( + state.user.profilePictureUrl ?? + defaultProfilePicture, + ), + ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - CircleAvatar( - radius: 40, - backgroundImage: - CachedNetworkImageProvider( - state.user.profilePictureUrl ?? - defaultProfilePicture, - )), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: () { + _tabController.animateTo(0); + }, + child: Column( children: [ - InkWell( - onTap: () { - _tabController.animateTo(0); - }, - child: Column( - children: [ - Text( - state.user.posts.length - .toString(), - style: AppTextStyles.s18( - color: AppColor.appBlack, - fontType: FontType.SEMI_BOLD, - ), - ), - const SizedBox( - height: 10, - ), - Text("Posts", - style: AppTextStyles.s12( - color: AppColor.appGrey, - fontType: FontType.MEDIUM, - )), - ], + Text( + state.user.posts.length.toString(), + style: AppTextStyles.s16( + color: AppColor.appBlack, + fontType: FontType.MEDIUM, ), ), - const SizedBox(width: 20), - InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const UserConnectionsScreen( - index: 0, - )), - ); - }, - child: Column( - children: [ - Text( - state.user.followers.length - .toString(), - style: AppTextStyles.s18( - color: AppColor.appBlack, - fontType: FontType.SEMI_BOLD, - ), - ), - const SizedBox( - height: 10, - ), - Text("Followers", - style: AppTextStyles.s12( - color: AppColor.appGrey, - fontType: FontType.MEDIUM, - )), - ], + const SizedBox( + height: 2, + ), + Text( + 'Posts', + style: AppTextStyles.s12( + color: AppColor.appGrey, + fontType: FontType.REGULAR, ), ), - const SizedBox(width: 20), - InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const UserConnectionsScreen( - index: 1, - )), - ); - }, - child: Column( - children: [ - Text( - state.user.following.length - .toString(), - style: AppTextStyles.s18( - color: AppColor.appBlack, - fontType: FontType.SEMI_BOLD, - ), - ), - const SizedBox( - height: 10, - ), - Text("Following", - style: AppTextStyles.s12( - color: AppColor.appGrey, - fontType: FontType.MEDIUM, - )), - ], + ], + ), + ), + const SizedBox( + width: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + UserConnectionsScreen( + index: 0, + ), + ), + ); + }, + child: Column( + children: [ + Text( + state.user.followers.length.toString(), + style: AppTextStyles.s16( + color: AppColor.appBlack, + fontType: FontType.MEDIUM, + ), + ), + const SizedBox( + height: 2, + ), + Text( + 'Followers', + style: AppTextStyles.s12( + color: AppColor.appGrey, + fontType: FontType.REGULAR, ), - ) + ), ], - ) - ]), - const SizedBox( - height: 10, - ), - Text( - state.user.name, - style: AppTextStyles.s16( - color: AppColor.appBlack, - fontType: FontType.MEDIUM, - ), - ), - const SizedBox( - height: 2, - ), - Text( - '@${state.user.username}', - style: AppTextStyles.s12( - color: AppColor.appLightGrey, - fontType: FontType.REGULAR, - ), - ), - const SizedBox( - height: 10, - ), - Text( - state.user.status, - style: AppTextStyles.s12( - color: AppColor.appGrey, - fontType: FontType.REGULAR, - ), + ), + ), + const SizedBox( + width: 20, + ), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + UserConnectionsScreen( + index: 1, + ), + ), + ); + }, + child: Column( + children: [ + Text( + state.user.following.length.toString(), + style: AppTextStyles.s16( + color: AppColor.appBlack, + fontType: FontType.MEDIUM, + ), + ), + const SizedBox( + height: 2, + ), + Text( + 'Following', + style: AppTextStyles.s12( + color: AppColor.appGrey, + fontType: FontType.REGULAR, + ), + ), + ], + ), + ), + ], ), ], - )), - FollowButton( - isAccountOwner: isAccountOwner, targetUser: state.user), - const Divider(thickness: 2), - ProfileTabsView( - tabController: _tabController, - ) - ], - ), - ); - })); + ), + const SizedBox( + height: 20, + ), + Text( + state.user.name, + style: AppTextStyles.s16( + color: AppColor.appBlack, + fontType: FontType.MEDIUM, + ), + ), + const SizedBox( + height: 2, + ), + Text( + '@${state.user.username}', + style: AppTextStyles.s12( + color: AppColor.appLightGrey, + fontType: FontType.REGULAR, + ), + ), + const SizedBox( + height: 10, + ), + Text( + state.user.status, + style: AppTextStyles.s12( + color: AppColor.appGrey, + fontType: FontType.REGULAR, + ), + ), + ], + ), + ), + FollowButton( + isAccountOwner: isAccountOwner, + targetUser: state.user), + const Divider(thickness: 2), + ProfileTabsView( + tabController: _tabController, + ) + ], + ), + ); + }, + ), + ), + ); } } diff --git a/lib/presentation/profile_screen/mobile/widgets/follow_button.dart b/lib/presentation/profile_screen/mobile/widgets/follow_button.dart index 717c3ec4..014d9fbf 100644 --- a/lib/presentation/profile_screen/mobile/widgets/follow_button.dart +++ b/lib/presentation/profile_screen/mobile/widgets/follow_button.dart @@ -7,50 +7,79 @@ import 'package:monumento/service_locator.dart'; import 'package:monumento/utils/app_colors.dart'; import 'package:monumento/utils/constants.dart'; -class FollowButton extends StatelessWidget { +class FollowButton extends StatefulWidget { final bool isAccountOwner; final UserEntity targetUser; const FollowButton( {super.key, required this.isAccountOwner, required this.targetUser}); + @override + State createState() => _FollowButtonState(); +} + +class _FollowButtonState extends State { + bool _isFollowing = false; + + @override + void initState() { + super.initState(); + // Initialize follow status + locator().add(GetFollowStatus(targetUser: widget.targetUser)); + } + @override Widget build(BuildContext context) { - return isAccountOwner + return widget.isAccountOwner ? const SizedBox() : BlocBuilder( bloc: locator(), builder: (context, state) { state as Authenticated; - return Center( - child: CustomElevatedButton( - onPressed: () { - if (targetUser.followers.contains(state.user.uid)) { - locator().add( - UnfollowUser( - targetUser: targetUser, + return BlocBuilder( + bloc: locator(), + builder: (context, followState) { + if (followState is FollowStatusRetrieved) { + _isFollowing = followState.following; + } else if (followState is LoadingFollowState) { + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + AppColor.appPrimary, ), - ); - } else { - locator().add( - FollowUser( - targetUser: targetUser, + ), + ); + } + + return Center( + child: CustomElevatedButton( + onPressed: () { + if (_isFollowing) { + locator().add( + UnfollowUser( + targetUser: widget.targetUser, + ), + ); + } else { + locator().add( + FollowUser( + targetUser: widget.targetUser, + ), + ); + } + }, + text: _isFollowing ? 'Following' : ' Follow ', + style: ElevatedButton.styleFrom( + minimumSize: Size(MediaQuery.sizeOf(context).width*2/3, 20), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), ), - ); - } - }, - text: targetUser.followers.contains(state.user.uid) - ? 'Following' - : ' Follow ', - style: ElevatedButton.styleFrom( - minimumSize:Size(MediaQuery.sizeOf(context).width*2/3, 20), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), + backgroundColor: AppColor.appPrimary, + padding: + const EdgeInsets.symmetric(vertical: 15, horizontal: 20), + ), ), - backgroundColor: AppColor.appPrimary, - padding: - const EdgeInsets.symmetric(vertical: 15, horizontal: 20), - ), - ), + ); + }, ); }, ); diff --git a/lib/service_locator.dart b/lib/service_locator.dart index d79650c5..1ef82ded 100644 --- a/lib/service_locator.dart +++ b/lib/service_locator.dart @@ -39,9 +39,11 @@ void setupLocator() { () => FirebaseMonumentRepository(locator())); // Register blocs - locator.registerLazySingleton(() => - AuthenticationBloc(locator()) - ..add(AppStarted())); + // Initialize AuthenticationBloc first + final authBloc = AuthenticationBloc(locator()); + authBloc.add(AppStarted()); + locator.registerSingleton(authBloc); + locator.registerLazySingleton(() => LoginRegisterBloc( locator(), locator(), @@ -57,7 +59,11 @@ void setupLocator() { () => RecommendedUsersBloc(locator())); locator.registerLazySingleton(() => NewPostBloc(locator())); - locator.registerLazySingleton(() => FollowBloc(locator())); + locator.registerLazySingleton(() => FollowBloc( + locator(), + locator(), + locator(), + )); locator.registerLazySingleton(() => ProfilePostsBloc( locator(), diff --git a/pubspec.lock b/pubspec.lock index 681c4f03..07c7c42b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + sha256: dc27559385e905ad30838356c5f5d574014ba39872d732111cd07ac0beff4c57 url: "https://pub.dev" source: hosted - version: "72.0.0" + version: "80.0.0" _flutterfire_internals: dependency: transitive description: @@ -17,19 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.53" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.2" analyzer: dependency: transitive description: name: analyzer - sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + sha256: "192d1c5b944e7e53b24b5586db760db934b177d4147c42fbca8c8c5f1eb8d11e" url: "https://pub.dev" source: hosted - version: "6.7.0" + version: "7.3.0" android_intent_plus: dependency: transitive description: @@ -58,10 +53,10 @@ packages: dependency: transitive description: name: archive - sha256: "0c64e928dcbefddecd234205422bcfc2b5e6d31be0b86fef0d0dd48d7b4c9742" + sha256: "7dcbd0f87fe5f61cb28da39a1a8b70dbc106e2fe0516f7836eb7bb2948481a12" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.5" args: dependency: transitive description: @@ -98,50 +93,50 @@ packages: dependency: transitive description: name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" build_daemon: dependency: transitive description: name: build_daemon - sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.4" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.4" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" url: "https://pub.dev" source: hosted - version: "2.4.13" + version: "2.4.15" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" url: "https://pub.dev" source: hosted - version: "7.3.2" + version: "8.0.0" built_collection: dependency: transitive description: @@ -258,10 +253,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" color: dependency: transitive description: @@ -314,10 +309,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac" url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "3.0.1" dartx: dependency: transitive description: @@ -342,22 +337,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" - device_frame: - dependency: transitive - description: - name: device_frame - sha256: d031a06f5d6f4750009672db98a5aa1536aa4a231713852469ce394779a23d75 - url: "https://pub.dev" - source: hosted - version: "1.2.0" - device_preview: - dependency: "direct main" - description: - name: device_preview - sha256: a694acdd3894b4c7d600f4ee413afc4ff917f76026b97ab06575fe886429ef19 - url: "https://pub.dev" - source: hosted - version: "1.2.0" easy_sidemenu: dependency: "direct main" description: @@ -620,10 +599,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "1c2b787f99bdca1f3718543f81d38aa1b124817dfeb9fb196201bea85b6134bf" + sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3" url: "https://pub.dev" source: hosted - version: "2.0.26" + version: "2.0.27" flutter_screenutil: dependency: "direct main" description: @@ -694,50 +673,50 @@ packages: dependency: "direct main" description: name: geolocator - sha256: d2ec66329cab29cb297d51d96c067d457ca519dca8589665fa0b82ebacb7dbe4 + sha256: f62bcd90459e63210bbf9c35deb6a51c521f992a78de19a1fe5c11704f9530e2 url: "https://pub.dev" source: hosted - version: "13.0.2" + version: "13.0.4" geolocator_android: dependency: transitive description: name: geolocator_android - sha256: "7aefc530db47d90d0580b552df3242440a10fe60814496a979aa67aa98b1fd47" + sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d url: "https://pub.dev" source: hosted - version: "4.6.1" + version: "4.6.2" geolocator_apple: dependency: transitive description: name: geolocator_apple - sha256: c4ecead17985ede9634f21500072edfcb3dba0ef7b97f8d7bc556d2d722b3ba3 + sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22 url: "https://pub.dev" source: hosted - version: "2.3.9" + version: "2.3.13" geolocator_platform_interface: dependency: transitive description: name: geolocator_platform_interface - sha256: "386ce3d9cce47838355000070b1d0b13efb5bc430f8ecda7e9238c8409ace012" + sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "4.2.6" geolocator_web: dependency: transitive description: name: geolocator_web - sha256: "2ed69328e05cd94e7eb48bb0535f5fc0c0c44d1c4fa1e9737267484d05c29b5e" + sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 url: "https://pub.dev" source: hosted - version: "4.1.1" + version: "4.1.3" geolocator_windows: dependency: transitive description: name: geolocator_windows - sha256: "53da08937d07c24b0d9952eb57a3b474e29aae2abf9dd717f7e1230995f13f0e" + sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" url: "https://pub.dev" source: hosted - version: "0.2.3" + version: "0.2.5" get_it: dependency: "direct main" description: @@ -798,18 +777,18 @@ packages: dependency: "direct main" description: name: google_sign_in - sha256: fad6ddc80c427b0bba705f2116204ce1173e09cf299f85e053d57a55e5b2dd56 + sha256: d0a2c3bcb06e607bb11e4daca48bd4b6120f0bbc4015ccebbe757d24ea60ed2a url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" google_sign_in_android: dependency: transitive description: name: google_sign_in_android - sha256: "7af72e5502c313865c729223b60e8ae7bce0a1011b250c24edcf30d3d7032748" + sha256: "4e52c64366bdb3fe758f683b088ee514cc7a95e69c52b5ee9fc5919e1683d21b" url: "https://pub.dev" source: hosted - version: "6.1.35" + version: "6.2.0" google_sign_in_ios: dependency: transitive description: @@ -878,18 +857,18 @@ packages: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" image: dependency: transitive description: name: image - sha256: "13d3349ace88f12f4a0d175eb5c12dcdd39d35c4c109a8a13dfeb6d0bd9e31c3" + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" url: "https://pub.dev" source: hosted - version: "4.5.3" + version: "4.5.4" image_cropper: dependency: "direct main" description: @@ -926,10 +905,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: "82652a75e3dd667a91187769a6a2cc81bd8c111bbead698d8e938d2b63e5e89a" + sha256: "8bd392ba8b0c8957a157ae0dc9fcf48c58e6c20908d5880aea1d79734df090e9" url: "https://pub.dev" source: hosted - version: "0.8.12+21" + version: "0.8.12+22" image_picker_for_web: dependency: transitive description: @@ -950,10 +929,10 @@ packages: dependency: transitive description: name: image_picker_linux - sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" url: "https://pub.dev" source: hosted - version: "0.2.1+1" + version: "0.2.1+2" image_picker_macos: dependency: transitive description: @@ -1022,26 +1001,26 @@ packages: dependency: "direct main" description: name: json_serializable - sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c + sha256: "81f04dee10969f89f604e1249382d46b97a1ccad53872875369622b5bfc9e58a" url: "https://pub.dev" source: hosted - version: "6.9.0" + version: "6.9.4" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -1066,14 +1045,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" - url: "https://pub.dev" - source: hosted - version: "0.1.2-main.4" matcher: dependency: transitive description: @@ -1166,10 +1137,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" + sha256: "0ca7359dad67fd7063cb2892ab0c0737b2daafd807cf1acecd62374c8fae6c12" url: "https://pub.dev" source: hosted - version: "2.2.15" + version: "2.2.16" path_provider_foundation: dependency: transitive description: @@ -1246,10 +1217,10 @@ packages: dependency: transitive description: name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + sha256: "489024f942069c2920c844ee18bb3d467c69e48955a4f32d1677f71be103e310" url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.4" pub_semver: dependency: transitive description: @@ -1262,10 +1233,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" responsive_framework: dependency: "direct main" description: @@ -1286,18 +1257,18 @@ packages: dependency: transitive description: name: shared_preferences - sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "9f9f3d372d4304723e6136663bb291c0b93f5e4c8a4a6314347f481a33bda2b1" + sha256: "3ec7210872c4ba945e3244982918e502fa2bfb5230dff6832459ca0e1879b7ad" url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.4.8" shared_preferences_foundation: dependency: transitive description: @@ -1342,31 +1313,31 @@ packages: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_gen: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "2.0.0" source_helper: dependency: transitive description: @@ -1435,10 +1406,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -1459,10 +1430,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" synchronized: dependency: transitive description: @@ -1483,10 +1454,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" time: dependency: transitive description: @@ -1539,10 +1510,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" + sha256: "1d0eae19bd7606ef60fe69ef3b312a437a16549476c42321d5dc1506c9ca3bf4" url: "https://pub.dev" source: hosted - version: "6.3.14" + version: "6.3.15" url_launcher_ios: dependency: transitive description: @@ -1579,10 +1550,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.0" url_launcher_windows: dependency: transitive description: @@ -1635,10 +1606,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.0" watcher: dependency: transitive description: @@ -1683,10 +1654,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "512c26ccc5b8a571fd5d13ec994b7509f142ff6faf85835e243dde3538fdc713" + sha256: e09150b28a07933839adef0e4a088bb43e8c8d9e6b93025b01882d4067a58ab0 url: "https://pub.dev" source: hosted - version: "4.3.2" + version: "4.3.4" webview_flutter_platform_interface: dependency: transitive description: @@ -1744,5 +1715,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.6.0 <4.0.0" + flutter: ">=3.27.0"