| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  | import 'package:appflowy/generated/locale_keys.g.dart'; | 
					
						
							| 
									
										
										
										
											2024-01-05 17:30:54 +08:00
										 |  |  | import 'package:appflowy/plugins/database/application/share_bloc.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  | import 'package:appflowy/startup/startup.dart'; | 
					
						
							| 
									
										
										
										
											2023-09-04 17:28:19 +08:00
										 |  |  | import 'package:appflowy/util/string_extension.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  | import 'package:appflowy/workspace/application/view/view_listener.dart'; | 
					
						
							|  |  |  | import 'package:appflowy/workspace/presentation/home/toast.dart'; | 
					
						
							|  |  |  | import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; | 
					
						
							| 
									
										
										
										
											2023-09-04 17:28:19 +08:00
										 |  |  | import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; | 
					
						
							| 
									
										
										
										
											2023-12-31 07:29:40 +08:00
										 |  |  | import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  | import 'package:appflowy_popover/appflowy_popover.dart'; | 
					
						
							|  |  |  | import 'package:easy_localization/easy_localization.dart'; | 
					
						
							|  |  |  | import 'package:flowy_infra/file_picker/file_picker_service.dart'; | 
					
						
							|  |  |  | import 'package:flowy_infra_ui/widget/rounded_button.dart'; | 
					
						
							| 
									
										
										
										
											2024-05-27 08:51:49 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  | import 'package:flutter_bloc/flutter_bloc.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DatabaseShareButton extends StatelessWidget { | 
					
						
							|  |  |  |   const DatabaseShareButton({ | 
					
						
							|  |  |  |     super.key, | 
					
						
							|  |  |  |     required this.view, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final ViewPB view; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return BlocProvider( | 
					
						
							|  |  |  |       create: (context) => DatabaseShareBloc(view: view), | 
					
						
							|  |  |  |       child: BlocListener<DatabaseShareBloc, DatabaseShareState>( | 
					
						
							|  |  |  |         listener: (context, state) { | 
					
						
							|  |  |  |           state.mapOrNull( | 
					
						
							|  |  |  |             finish: (state) { | 
					
						
							|  |  |  |               state.successOrFail.fold( | 
					
						
							|  |  |  |                 (data) => _handleExportData(context), | 
					
						
							|  |  |  |                 _handleExportError, | 
					
						
							|  |  |  |               ); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           ); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         child: BlocBuilder<DatabaseShareBloc, DatabaseShareState>( | 
					
						
							| 
									
										
										
										
											2024-05-27 08:51:49 +08:00
										 |  |  |           builder: (context, state) => IntrinsicWidth( | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  |             child: DatabaseShareActionList(view: view), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void _handleExportData(BuildContext context) { | 
					
						
							|  |  |  |     showSnackBarMessage( | 
					
						
							|  |  |  |       context, | 
					
						
							|  |  |  |       LocaleKeys.settings_files_exportFileSuccess.tr(), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void _handleExportError(FlowyError error) { | 
					
						
							|  |  |  |     showMessageToast(error.msg); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DatabaseShareActionList extends StatefulWidget { | 
					
						
							|  |  |  |   const DatabaseShareActionList({ | 
					
						
							|  |  |  |     super.key, | 
					
						
							|  |  |  |     required this.view, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final ViewPB view; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<DatabaseShareActionList> createState() => | 
					
						
							|  |  |  |       DatabaseShareActionListState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @visibleForTesting | 
					
						
							|  |  |  | class DatabaseShareActionListState extends State<DatabaseShareActionList> { | 
					
						
							|  |  |  |   late String name; | 
					
						
							|  |  |  |   late final ViewListener viewListener = ViewListener(viewId: widget.view.id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  |     listenOnViewUpdated(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     viewListener.stop(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final databaseShareBloc = context.read<DatabaseShareBloc>(); | 
					
						
							|  |  |  |     return PopoverActionList<ShareActionWrapper>( | 
					
						
							|  |  |  |       direction: PopoverDirection.bottomWithCenterAligned, | 
					
						
							|  |  |  |       offset: const Offset(0, 8), | 
					
						
							|  |  |  |       actions: ShareAction.values | 
					
						
							|  |  |  |           .map((action) => ShareActionWrapper(action)) | 
					
						
							|  |  |  |           .toList(), | 
					
						
							| 
									
										
										
										
											2024-02-25 21:32:44 +01:00
										 |  |  |       buildChild: (controller) => Listener( | 
					
						
							|  |  |  |         onPointerDown: (_) => controller.show(), | 
					
						
							|  |  |  |         child: RoundedTextButton( | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  |           title: LocaleKeys.shareAction_buttonText.tr(), | 
					
						
							| 
									
										
										
										
											2024-05-27 08:51:49 +08:00
										 |  |  |           padding: const EdgeInsets.symmetric(horizontal: 12.0), | 
					
						
							|  |  |  |           fontSize: 14.0, | 
					
						
							| 
									
										
										
										
											2023-11-03 12:09:12 -07:00
										 |  |  |           textColor: Theme.of(context).colorScheme.onPrimary, | 
					
						
							| 
									
										
										
										
											2024-02-25 21:32:44 +01:00
										 |  |  |           onPressed: () {}, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  |       onSelected: (action, controller) async { | 
					
						
							|  |  |  |         switch (action.inner) { | 
					
						
							|  |  |  |           case ShareAction.csv: | 
					
						
							|  |  |  |             final exportPath = await getIt<FilePickerService>().saveFile( | 
					
						
							|  |  |  |               dialogTitle: '', | 
					
						
							| 
									
										
										
										
											2023-09-04 17:28:19 +08:00
										 |  |  |               fileName: '${name.toFileName()}.csv', | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  |             ); | 
					
						
							|  |  |  |             if (exportPath != null) { | 
					
						
							|  |  |  |               databaseShareBloc.add(DatabaseShareEvent.shareCSV(exportPath)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         controller.close(); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void listenOnViewUpdated() { | 
					
						
							|  |  |  |     name = widget.view.name; | 
					
						
							|  |  |  |     viewListener.start( | 
					
						
							|  |  |  |       onViewUpdated: (view) { | 
					
						
							|  |  |  |         name = view.name; | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum ShareAction { | 
					
						
							|  |  |  |   csv, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ShareActionWrapper extends ActionCell { | 
					
						
							|  |  |  |   ShareActionWrapper(this.inner); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-25 16:37:36 +01:00
										 |  |  |   final ShareAction inner; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-28 23:20:56 +08:00
										 |  |  |   Widget? icon(Color iconColor) => null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   String get name { | 
					
						
							|  |  |  |     switch (inner) { | 
					
						
							|  |  |  |       case ShareAction.csv: | 
					
						
							|  |  |  |         return LocaleKeys.shareAction_csv.tr(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |