mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: show indicator when importing appflowy data (#4357)
* feat: show indicator when importing appflowy data * Update frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> * chore: fix analyzer * chore: fix test --------- Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com>
This commit is contained in:
parent
b1cc4e485b
commit
6e41359fc5
@ -34,6 +34,7 @@ typedef OnError = void Function(FlowyError);
|
||||
|
||||
@freezed
|
||||
class LoadingState with _$LoadingState {
|
||||
const factory LoadingState.idle() = _Idle;
|
||||
const factory LoadingState.loading() = _Loading;
|
||||
const factory LoadingState.finish(
|
||||
Either<Unit, FlowyError> successOrFail,
|
||||
|
@ -103,6 +103,7 @@ class BoardPage extends StatelessWidget {
|
||||
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
||||
),
|
||||
),
|
||||
idle: (_) => const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -131,6 +131,7 @@ class _GridPageState extends State<GridPage> {
|
||||
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
||||
),
|
||||
),
|
||||
idle: (_) => const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -97,6 +97,7 @@ class _MobileGridPageState extends State<MobileGridPage> {
|
||||
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
||||
),
|
||||
),
|
||||
idle: (_) => const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -14,17 +14,20 @@ class DeviceOrApplicationInfoTask extends LaunchTask {
|
||||
|
||||
@override
|
||||
Future<void> initialize(LaunchContext context) async {
|
||||
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
// Can't get the device info from test environment
|
||||
if (!context.env.isTest) {
|
||||
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
final androidInfo = await deviceInfoPlugin.androidInfo;
|
||||
androidSDKVersion = androidInfo.version.sdkInt;
|
||||
}
|
||||
if (Platform.isAndroid) {
|
||||
final androidInfo = await deviceInfoPlugin.androidInfo;
|
||||
androidSDKVersion = androidInfo.version.sdkInt;
|
||||
}
|
||||
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
applicationVersion = packageInfo.version;
|
||||
buildNumber = packageInfo.buildNumber;
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
applicationVersion = packageInfo.version;
|
||||
buildNumber = packageInfo.buildNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,11 @@ class EncryptSecretBloc extends Bloc<EncryptSecretEvent, EncryptSecretState> {
|
||||
bool isLoading() {
|
||||
final loadingState = state.loadingState;
|
||||
if (loadingState != null) {
|
||||
return loadingState.when(loading: () => true, finish: (_) => false);
|
||||
return loadingState.when(
|
||||
loading: () => true,
|
||||
finish: (_) => false,
|
||||
idle: () => false,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ class _EncryptSecretScreenState extends State<EncryptSecretScreen> {
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
),
|
||||
finish: (result) => const SizedBox.shrink(),
|
||||
idle: () => const SizedBox.shrink(),
|
||||
) ??
|
||||
const SizedBox.shrink();
|
||||
return Center(
|
||||
|
@ -70,6 +70,7 @@ class WorkspaceErrorScreen extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
},
|
||||
idle: () {},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy/plugins/database/application/defines.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
@ -9,39 +10,51 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'setting_file_importer_bloc.freezed.dart';
|
||||
|
||||
class SettingFileImporterBloc
|
||||
class SettingFileImportBloc
|
||||
extends Bloc<SettingFileImportEvent, SettingFileImportState> {
|
||||
SettingFileImporterBloc() : super(SettingFileImportState.initial()) {
|
||||
on<SettingFileImportEvent>((event, emit) async {
|
||||
await event.when(
|
||||
importAppFlowyDataFolder: (String path) async {
|
||||
final formattedDate =
|
||||
DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
|
||||
final payload = ImportAppFlowyDataPB.create()
|
||||
..path = path
|
||||
..importContainerName = "appflowy_import_$formattedDate";
|
||||
final result =
|
||||
await FolderEventImportAppFlowyDataFolder(payload).send();
|
||||
result.fold(
|
||||
(l) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
successOrFail: some(left(unit)),
|
||||
),
|
||||
);
|
||||
},
|
||||
(err) {
|
||||
Log.error(err);
|
||||
emit(
|
||||
state.copyWith(
|
||||
successOrFail: some(right(err)),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
SettingFileImportBloc() : super(SettingFileImportState.initial()) {
|
||||
on<SettingFileImportEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
importAppFlowyDataFolder: (String path) async {
|
||||
final formattedDate =
|
||||
DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
|
||||
final payload = ImportAppFlowyDataPB.create()
|
||||
..path = path
|
||||
..importContainerName = "appflowy_import_$formattedDate";
|
||||
emit(
|
||||
state.copyWith(loadingState: const LoadingState.loading()),
|
||||
);
|
||||
FolderEventImportAppFlowyDataFolder(payload).send().then((result) {
|
||||
if (!isClosed) {
|
||||
add(SettingFileImportEvent.finishImport(result));
|
||||
}
|
||||
});
|
||||
},
|
||||
finishImport: (result) {
|
||||
result.fold(
|
||||
(l) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
successOrFail: some(left(unit)),
|
||||
loadingState: LoadingState.finish(left(unit)),
|
||||
),
|
||||
);
|
||||
},
|
||||
(err) {
|
||||
Log.error(err);
|
||||
emit(
|
||||
state.copyWith(
|
||||
successOrFail: some(right(err)),
|
||||
loadingState: LoadingState.finish(right(err)),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,15 +62,20 @@ class SettingFileImporterBloc
|
||||
class SettingFileImportEvent with _$SettingFileImportEvent {
|
||||
const factory SettingFileImportEvent.importAppFlowyDataFolder(String path) =
|
||||
_ImportAppFlowyDataFolder;
|
||||
const factory SettingFileImportEvent.finishImport(
|
||||
Either<Unit, FlowyError> result,
|
||||
) = _ImportResult;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class SettingFileImportState with _$SettingFileImportState {
|
||||
const factory SettingFileImportState({
|
||||
required LoadingState loadingState,
|
||||
required Option<Either<Unit, FlowyError>> successOrFail,
|
||||
}) = _SettingFileImportState;
|
||||
|
||||
factory SettingFileImportState.initial() => SettingFileImportState(
|
||||
loadingState: const LoadingState.idle(),
|
||||
successOrFail: none(),
|
||||
);
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class _ImportAppFlowyDataState extends State<ImportAppFlowyData> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => SettingFileImporterBloc(),
|
||||
child: BlocListener<SettingFileImporterBloc, SettingFileImportState>(
|
||||
create: (context) => SettingFileImportBloc(),
|
||||
child: BlocListener<SettingFileImportBloc, SettingFileImportState>(
|
||||
listener: (context, state) {
|
||||
state.successOrFail.fold(
|
||||
() {},
|
||||
@ -47,7 +47,7 @@ class _ImportAppFlowyDataState extends State<ImportAppFlowyData> {
|
||||
},
|
||||
);
|
||||
},
|
||||
child: BlocBuilder<SettingFileImporterBloc, SettingFileImportState>(
|
||||
child: BlocBuilder<SettingFileImportBloc, SettingFileImportState>(
|
||||
builder: (context, state) {
|
||||
return const Column(
|
||||
children: [
|
||||
@ -120,24 +120,33 @@ class ImportAppFlowyDataButton extends StatefulWidget {
|
||||
class _ImportAppFlowyDataButtonState extends State<ImportAppFlowyDataButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 40,
|
||||
child: FlowyButton(
|
||||
text: FlowyText(LocaleKeys.settings_menu_importAppFlowyData.tr()),
|
||||
onTap: () async {
|
||||
final path = await getIt<FilePickerService>().getDirectoryPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
return BlocBuilder<SettingFileImportBloc, SettingFileImportState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 40,
|
||||
child: FlowyButton(
|
||||
text:
|
||||
FlowyText(LocaleKeys.settings_menu_importAppFlowyData.tr()),
|
||||
onTap: () async {
|
||||
final path =
|
||||
await getIt<FilePickerService>().getDirectoryPath();
|
||||
if (path == null || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
context
|
||||
.read<SettingFileImporterBloc>()
|
||||
.add(SettingFileImportEvent.importAppFlowyDataFolder(path));
|
||||
},
|
||||
),
|
||||
context.read<SettingFileImportBloc>().add(
|
||||
SettingFileImportEvent.importAppFlowyDataFolder(path),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (state.loadingState.isLoading())
|
||||
const LinearProgressIndicator(minHeight: 1),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ class EnableEncrypt extends StatelessWidget {
|
||||
final indicator = state.loadingState.when(
|
||||
loading: () => const CircularProgressIndicator.adaptive(),
|
||||
finish: (successOrFail) => const SizedBox.shrink(),
|
||||
idle: () => const SizedBox.shrink(),
|
||||
);
|
||||
|
||||
return Column(
|
||||
|
Loading…
Reference in New Issue
Block a user