Using the same cubit instance in multiple list tiles

41 views Asked by At

I'm using cubit to trigger action (sync to backend) to the current list tile, my problem is that when I trigger the sync, all unsynced tiles get synced, I want to trigger the action on the current tile only. here's the code for the list tile and where I'm using it. work_session_listing_page.dart:

BlocConsumer<WorkSessionListingCubit, WorkSessionListingState>(
      listener: (context, state) {
        state.whenOrNull(
          deleted: () async {
            print("SESSION DELETED");
            await _animateAndReset();
          },
          error: (errorMessage) => showSnackBar(context, errorMessage),
        );
      },
      builder: (context, state) {
        return state.maybeMap(
          orElse: () => _workSessionListingCubit.workSessions.isEmpty
              ? NoResultsWidget(
                  text: LocaleKeys.work_list_page_no_results.tr(),
                  description: LocaleKeys.you_can_create_work_sessions_from_the_home_screen.tr(),
                )
              : ListView.builder(
                  itemCount: _workSessionListingCubit.workSessions.length,
                  itemBuilder: (context, index) {
                    return SessionListTile(
                      animationController: _animationController,
                      session: _workSessionListingCubit.workSessions[index],
                      workSessionListingCubit: _workSessionListingCubit,
                    );
                  },
                ),
          loading: (state) => const Center(
            child: CircularProgressIndicator(),
          ),
        );
      },
    ),

session_list_tile.dart:

      @override
  Widget build(BuildContext context) {
    final dateFormat = DateFormat.yMMMMEEEEd();
    return BlocListener<ReportCubit, ReportState>(
      listener: (context, state) {
        state.whenOrNull(
          loaded: (reportData) {
            if (reportData.sessionPath == widget.session.path)
              Navigator.pushNamed(context, WergoRouter.report, arguments: [widget.session, reportData]);
          },
        );
      },
      child: BlocListener<TnoReportCubit, TnoReportState>(
        listener: (context, state) {
          state.whenOrNull(
            loaded: (report) {
              EasyLoading.dismiss();
              if (report.sessionId == widget.session.remoteSessionId)
                Navigator.pushNamed(context, WergoRouter.tnoReport, arguments: [report, widget.session]);
            },
            loading: () {
              // code
            },
            inProgress: (text) {
              //more code
            },
            error: (errorMessage, sessionId) {
              // more code
            },
          );
        },
        child: BlocProvider.value(
          value: _sessionSyncCubit,
          child: Container(
            margin: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
            padding: EdgeInsets.all(10.sp),
            height: 65.h,
            decoration: BoxDecoration(
              color: DevelColors.cardGray,
              borderRadius: BorderRadius.circular(8.r),
            ),
            child: Row(
              children: [
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(
                      height: 10,
                    ),
                    Text(
                      '${widget.session.firstName} ${widget.session.lastName}',
                     
                    ),
                    const Spacer(),
                    Text(
                      widget.session.workplace,
                      
                    ),
                  ],
                ),
                const Spacer(),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    Row(
                      children: [
                        if (!widget.session.isSynced)
                          BlocConsumer<UserProfileCubit, UserProfileState>(
                            listener: (context, state) {
                              state.whenOrNull(
                                success: (profile) async =>
                                    _sessionSyncCubit.syncSession(widget.session.copyWith(workerProfileId: profile.id)),
                                
                            },
                            builder: (context, state) => state.maybeWhen(
                              loading: () => Text(
                                LocaleKeys.creating_worker.tr(),
                                style: DevelStyles.hintTextStyle12,
                              ),
                              orElse: () => BlocConsumer<SessionSyncCubit, SessionSyncState>(
                                bloc: _sessionSyncCubit,
                                listener: (context, state) {
                                  state.whenOrNull(
                                    synced: () {
                                      Future.delayed(
                                        const Duration(seconds: 1),
                                        () {
                                          setState(() {
                                            opacity = 0;
                                          });
                                        },
                                      );
                                    },
                                  );
                                },
                                builder: (context, state) {
                                  return state.maybeWhen(
                                    syncStepUpdated: (step) => Text(
                                      step.toString(),
                                      style: DevelStyles.hintTextStyle12,
                                    ),
                                    synced: () {
                                      return AnimatedOpacity(
                                        duration: const Duration(seconds: 1),
                                        opacity: opacity,
                                        child: const Icon(Icons.file_download_done, color: DevelColors.blueConnected),
                                      );
                                    },
                                    orElse: () => GestureDetector(
                                      onTap: () async {
                                        if (context.read<InternetCubit>().hasInternet) {
                                          if (widget.session.workerProfileId == null) {
                                            final user = CreateProfileData.fromWorkSession(widget.session);
                                            await _userProfileCubit.createUserProfile(
                                              user: user,
                                              orgId: _userCubit.user.organization!.id!,
                                              userId: _userCubit.user.id,
                                            );
                                          } else {
                                            _sessionSyncCubit.syncSession(widget.session);
                                          }
                                        } else {
                                          if (mounted)
                                            WergoDialog(
                                              context,
                                              mainButton: TextButton(
                                                style: const ButtonStyle(
                                                  splashFactory: NoSplash.splashFactory,
                                                  overlayColor: MaterialStatePropertyAll(Colors.transparent),
                                                ),
                                                onPressed: () {
                                                  Navigator.of(context).pop();
                                                },
                                                child: Text(
                                                  LocaleKeys.close.tr(),
                                                  style: DevelStyles.actionButtonStyle14.copyWith(
                                                    fontWeight: FontWeight.w600,
                                                    color: DevelColors.buttonBlue,
                                                    fontSize: 14.sp,
                                                  ),
                                                ),
                                              ),
                                              title: LocaleKeys.an_error_occured.tr(),
                                              description: LocaleKeys.no_internet_connection.tr(),
                                              header: Lottie.asset(
                                                'assets/lotties/error_sad_face.json',
                                                height: 30.h,
                                                width: 30.h,
                                                controller: _animationController,
                                                onLoaded: (composition) async {
                                                  _animationController
                                                    ..forward()
                                                    ..repeat();
                                                },
                                              ),
                                            ).show();
                                        }
                                      },
                                      child: const Icon(
                                        Icons.cloud_off_rounded,
                                        color: DevelColors.hintTextColor,
                                      ),
                                    ),
                                  );
                                },
                              ),
                            ),
                          ),
                        PopupMenuButton(
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8.r),
                          ),
                          padding: EdgeInsets.zero,
                          onSelected: (value) async {
                            switch (value) {
                              case 'report':
                                context.read<ReportCubit>().getReportData(widget.session);
                                break;
                              case 'sync':
                                if (!widget.session.isSynced) {
                                  final session = widget.session;
                                  if (context.read<InternetCubit>().hasInternet) {
                                    if (widget.session.workerProfileId == null) {
                                      final user = CreateProfileData.fromWorkSession(widget.session);
                                      await _userProfileCubit.createUserProfile(
                                        user: user,
                                        orgId: _userCubit.user.organization!.id!,
                                        userId: _userCubit.user.id,
                                      );
                                    } else {
                                      _sessionSyncCubit.syncSession(
                                          session.copyWith(workerProfileId: widget.session.remoteSessionId));
                                    }
                                  }
                                }
                                break;
                              case 'tno':
                                if (!widget.session.isSynced) {
                                  final session = widget.session;
                                  if (context.read<InternetCubit>().hasInternet) {
                                    if (widget.session.workerProfileId == null) {
                                      final user = CreateProfileData.fromWorkSession(widget.session);
                                      await _userProfileCubit.createUserProfile(
                                        user: user,
                                        orgId: _userCubit.user.organization!.id!,
                                        userId: _userCubit.user.id,
                                      );
                                    } else {
                                      _sessionSyncCubit.syncSession(
                                          session.copyWith(workerProfileId: widget.session.remoteSessionId));
                                    }
                                  }
                                }
                                _tnoReportCubit.getTNOReport(widget.session.remoteSessionId!);
                                break;
                              case 'share':
                                showDialogExportOptionsMenu(
                                  context,
                                  saveToPhoneFunction: () async {
                                    await locator<ExportWorSessionUseCase>()
                                        .call(session: widget.session, exportLocally: true);
                                    if (mounted) Navigator.of(context, rootNavigator: true).pop();
                                  },
                                  shareFunction: () async {
                                    await locator<ExportWorSessionUseCase>().call(session: widget.session);
                                    if (mounted) Navigator.of(context, rootNavigator: true).pop();
                                  },
                                  title: "${LocaleKeys.report_page_pop_up_menu_title.tr()} ZIP",
                                ).show();
                                break;
                              case 'delete':
                                WergoDialog(
                                  context,
                                  mainButton: TextButton(
                                    style: const ButtonStyle(
                                      splashFactory: NoSplash.splashFactory,
                                      overlayColor: MaterialStatePropertyAll(Colors.transparent),
                                    ),
                                    onPressed: () async {
                                      await _workSessionListingCubit.deleteSession(widget.session.path);
                                    },
                                    child: Text(
                                      LocaleKeys.delete.tr(),
                                      style: DevelStyles.actionButtonStyle14.copyWith(
                                        fontWeight: FontWeight.w600,
                                        color: DevelColors.redColor,
                                        fontSize: 14.sp,
                                      ),
                                    ),
                                  ),
                                  title: 'worksession is going to be deleted',
                                  description:
                                      "Are you sure to delete the selected work session and all it's data from local device. action can not be reverted",
                                  header: Lottie.asset(
                                    "assets/lotties/deletion.json",
                                    controller: widget.animationController,
                                    height: 40.h,
                                    width: 40.h,
                                  ),
                                  secondaryButton: TextButton(
                                    style: const ButtonStyle(
                                      splashFactory: NoSplash.splashFactory,
                                      overlayColor: MaterialStatePropertyAll(Colors.transparent),
                                    ),
                                    onPressed: () {
                                      Navigator.pop(context);
                                    },
                                    child: Text(
                                      LocaleKeys.login_cancel_button.tr(),
                                      style: DevelStyles.actionButtonStyle14.copyWith(
                                          fontWeight: FontWeight.w600, color: Colors.black45, fontSize: 14.sp),
                                    ),
                                  ),
                                ).show();
                                break;
                              default:
                                break;
                            }
                          },
                          itemBuilder: (context) {
                            return [
                              const PopupMenuItem(
                                value: 'report',
                                child: Text(
                                  "Report",
                                  style: DevelStyles.popUpMenuItemStyle14,
                                ),
                              ),
                              PopupMenuItem(
                                value: 'sync',
                                child: Text(
                                  "Sync Session",
                                  style: !widget.session.isSynced
                                      ? DevelStyles.popUpMenuItemStyle14
                                      : DevelStyles.popUpMenuItemStyle14.copyWith(color: Colors.black45),
                                ),
                              ),
                              const PopupMenuItem(
                                value: 'tno',
                                child: Text(
                                  "Static & Dynamic analysis",
                                  style: DevelStyles.popUpMenuItemStyle14,
                                ),
                              ),
                              const PopupMenuItem(
                                value: 'share',
                                child: Text(
                                  "Share",
                                  style: DevelStyles.popUpMenuItemStyle14,
                                ),
                              ),
                              PopupMenuItem(
                                value: 'delete',
                                child: Text(
                                  LocaleKeys.delete.tr(),
                                  style: DevelStyles.popUpDeleteMenuStyle14,
                                ),
                              ),
                            ];
                          },
                        ),
                      ],
                    ),
                    const Spacer(),
                    Text(
                      dateFormat.format(widget.session.startedAt),
                      style: const TextStyle(
                        color: DevelColors.grayTextColor,
                        fontSize: 13,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
1

There are 1 answers

0
Hamed On

You can move the sync action to the SessionListTile widget. This way, each tile will have its sync action.

First of all, remove the BlocListener from ReportCubit and TnoReportCubit, then add a new method in SessionListTile to handle the sync action:

void syncSession() =>
  _sessionSyncCubit.syncSession(
    widget.session.copyWith(workerProfileId: widget.session.workerProfileId)
  );

Call this method in the onTap callback of the ListTile:

ListTile(
  onTap: syncSession,
  // ...
)