mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add unwaited futures to analysis options (#4485)
This commit is contained in:
@ -49,6 +49,7 @@ linter:
|
|||||||
- always_declare_return_types
|
- always_declare_return_types
|
||||||
|
|
||||||
- sort_constructors_first
|
- sort_constructors_first
|
||||||
|
- unawaited_futures
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
@ -23,7 +23,7 @@ void main() {
|
|||||||
input: 'hello world',
|
input: 'hello world',
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: 'hello world',
|
content: 'hello world',
|
||||||
@ -56,13 +56,13 @@ void main() {
|
|||||||
cellIndex: 1,
|
cellIndex: 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: 'hello',
|
content: 'hello',
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: 'world',
|
content: 'world',
|
||||||
@ -95,7 +95,7 @@ void main() {
|
|||||||
input: '0.2',
|
input: '0.2',
|
||||||
);
|
);
|
||||||
// -1 -> -1
|
// -1 -> -1
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
fieldType: fieldType,
|
fieldType: fieldType,
|
||||||
content: '-1',
|
content: '-1',
|
||||||
@ -108,7 +108,7 @@ void main() {
|
|||||||
input: '.1',
|
input: '.1',
|
||||||
);
|
);
|
||||||
// 0.2 -> 0.2
|
// 0.2 -> 0.2
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 1,
|
rowIndex: 1,
|
||||||
fieldType: fieldType,
|
fieldType: fieldType,
|
||||||
content: '0.2',
|
content: '0.2',
|
||||||
@ -121,7 +121,7 @@ void main() {
|
|||||||
input: '',
|
input: '',
|
||||||
);
|
);
|
||||||
// .1 -> 0.1
|
// .1 -> 0.1
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: 2,
|
rowIndex: 2,
|
||||||
fieldType: fieldType,
|
fieldType: fieldType,
|
||||||
content: '0.1',
|
content: '0.1',
|
||||||
|
@ -27,29 +27,29 @@ void main() {
|
|||||||
// hide the field
|
// hide the field
|
||||||
await tester.tapGridFieldWithName('New field 1');
|
await tester.tapGridFieldWithName('New field 1');
|
||||||
await tester.tapHidePropertyButton();
|
await tester.tapHidePropertyButton();
|
||||||
await tester.noFieldWithName('New field 1');
|
tester.noFieldWithName('New field 1');
|
||||||
|
|
||||||
// go back to inline database view, expect field to be shown
|
// go back to inline database view, expect field to be shown
|
||||||
await tester.tapTabBarLinkedViewByViewName('Untitled');
|
await tester.tapTabBarLinkedViewByViewName('Untitled');
|
||||||
await tester.findFieldWithName('New field 1');
|
tester.findFieldWithName('New field 1');
|
||||||
|
|
||||||
// go back to linked database view, expect field to be hidden
|
// go back to linked database view, expect field to be hidden
|
||||||
await tester.tapTabBarLinkedViewByViewName('Grid');
|
await tester.tapTabBarLinkedViewByViewName('Grid');
|
||||||
await tester.noFieldWithName('New field 1');
|
tester.noFieldWithName('New field 1');
|
||||||
|
|
||||||
// use the settings button to show the field
|
// use the settings button to show the field
|
||||||
await tester.tapDatabaseSettingButton();
|
await tester.tapDatabaseSettingButton();
|
||||||
await tester.tapViewPropertiesButton();
|
await tester.tapViewPropertiesButton();
|
||||||
await tester.tapViewTogglePropertyVisibilityButtonByName('New field 1');
|
await tester.tapViewTogglePropertyVisibilityButtonByName('New field 1');
|
||||||
await tester.dismissFieldEditor();
|
await tester.dismissFieldEditor();
|
||||||
await tester.findFieldWithName('New field 1');
|
tester.findFieldWithName('New field 1');
|
||||||
|
|
||||||
// open first row in popup then hide the field
|
// open first row in popup then hide the field
|
||||||
await tester.openFirstRowDetailPage();
|
await tester.openFirstRowDetailPage();
|
||||||
await tester.tapGridFieldWithNameInRowDetailPage('New field 1');
|
await tester.tapGridFieldWithNameInRowDetailPage('New field 1');
|
||||||
await tester.tapHidePropertyButtonInFieldEditor();
|
await tester.tapHidePropertyButtonInFieldEditor();
|
||||||
await tester.dismissRowDetailPage();
|
await tester.dismissRowDetailPage();
|
||||||
await tester.noFieldWithName('New field 1');
|
tester.noFieldWithName('New field 1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ void main() {
|
|||||||
await tester.createField(FieldType.Checklist, 'checklist');
|
await tester.createField(FieldType.Checklist, 'checklist');
|
||||||
|
|
||||||
// check the field is created successfully
|
// check the field is created successfully
|
||||||
await tester.findFieldWithName('checklist');
|
tester.findFieldWithName('checklist');
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ void main() {
|
|||||||
// confirm delete
|
// confirm delete
|
||||||
await tester.tapDialogOkButton();
|
await tester.tapDialogOkButton();
|
||||||
|
|
||||||
await tester.noFieldWithName('New field 1');
|
tester.noFieldWithName('New field 1');
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void main() {
|
|||||||
await tester.tapGridFieldWithName('New field 1');
|
await tester.tapGridFieldWithName('New field 1');
|
||||||
await tester.tapDuplicatePropertyButton();
|
await tester.tapDuplicatePropertyButton();
|
||||||
|
|
||||||
await tester.findFieldWithName('New field 1 (copy)');
|
tester.findFieldWithName('New field 1 (copy)');
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -120,13 +120,13 @@ void main() {
|
|||||||
await tester.tapGridFieldWithName('Type');
|
await tester.tapGridFieldWithName('Type');
|
||||||
await tester.tapInsertFieldButton(left: false, name: 'Right');
|
await tester.tapInsertFieldButton(left: false, name: 'Right');
|
||||||
await tester.dismissFieldEditor();
|
await tester.dismissFieldEditor();
|
||||||
await tester.findFieldWithName('Right');
|
tester.findFieldWithName('Right');
|
||||||
|
|
||||||
// insert new field to the right
|
// insert new field to the right
|
||||||
await tester.tapGridFieldWithName('Type');
|
await tester.tapGridFieldWithName('Type');
|
||||||
await tester.tapInsertFieldButton(left: true, name: "Left");
|
await tester.tapInsertFieldButton(left: true, name: "Left");
|
||||||
await tester.dismissFieldEditor();
|
await tester.dismissFieldEditor();
|
||||||
await tester.findFieldWithName('Left');
|
tester.findFieldWithName('Left');
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@ void main() {
|
|||||||
// check the text cell
|
// check the text cell
|
||||||
final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', ''];
|
final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', ''];
|
||||||
for (final (index, content) in textCells.indexed) {
|
for (final (index, content) in textCells.indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: content,
|
content: content,
|
||||||
@ -57,7 +57,7 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
];
|
];
|
||||||
for (final (index, content) in numberCells.indexed) {
|
for (final (index, content) in numberCells.indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.Number,
|
fieldType: FieldType.Number,
|
||||||
content: content,
|
content: content,
|
||||||
@ -74,7 +74,7 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
];
|
];
|
||||||
for (final (index, content) in urlCells.indexed) {
|
for (final (index, content) in urlCells.indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.URL,
|
fieldType: FieldType.URL,
|
||||||
content: content,
|
content: content,
|
||||||
@ -135,7 +135,7 @@ void main() {
|
|||||||
null,
|
null,
|
||||||
];
|
];
|
||||||
for (final (index, percent) in checklistCells.indexed) {
|
for (final (index, percent) in checklistCells.indexed) {
|
||||||
await tester.assertChecklistCellInGrid(
|
tester.assertChecklistCellInGrid(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
percent: percent,
|
percent: percent,
|
||||||
);
|
);
|
||||||
|
@ -28,7 +28,7 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
];
|
];
|
||||||
for (final (index, content) in textCells.indexed) {
|
for (final (index, content) in textCells.indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: content,
|
content: content,
|
||||||
@ -51,7 +51,7 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
].indexed) {
|
].indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: content,
|
content: content,
|
||||||
@ -75,7 +75,7 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
].indexed) {
|
].indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.RichText,
|
fieldType: FieldType.RichText,
|
||||||
content: content,
|
content: content,
|
||||||
@ -153,7 +153,7 @@ void main() {
|
|||||||
'12',
|
'12',
|
||||||
'',
|
'',
|
||||||
].indexed) {
|
].indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.Number,
|
fieldType: FieldType.Number,
|
||||||
content: content,
|
content: content,
|
||||||
@ -176,7 +176,7 @@ void main() {
|
|||||||
'-2',
|
'-2',
|
||||||
'',
|
'',
|
||||||
].indexed) {
|
].indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.Number,
|
fieldType: FieldType.Number,
|
||||||
content: content,
|
content: content,
|
||||||
@ -255,7 +255,7 @@ void main() {
|
|||||||
'2',
|
'2',
|
||||||
'',
|
'',
|
||||||
].indexed) {
|
].indexed) {
|
||||||
await tester.assertCellContent(
|
tester.assertCellContent(
|
||||||
rowIndex: index,
|
rowIndex: index,
|
||||||
fieldType: FieldType.Number,
|
fieldType: FieldType.Number,
|
||||||
content: content,
|
content: content,
|
||||||
|
@ -84,7 +84,7 @@ void main() {
|
|||||||
|
|
||||||
await createInlineDatabase(tester, ViewLayoutPB.Grid);
|
await createInlineDatabase(tester, ViewLayoutPB.Grid);
|
||||||
|
|
||||||
// validate the referenced grid is inserted
|
// validate the inline grid is created
|
||||||
expect(
|
expect(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(AppFlowyEditor),
|
of: find.byType(AppFlowyEditor),
|
||||||
@ -100,7 +100,7 @@ void main() {
|
|||||||
|
|
||||||
await createInlineDatabase(tester, ViewLayoutPB.Board);
|
await createInlineDatabase(tester, ViewLayoutPB.Board);
|
||||||
|
|
||||||
// validate the referenced grid is inserted
|
// validate the inline board is created
|
||||||
expect(
|
expect(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(AppFlowyEditor),
|
of: find.byType(AppFlowyEditor),
|
||||||
@ -116,7 +116,7 @@ void main() {
|
|||||||
|
|
||||||
await createInlineDatabase(tester, ViewLayoutPB.Calendar);
|
await createInlineDatabase(tester, ViewLayoutPB.Calendar);
|
||||||
|
|
||||||
// validate the referenced grid is inserted
|
// validate the inline calendar is created
|
||||||
expect(
|
expect(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(AppFlowyEditor),
|
of: find.byType(AppFlowyEditor),
|
||||||
|
@ -64,7 +64,7 @@ void main() {
|
|||||||
paths: [imagePath],
|
paths: [imagePath],
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt<KeyValueStorage>().set(KVKeys.kCloudType, '0');
|
await getIt<KeyValueStorage>().set(KVKeys.kCloudType, '0');
|
||||||
await tester.tapButtonWithName(
|
await tester.tapButtonWithName(
|
||||||
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
||||||
);
|
);
|
||||||
|
@ -33,7 +33,7 @@ void main() {
|
|||||||
File(path).writeAsStringSync(str);
|
File(path).writeAsStringSync(str);
|
||||||
}
|
}
|
||||||
// mock get files
|
// mock get files
|
||||||
await mockPickFilePaths(
|
mockPickFilePaths(
|
||||||
paths: testFileNames
|
paths: testFileNames
|
||||||
.map((e) => p.join(context.applicationDataDirectory, e))
|
.map((e) => p.join(context.applicationDataDirectory, e))
|
||||||
.toList(),
|
.toList(),
|
||||||
|
@ -34,12 +34,12 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
String? pathExtension,
|
String? pathExtension,
|
||||||
// use to specify the application data directory, if not specified, a temporary directory will be used.
|
// use to specify the application data directory, if not specified, a temporary directory will be used.
|
||||||
String? dataDirectory,
|
String? dataDirectory,
|
||||||
Size windowsSize = const Size(1600, 1200),
|
Size windowSize = const Size(1600, 1200),
|
||||||
AuthenticatorType? cloudType,
|
AuthenticatorType? cloudType,
|
||||||
String? email,
|
String? email,
|
||||||
}) async {
|
}) async {
|
||||||
// view.physicalSize = windowsSize;
|
// view.physicalSize = windowsSize;
|
||||||
binding.setSurfaceSize(windowsSize);
|
await binding.setSurfaceSize(windowSize);
|
||||||
// addTearDown(() => binding.setSurfaceSize(null));
|
// addTearDown(() => binding.setSurfaceSize(null));
|
||||||
|
|
||||||
mockHotKeyManagerHandlers();
|
mockHotKeyManagerHandlers();
|
||||||
|
@ -121,7 +121,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
File(path).writeAsStringSync(str);
|
File(path).writeAsStringSync(str);
|
||||||
}
|
}
|
||||||
// mock get files
|
// mock get files
|
||||||
await mockPickFilePaths(
|
mockPickFilePaths(
|
||||||
paths: paths,
|
paths: paths,
|
||||||
);
|
);
|
||||||
await tapDatabaseRawDataButton();
|
await tapDatabaseRawDataButton();
|
||||||
@ -209,12 +209,12 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The [fieldName] must be unique in the grid.
|
/// The [fieldName] must be unique in the grid.
|
||||||
Future<void> assertCellContent({
|
void assertCellContent({
|
||||||
required int rowIndex,
|
required int rowIndex,
|
||||||
required FieldType fieldType,
|
required FieldType fieldType,
|
||||||
required String content,
|
required String content,
|
||||||
int cellIndex = 0,
|
int cellIndex = 0,
|
||||||
}) async {
|
}) {
|
||||||
final findCell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex);
|
final findCell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex);
|
||||||
final findContent = find.descendant(
|
final findContent = find.descendant(
|
||||||
of: findCell,
|
of: findCell,
|
||||||
@ -263,10 +263,10 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// null percent means no progress bar should be found
|
/// null percent means no progress bar should be found
|
||||||
Future<void> assertChecklistCellInGrid({
|
void assertChecklistCellInGrid({
|
||||||
required int rowIndex,
|
required int rowIndex,
|
||||||
required double? percent,
|
required double? percent,
|
||||||
}) async {
|
}) {
|
||||||
final findCell = cellFinder(rowIndex, FieldType.Checklist);
|
final findCell = cellFinder(rowIndex, FieldType.Checklist);
|
||||||
|
|
||||||
if (percent == null) {
|
if (percent == null) {
|
||||||
@ -880,14 +880,14 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
expect(widget.field.fieldType, fieldType);
|
expect(widget.field.fieldType, fieldType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> findFieldWithName(String name) async {
|
void findFieldWithName(String name) {
|
||||||
final field = find.byWidgetPredicate(
|
final field = find.byWidgetPredicate(
|
||||||
(widget) => widget is FieldCellButton && widget.field.name == name,
|
(widget) => widget is FieldCellButton && widget.field.name == name,
|
||||||
);
|
);
|
||||||
expect(field, findsOneWidget);
|
expect(field, findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> noFieldWithName(String name) async {
|
void noFieldWithName(String name) {
|
||||||
final field = find.byWidgetPredicate(
|
final field = find.byWidgetPredicate(
|
||||||
(widget) => widget is FieldCellButton && widget.field.name == name,
|
(widget) => widget is FieldCellButton && widget.field.name == name,
|
||||||
);
|
);
|
||||||
@ -1559,7 +1559,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
await tapButton(okButton);
|
await tapButton(okButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> assertCurrentDatabaseTagIs(DatabaseLayoutPB layout) async {
|
void assertCurrentDatabaseTagIs(DatabaseLayoutPB layout) {
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case DatabaseLayoutPB.Board:
|
case DatabaseLayoutPB.Board:
|
||||||
expect(find.byType(BoardPage), findsOneWidget);
|
expect(find.byType(BoardPage), findsOneWidget);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
@ -202,9 +203,11 @@ class EditorOperations {
|
|||||||
/// Update the editor's selection
|
/// Update the editor's selection
|
||||||
Future<void> updateSelection(Selection selection) async {
|
Future<void> updateSelection(Selection selection) async {
|
||||||
final editorState = getCurrentEditorState();
|
final editorState = getCurrentEditorState();
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
reason: SelectionUpdateReason.uiEvent,
|
selection,
|
||||||
|
reason: SelectionUpdateReason.uiEvent,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,7 @@ Future<String> mockSaveFilePath(
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<String>> mockPickFilePaths({
|
List<String> mockPickFilePaths({required List<String> paths}) {
|
||||||
required List<String> paths,
|
|
||||||
}) async {
|
|
||||||
getIt.unregister<FilePickerService>();
|
getIt.unregister<FilePickerService>();
|
||||||
getIt.registerFactory<FilePickerService>(
|
getIt.registerFactory<FilePickerService>(
|
||||||
() => MockFilePicker(
|
() => MockFilePicker(
|
||||||
|
@ -50,11 +50,8 @@ class NetworkListener {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
final state = NetworkStatePB.create()..ty = networkType;
|
final state = NetworkStatePB.create()..ty = networkType;
|
||||||
UserEventUpdateNetworkState(state).send().then((result) {
|
return UserEventUpdateNetworkState(state).send().then((result) {
|
||||||
result.fold(
|
result.fold((l) {}, (e) => Log.error(e));
|
||||||
(l) {},
|
|
||||||
(e) => Log.error(e),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import 'package:go_router/go_router.dart';
|
|||||||
|
|
||||||
extension MobileRouter on BuildContext {
|
extension MobileRouter on BuildContext {
|
||||||
Future<void> pushView(ViewPB view, [Map<String, dynamic>? arguments]) async {
|
Future<void> pushView(ViewPB view, [Map<String, dynamic>? arguments]) async {
|
||||||
push(
|
await push(
|
||||||
Uri(
|
Uri(
|
||||||
path: view.routeName,
|
path: view.routeName,
|
||||||
queryParameters: view.queryParameters(arguments),
|
queryParameters: view.queryParameters(arguments),
|
||||||
|
@ -72,7 +72,7 @@ void showQuickEditField(
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
String viewId,
|
String viewId,
|
||||||
FieldInfo fieldInfo,
|
FieldInfo fieldInfo,
|
||||||
) async {
|
) {
|
||||||
showMobileBottomSheet(
|
showMobileBottomSheet(
|
||||||
context,
|
context,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
|
@ -348,7 +348,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (newLayout != null && newLayout != databaseLayout) {
|
if (newLayout != null && newLayout != databaseLayout) {
|
||||||
DatabaseViewBackendService.updateLayout(
|
await DatabaseViewBackendService.updateLayout(
|
||||||
viewId: databaseController.viewId,
|
viewId: databaseController.viewId,
|
||||||
layout: newLayout,
|
layout: newLayout,
|
||||||
);
|
);
|
||||||
@ -357,7 +357,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setting == DatabaseViewSettings.board) {
|
if (setting == DatabaseViewSettings.board) {
|
||||||
showMobileBottomSheet<DatabaseLayoutPB>(
|
await showMobileBottomSheet<DatabaseLayoutPB>(
|
||||||
context,
|
context,
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
@ -373,7 +373,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setting == DatabaseViewSettings.calendar) {
|
if (setting == DatabaseViewSettings.calendar) {
|
||||||
showMobileBottomSheet<DatabaseLayoutPB>(
|
await showMobileBottomSheet<DatabaseLayoutPB>(
|
||||||
context,
|
context,
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
@ -38,7 +40,9 @@ class FontSetting extends StatelessWidget {
|
|||||||
if (newFont != null && newFont != selectedFont) {
|
if (newFont != null && newFont != selectedFont) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
context.read<AppearanceSettingsCubit>().setFontFamily(newFont);
|
context.read<AppearanceSettingsCubit>().setFontFamily(newFont);
|
||||||
context.read<DocumentAppearanceCubit>().syncFontFamily(newFont);
|
unawaited(
|
||||||
|
context.read<DocumentAppearanceCubit>().syncFontFamily(newFont),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,7 @@ class _SelfHostUrlBottomSheetState extends State<SelfHostUrlBottomSheet> {
|
|||||||
validateUrl(value).fold(
|
validateUrl(value).fold(
|
||||||
(url) async {
|
(url) async {
|
||||||
await setAppFlowyCloudUrl(Some(url));
|
await setAppFlowyCloudUrl(Some(url));
|
||||||
runAppFlowy();
|
await runAppFlowy();
|
||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
|
@ -45,7 +45,7 @@ class UserSessionSettingGroup extends StatelessWidget {
|
|||||||
labelText: LocaleKeys.settings_menu_logout.tr(),
|
labelText: LocaleKeys.settings_menu_logout.tr(),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await getIt<AuthService>().signOut();
|
await getIt<AuthService>().signOut();
|
||||||
runAppFlowy();
|
await runAppFlowy();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -18,7 +18,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
|||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<NumberCellEvent>(
|
on<NumberCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
|
@ -242,8 +242,10 @@ class DatabaseController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadLayoutSetting() async {
|
Future<void> _loadLayoutSetting() {
|
||||||
_databaseViewBackendSvc.getLayoutSetting(databaseLayout).then((result) {
|
return _databaseViewBackendSvc
|
||||||
|
.getLayoutSetting(databaseLayout)
|
||||||
|
.then((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(newDatabaseLayoutSetting) {
|
(newDatabaseLayoutSetting) {
|
||||||
databaseLayoutSetting = newDatabaseLayoutSetting;
|
databaseLayoutSetting = newDatabaseLayoutSetting;
|
||||||
|
@ -47,7 +47,7 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
|
|||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<DatabaseGroupEvent>(
|
on<DatabaseGroupEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ class DatabaseTabBarBloc
|
|||||||
: super(DatabaseTabBarState.initial(view)) {
|
: super(DatabaseTabBarState.initial(view)) {
|
||||||
on<DatabaseTabBarEvent>(
|
on<DatabaseTabBarEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () {
|
initial: () {
|
||||||
_listenInlineViewChanged();
|
_listenInlineViewChanged();
|
||||||
_loadChildView();
|
_loadChildView();
|
||||||
@ -93,7 +93,7 @@ class DatabaseTabBarBloc
|
|||||||
// Dispose the controller when the tab is removed.
|
// Dispose the controller when the tab is removed.
|
||||||
final controller =
|
final controller =
|
||||||
tabBarControllerByViewId.remove(tabBar.viewId);
|
tabBarControllerByViewId.remove(tabBar.viewId);
|
||||||
controller?.dispose();
|
await controller?.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == state.selectedIndex) {
|
if (index == state.selectedIndex) {
|
||||||
@ -186,17 +186,18 @@ class DatabaseTabBarBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadChildView() async {
|
void _loadChildView() async {
|
||||||
ViewBackendService.getChildViews(viewId: state.parentView.id)
|
final viewsOrFail =
|
||||||
.then((viewsOrFail) {
|
await ViewBackendService.getChildViews(viewId: state.parentView.id);
|
||||||
if (isClosed) {
|
|
||||||
return;
|
viewsOrFail.fold(
|
||||||
}
|
(views) {
|
||||||
viewsOrFail.fold(
|
if (!isClosed) {
|
||||||
(views) => add(DatabaseTabBarEvent.didLoadChildViews(views)),
|
add(DatabaseTabBarEvent.didLoadChildViews(views));
|
||||||
(err) => Log.error(err),
|
}
|
||||||
);
|
},
|
||||||
});
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _reorderGroup(
|
void _reorderGroup(
|
||||||
String fromGroupId,
|
String fromGroupId,
|
||||||
String toGroupId,
|
String toGroupId,
|
||||||
Emitter<BoardState> emit,
|
Emitter<BoardState> emit,
|
||||||
@ -275,7 +275,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
for (final controller in groupControllers.values) {
|
for (final controller in groupControllers.values) {
|
||||||
controller.dispose();
|
await controller.dispose();
|
||||||
}
|
}
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,8 @@ class GroupController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() {
|
||||||
_listener.stop();
|
return _listener.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,18 +218,17 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadAllEvents() async {
|
void _loadAllEvents() async {
|
||||||
final payload = CalendarEventRequestPB.create()..viewId = viewId;
|
final payload = CalendarEventRequestPB.create()..viewId = viewId;
|
||||||
DatabaseEventGetAllCalendarEvents(payload).send().then((result) {
|
final result = await DatabaseEventGetAllCalendarEvents(payload).send();
|
||||||
result.fold(
|
result.fold(
|
||||||
(events) {
|
(events) {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(CalendarEvent.didLoadAllEvents(events.items));
|
add(CalendarEvent.didLoadAllEvents(events.items));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(r) => Log.error(r),
|
(r) => Log.error(r),
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<CalendarEventData<CalendarDayEvent>> _calendarEventDataFromEventPBs(
|
List<CalendarEventData<CalendarDayEvent>> _calendarEventDataFromEventPBs(
|
||||||
|
@ -90,18 +90,17 @@ class UnscheduleEventsBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadAllEvents() async {
|
void _loadAllEvents() async {
|
||||||
final payload = CalendarEventRequestPB.create()..viewId = viewId;
|
final payload = CalendarEventRequestPB.create()..viewId = viewId;
|
||||||
DatabaseEventGetAllCalendarEvents(payload).send().then((result) {
|
final result = await DatabaseEventGetAllCalendarEvents(payload).send();
|
||||||
result.fold(
|
result.fold(
|
||||||
(events) {
|
(events) {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(UnscheduleEventsEvent.didLoadAllEvents(events.items));
|
add(UnscheduleEventsEvent.didLoadAllEvents(events.items));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(r) => Log.error(r),
|
(r) => Log.error(r),
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
|
@ -29,7 +29,7 @@ class CheckboxFilterEditorBloc
|
|||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<CheckboxFilterEditorEvent>(
|
on<CheckboxFilterEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () async {
|
initial: () async {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
|
@ -29,7 +29,7 @@ class ChecklistFilterEditorBloc
|
|||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<ChecklistFilterEditorEvent>(
|
on<ChecklistFilterEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () async {
|
initial: () async {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,7 @@ class GridCreateFilterBloc
|
|||||||
on<GridCreateFilterEvent>(
|
on<GridCreateFilterEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFields: (List<FieldInfo> fields) {
|
didReceiveFields: (List<FieldInfo> fields) {
|
||||||
|
@ -34,7 +34,7 @@ class SelectOptionFilterEditorBloc
|
|||||||
on<SelectOptionFilterEditorEvent>(
|
on<SelectOptionFilterEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
_loadOptions();
|
_loadOptions();
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,7 @@ class TextFilterEditorBloc
|
|||||||
on<TextFilterEditorEvent>(
|
on<TextFilterEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
updateCondition: (TextFilterConditionPB condition) {
|
updateCondition: (TextFilterConditionPB condition) {
|
||||||
|
@ -31,7 +31,7 @@ class RowDocumentBloc extends Bloc<RowDocumentEvent, RowDocumentState> {
|
|||||||
on<RowDocumentEvent>(
|
on<RowDocumentEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.when(
|
await event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_getRowDocumentView();
|
_getRowDocumentView();
|
||||||
},
|
},
|
||||||
didReceiveRowDocument: (view) {
|
didReceiveRowDocument: (view) {
|
||||||
|
@ -31,7 +31,7 @@ class CreateSortBloc extends Bloc<CreateSortEvent, CreateSortState> {
|
|||||||
on<CreateSortEvent>(
|
on<CreateSortEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFields: (List<FieldInfo> fields) {
|
didReceiveFields: (List<FieldInfo> fields) {
|
||||||
|
@ -32,8 +32,8 @@ class SortEditorBloc extends Bloc<SortEditorEvent, SortEditorState> {
|
|||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<SortEditorEvent>(
|
on<SortEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.when(
|
await event.when(
|
||||||
initial: () async {
|
initial: () {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFields: (List<FieldInfo> fields) {
|
didReceiveFields: (List<FieldInfo> fields) {
|
||||||
|
@ -98,7 +98,7 @@ class _GridCreateFilterListState extends State<GridCreateFilterList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
editBloc.close();
|
editBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,9 @@ class _GridFieldCellState extends State<GridFieldCell> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
|
_bloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
await _bloc.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class _GridCreateSortListState extends State<GridCreateSortList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
editBloc.close();
|
editBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ class _RowCardState extends State<RowCard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
rowNotifier.dispose();
|
rowNotifier.dispose();
|
||||||
_cardBloc.close();
|
_cardBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -68,7 +68,7 @@ class _NumberCellState extends GridEditableTextCell<EditableNumberCell> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
_textEditingController.dispose();
|
_textEditingController.dispose();
|
||||||
cellBloc.close();
|
cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
||||||
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
||||||
@ -66,7 +68,7 @@ class _TextCellState extends GridEditableTextCell<EditableTextCell> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
void dispose() {
|
||||||
_textEditingController.dispose();
|
_textEditingController.dispose();
|
||||||
cellBloc.close();
|
cellBloc.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -176,7 +176,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
await _transactionAdapter.apply(event.$2, editorState);
|
await _transactionAdapter.apply(event.$2, editorState);
|
||||||
|
|
||||||
// check if the document is empty.
|
// check if the document is empty.
|
||||||
applyRules();
|
await applyRules();
|
||||||
|
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
// ignore: invalid_use_of_visible_for_testing_member
|
// ignore: invalid_use_of_visible_for_testing_member
|
||||||
@ -197,8 +197,10 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> applyRules() async {
|
Future<void> applyRules() async {
|
||||||
ensureAtLeastOneParagraphExists();
|
await Future.wait([
|
||||||
ensureLastNodeIsEditable();
|
ensureAtLeastOneParagraphExists(),
|
||||||
|
ensureLastNodeIsEditable(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> ensureLastNodeIsEditable() async {
|
Future<void> ensureLastNodeIsEditable() async {
|
||||||
|
@ -164,10 +164,10 @@ class _DocumentPageState extends State<DocumentPage> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Future<void> _onNotificationAction(
|
void _onNotificationAction(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
NotificationActionState state,
|
NotificationActionState state,
|
||||||
) async {
|
) {
|
||||||
if (state.action != null && state.action!.type == ActionType.jumpToBlock) {
|
if (state.action != null && state.action!.type == ActionType.jumpToBlock) {
|
||||||
final path = state.action?.arguments?[ActionArgumentKeys.nodePath];
|
final path = state.action?.arguments?[ActionArgumentKeys.nodePath];
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
|
|||||||
case _ActionType.delete:
|
case _ActionType.delete:
|
||||||
final transaction = widget.editorState.transaction;
|
final transaction = widget.editorState.transaction;
|
||||||
transaction.deleteNode(widget.node);
|
transaction.deleteNode(widget.node);
|
||||||
widget.editorState.apply(transaction);
|
await widget.editorState.apply(transaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
controller.close();
|
controller.close();
|
||||||
@ -177,7 +177,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
|
|||||||
Future<void> _deletePage() async {
|
Future<void> _deletePage() async {
|
||||||
final transaction = widget.editorState.transaction;
|
final transaction = widget.editorState.transaction;
|
||||||
transaction.deleteNode(widget.node);
|
transaction.deleteNode(widget.node);
|
||||||
widget.editorState.apply(transaction);
|
await widget.editorState.apply(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/mobile_block_action_buttons.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/mobile_block_action_buttons.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_item_list_menu.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_item_list_menu.dart';
|
||||||
@ -310,7 +312,7 @@ class _CodeBlockComponentWidgetState extends State<CodeBlockComponentWidget>
|
|||||||
MobileCodeLanguagePickerScreen.routeName,
|
MobileCodeLanguagePickerScreen.routeName,
|
||||||
);
|
);
|
||||||
if (language != null) {
|
if (language != null) {
|
||||||
updateLanguage(language);
|
unawaited(updateLanguage(language));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -101,7 +101,7 @@ extension PasteNodes on EditorState {
|
|||||||
|
|
||||||
// delete the selection first.
|
// delete the selection first.
|
||||||
if (!selection.isCollapsed) {
|
if (!selection.isCollapsed) {
|
||||||
deleteSelection(selection);
|
await deleteSelection(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch selection again.selection = editorState.selection;
|
// fetch selection again.selection = editorState.selection;
|
||||||
|
@ -20,15 +20,12 @@ SelectionMenuItem inlineGridMenuItem(DocumentBloc documentBloc) =>
|
|||||||
handler: (editorState, menuService, context) async {
|
handler: (editorState, menuService, context) async {
|
||||||
// create the view inside current page
|
// create the view inside current page
|
||||||
final parentViewId = documentBloc.view.id;
|
final parentViewId = documentBloc.view.id;
|
||||||
ViewBackendService.createView(
|
final value = await ViewBackendService.createView(
|
||||||
parentViewId: parentViewId,
|
parentViewId: parentViewId,
|
||||||
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
layoutType: ViewLayoutPB.Grid,
|
layoutType: ViewLayoutPB.Grid,
|
||||||
).then(
|
|
||||||
(value) => value
|
|
||||||
.swap()
|
|
||||||
.map((r) => editorState.insertInlinePage(parentViewId, r)),
|
|
||||||
);
|
);
|
||||||
|
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -44,15 +41,12 @@ SelectionMenuItem inlineBoardMenuItem(DocumentBloc documentBloc) =>
|
|||||||
handler: (editorState, menuService, context) async {
|
handler: (editorState, menuService, context) async {
|
||||||
// create the view inside current page
|
// create the view inside current page
|
||||||
final parentViewId = documentBloc.view.id;
|
final parentViewId = documentBloc.view.id;
|
||||||
ViewBackendService.createView(
|
final value = await ViewBackendService.createView(
|
||||||
parentViewId: parentViewId,
|
parentViewId: parentViewId,
|
||||||
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
layoutType: ViewLayoutPB.Board,
|
layoutType: ViewLayoutPB.Board,
|
||||||
).then(
|
|
||||||
(value) => value
|
|
||||||
.swap()
|
|
||||||
.map((r) => editorState.insertInlinePage(parentViewId, r)),
|
|
||||||
);
|
);
|
||||||
|
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -68,14 +62,11 @@ SelectionMenuItem inlineCalendarMenuItem(DocumentBloc documentBloc) =>
|
|||||||
handler: (editorState, menuService, context) async {
|
handler: (editorState, menuService, context) async {
|
||||||
// create the view inside current page
|
// create the view inside current page
|
||||||
final parentViewId = documentBloc.view.id;
|
final parentViewId = documentBloc.view.id;
|
||||||
ViewBackendService.createView(
|
final value = await ViewBackendService.createView(
|
||||||
parentViewId: parentViewId,
|
parentViewId: parentViewId,
|
||||||
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
layoutType: ViewLayoutPB.Calendar,
|
layoutType: ViewLayoutPB.Calendar,
|
||||||
).then(
|
|
||||||
(value) => value
|
|
||||||
.swap()
|
|
||||||
.map((r) => editorState.insertInlinePage(parentViewId, r)),
|
|
||||||
);
|
);
|
||||||
|
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -53,7 +53,7 @@ class ChangeCoverPopoverBloc
|
|||||||
final updateImageList = currentState.imageNames
|
final updateImageList = currentState.imageNames
|
||||||
.where((path) => path != deleteImage.path)
|
.where((path) => path != deleteImage.path)
|
||||||
.toList();
|
.toList();
|
||||||
await _updateImagePathsInStorage(updateImageList);
|
_updateImagePathsInStorage(updateImageList);
|
||||||
emit(Loaded(updateImageList));
|
emit(Loaded(updateImageList));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -69,7 +69,7 @@ class ChangeCoverPopoverBloc
|
|||||||
_removeCoverImageFromNode();
|
_removeCoverImageFromNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await _updateImagePathsInStorage([]);
|
_updateImagePathsInStorage([]);
|
||||||
emit(const Loaded([]));
|
emit(const Loaded([]));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -84,14 +84,13 @@ class ChangeCoverPopoverBloc
|
|||||||
return imageNames;
|
return imageNames;
|
||||||
}
|
}
|
||||||
imageNames.removeWhere((name) => !File(name).existsSync());
|
imageNames.removeWhere((name) => !File(name).existsSync());
|
||||||
_prefs.setStringList(kLocalImagesKey, imageNames);
|
unawaited(_prefs.setStringList(kLocalImagesKey, imageNames));
|
||||||
return imageNames;
|
return imageNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateImagePathsInStorage(List<String> imagePaths) async {
|
void _updateImagePathsInStorage(List<String> imagePaths) async {
|
||||||
await _initCompleter.future;
|
await _initCompleter.future;
|
||||||
_prefs.setStringList(kLocalImagesKey, imagePaths);
|
await _prefs.setStringList(kLocalImagesKey, imagePaths);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteImageInStorage(String path) async {
|
Future<void> _deleteImageInStorage(String path) async {
|
||||||
@ -99,14 +98,14 @@ class ChangeCoverPopoverBloc
|
|||||||
await imageFile.delete();
|
await imageFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _removeCoverImageFromNode() async {
|
void _removeCoverImageFromNode() {
|
||||||
final transaction = editorState.transaction;
|
final transaction = editorState.transaction;
|
||||||
transaction.updateNode(node, {
|
transaction.updateNode(node, {
|
||||||
DocumentHeaderBlockKeys.coverType: CoverType.none.toString(),
|
DocumentHeaderBlockKeys.coverType: CoverType.none.toString(),
|
||||||
DocumentHeaderBlockKeys.icon:
|
DocumentHeaderBlockKeys.icon:
|
||||||
node.attributes[DocumentHeaderBlockKeys.icon],
|
node.attributes[DocumentHeaderBlockKeys.icon],
|
||||||
});
|
});
|
||||||
return editorState.apply(transaction);
|
editorState.apply(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: _calculateOverallHeight(),
|
height: _calculateOverallHeight(),
|
||||||
child: DocumentHeaderToolbar(
|
child: DocumentHeaderToolbar(
|
||||||
onCoverChanged: _saveCover,
|
onIconOrCoverChanged: _saveIconOrCover,
|
||||||
node: widget.node,
|
node: widget.node,
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
hasCover: hasCover,
|
hasCover: hasCover,
|
||||||
@ -133,8 +133,8 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
|
|||||||
node: widget.node,
|
node: widget.node,
|
||||||
coverType: coverType,
|
coverType: coverType,
|
||||||
coverDetails: coverDetails,
|
coverDetails: coverDetails,
|
||||||
onCoverChanged: (type, details) =>
|
onChangeCover: (type, details) =>
|
||||||
_saveCover(cover: (type, details)),
|
_saveIconOrCover(cover: (type, details)),
|
||||||
),
|
),
|
||||||
if (hasIcon)
|
if (hasIcon)
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -147,9 +147,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
|
|||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
node: widget.node,
|
node: widget.node,
|
||||||
icon: viewIcon,
|
icon: viewIcon,
|
||||||
onIconChanged: (icon) async {
|
onChangeIcon: (icon) => _saveIconOrCover(icon: icon),
|
||||||
_saveCover(icon: icon);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -169,7 +167,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveCover({(CoverType, String?)? cover, String? icon}) async {
|
void _saveIconOrCover({(CoverType, String?)? cover, String? icon}) async {
|
||||||
final transaction = widget.editorState.transaction;
|
final transaction = widget.editorState.transaction;
|
||||||
final coverType = widget.node.attributes[DocumentHeaderBlockKeys.coverType];
|
final coverType = widget.node.attributes[DocumentHeaderBlockKeys.coverType];
|
||||||
final coverDetails =
|
final coverDetails =
|
||||||
@ -190,7 +188,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transaction.updateNode(widget.node, attributes);
|
transaction.updateNode(widget.node, attributes);
|
||||||
return widget.editorState.apply(transaction);
|
await widget.editorState.apply(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,15 +200,15 @@ class DocumentHeaderToolbar extends StatefulWidget {
|
|||||||
required this.editorState,
|
required this.editorState,
|
||||||
required this.hasCover,
|
required this.hasCover,
|
||||||
required this.hasIcon,
|
required this.hasIcon,
|
||||||
required this.onCoverChanged,
|
required this.onIconOrCoverChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Node node;
|
final Node node;
|
||||||
final EditorState editorState;
|
final EditorState editorState;
|
||||||
final bool hasCover;
|
final bool hasCover;
|
||||||
final bool hasIcon;
|
final bool hasIcon;
|
||||||
final Future<void> Function({(CoverType, String?)? cover, String? icon})
|
final void Function({(CoverType, String?)? cover, String? icon})
|
||||||
onCoverChanged;
|
onIconOrCoverChanged;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentHeaderToolbar> createState() => _DocumentHeaderToolbarState();
|
State<DocumentHeaderToolbar> createState() => _DocumentHeaderToolbarState();
|
||||||
@ -276,7 +274,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
|||||||
children.add(
|
children.add(
|
||||||
FlowyButton(
|
FlowyButton(
|
||||||
leftIconSize: const Size.square(18),
|
leftIconSize: const Size.square(18),
|
||||||
onTap: () => widget.onCoverChanged(
|
onTap: () => widget.onIconOrCoverChanged(
|
||||||
cover: PlatformExtension.isDesktopOrWeb
|
cover: PlatformExtension.isDesktopOrWeb
|
||||||
? (CoverType.asset, builtInAssetImages.first)
|
? (CoverType.asset, builtInAssetImages.first)
|
||||||
: (CoverType.color, '0xffe8e0ff'),
|
: (CoverType.color, '0xffe8e0ff'),
|
||||||
@ -294,7 +292,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
|||||||
children.add(
|
children.add(
|
||||||
FlowyButton(
|
FlowyButton(
|
||||||
leftIconSize: const Size.square(18),
|
leftIconSize: const Size.square(18),
|
||||||
onTap: () => widget.onCoverChanged(icon: ""),
|
onTap: () => widget.onIconOrCoverChanged(icon: ""),
|
||||||
useIntrinsicWidth: true,
|
useIntrinsicWidth: true,
|
||||||
leftIcon: const Icon(
|
leftIcon: const Icon(
|
||||||
Icons.emoji_emotions_outlined,
|
Icons.emoji_emotions_outlined,
|
||||||
@ -323,7 +321,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
|||||||
MobileEmojiPickerScreen.routeName,
|
MobileEmojiPickerScreen.routeName,
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
widget.onCoverChanged(icon: result.emoji);
|
widget.onIconOrCoverChanged(icon: result.emoji);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -340,7 +338,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
|
|||||||
isPopoverOpen = true;
|
isPopoverOpen = true;
|
||||||
return FlowyIconPicker(
|
return FlowyIconPicker(
|
||||||
onSelected: (result) {
|
onSelected: (result) {
|
||||||
widget.onCoverChanged(icon: result.emoji);
|
widget.onIconOrCoverChanged(icon: result.emoji);
|
||||||
_popoverController.close();
|
_popoverController.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -370,14 +368,14 @@ class DocumentCover extends StatefulWidget {
|
|||||||
required this.editorState,
|
required this.editorState,
|
||||||
required this.coverType,
|
required this.coverType,
|
||||||
this.coverDetails,
|
this.coverDetails,
|
||||||
required this.onCoverChanged,
|
required this.onChangeCover,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Node node;
|
final Node node;
|
||||||
final EditorState editorState;
|
final EditorState editorState;
|
||||||
final CoverType coverType;
|
final CoverType coverType;
|
||||||
final String? coverDetails;
|
final String? coverDetails;
|
||||||
final Future<void> Function(CoverType type, String? details) onCoverChanged;
|
final void Function(CoverType type, String? details) onChangeCover;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentCover> createState() => DocumentCoverState();
|
State<DocumentCover> createState() => DocumentCoverState();
|
||||||
@ -459,18 +457,18 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
],
|
],
|
||||||
onSelectedLocalImage: (path) async {
|
onSelectedLocalImage: (path) async {
|
||||||
context.pop();
|
context.pop();
|
||||||
widget.onCoverChanged(CoverType.file, path);
|
widget.onChangeCover(CoverType.file, path);
|
||||||
},
|
},
|
||||||
onSelectedAIImage: (_) {
|
onSelectedAIImage: (_) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
},
|
},
|
||||||
onSelectedNetworkImage: (url) async {
|
onSelectedNetworkImage: (url) async {
|
||||||
context.pop();
|
context.pop();
|
||||||
widget.onCoverChanged(CoverType.file, url);
|
widget.onChangeCover(CoverType.file, url);
|
||||||
},
|
},
|
||||||
onSelectedColor: (color) {
|
onSelectedColor: (color) {
|
||||||
context.pop();
|
context.pop();
|
||||||
widget.onCoverChanged(CoverType.color, color);
|
widget.onChangeCover(CoverType.color, color);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -490,7 +488,7 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
SizedBox.square(
|
SizedBox.square(
|
||||||
dimension: 32.0,
|
dimension: 32.0,
|
||||||
child: DeleteCoverButton(
|
child: DeleteCoverButton(
|
||||||
onTap: () => widget.onCoverChanged(CoverType.none, null),
|
onTap: () => widget.onChangeCover(CoverType.none, null),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -521,7 +519,7 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
final imageFile = File(detail);
|
final imageFile = File(detail);
|
||||||
if (!imageFile.existsSync()) {
|
if (!imageFile.existsSync()) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
widget.onCoverChanged(CoverType.none, null);
|
widget.onChangeCover(CoverType.none, null);
|
||||||
});
|
});
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
@ -582,14 +580,14 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
UploadImageType.url,
|
UploadImageType.url,
|
||||||
UploadImageType.unsplash,
|
UploadImageType.unsplash,
|
||||||
],
|
],
|
||||||
onSelectedLocalImage: (path) async {
|
onSelectedLocalImage: (path) {
|
||||||
popoverController.close();
|
popoverController.close();
|
||||||
onCoverChanged(CoverType.file, path);
|
onCoverChanged(CoverType.file, path);
|
||||||
},
|
},
|
||||||
onSelectedAIImage: (_) {
|
onSelectedAIImage: (_) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
},
|
},
|
||||||
onSelectedNetworkImage: (url) async {
|
onSelectedNetworkImage: (url) {
|
||||||
popoverController.close();
|
popoverController.close();
|
||||||
onCoverChanged(CoverType.file, url);
|
onCoverChanged(CoverType.file, url);
|
||||||
},
|
},
|
||||||
@ -620,7 +618,7 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
details = await saveImageToCloudStorage(details);
|
details = await saveImageToCloudStorage(details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widget.onCoverChanged(type, details);
|
widget.onChangeCover(type, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOverlayButtonsHidden(bool value) {
|
void setOverlayButtonsHidden(bool value) {
|
||||||
@ -666,13 +664,13 @@ class DocumentIcon extends StatefulWidget {
|
|||||||
required this.node,
|
required this.node,
|
||||||
required this.editorState,
|
required this.editorState,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.onIconChanged,
|
required this.onChangeIcon,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Node node;
|
final Node node;
|
||||||
final EditorState editorState;
|
final EditorState editorState;
|
||||||
final String icon;
|
final String icon;
|
||||||
final Future<void> Function(String icon) onIconChanged;
|
final void Function(String icon) onChangeIcon;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentIcon> createState() => _DocumentIconState();
|
State<DocumentIcon> createState() => _DocumentIconState();
|
||||||
@ -697,7 +695,7 @@ class _DocumentIconState extends State<DocumentIcon> {
|
|||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
return FlowyIconPicker(
|
return FlowyIconPicker(
|
||||||
onSelected: (result) {
|
onSelected: (result) {
|
||||||
widget.onIconChanged(result.emoji);
|
widget.onChangeIcon(result.emoji);
|
||||||
_popoverController.close();
|
_popoverController.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -711,7 +709,7 @@ class _DocumentIconState extends State<DocumentIcon> {
|
|||||||
MobileEmojiPickerScreen.routeName,
|
MobileEmojiPickerScreen.routeName,
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
widget.onIconChanged(result.emoji);
|
widget.onChangeIcon(result.emoji);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart';
|
||||||
@ -138,13 +140,15 @@ class BlockItems extends StatelessWidget {
|
|||||||
_closeKeyboard(selection);
|
_closeKeyboard(selection);
|
||||||
|
|
||||||
// keep the selection
|
// keep the selection
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {
|
selection,
|
||||||
selectionExtraInfoDisableMobileToolbarKey: true,
|
extraInfo: {
|
||||||
selectionExtraInfoDoNotAttachTextService: true,
|
selectionExtraInfoDisableMobileToolbarKey: true,
|
||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
selectionExtraInfoDoNotAttachTextService: true,
|
||||||
},
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
|
|
||||||
@ -173,9 +177,11 @@ class BlockItems extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
// re-open the keyboard again
|
// re-open the keyboard again
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {},
|
selection,
|
||||||
|
extraInfo: {},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
|
||||||
@ -22,13 +24,15 @@ class ColorItem extends StatelessWidget {
|
|||||||
size: const Size(82, 52),
|
size: const Size(82, 52),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
service.closeKeyboard();
|
service.closeKeyboard();
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
editorState.selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {
|
editorState.selection,
|
||||||
selectionExtraInfoDisableMobileToolbarKey: true,
|
extraInfo: {
|
||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
selectionExtraInfoDisableMobileToolbarKey: true,
|
||||||
selectionExtraInfoDoNotAttachTextService: true,
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
},
|
selectionExtraInfoDoNotAttachTextService: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
await showTextColorAndBackgroundColorPicker(
|
await showTextColorAndBackgroundColorPicker(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
@ -30,12 +32,14 @@ class FontFamilyItem extends StatelessWidget {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
final selection = editorState.selection;
|
final selection = editorState.selection;
|
||||||
// disable the floating toolbar
|
// disable the floating toolbar
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {
|
selection,
|
||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
extraInfo: {
|
||||||
selectionExtraInfoDisableMobileToolbarKey: true,
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
},
|
selectionExtraInfoDisableMobileToolbarKey: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final newFont = await context
|
final newFont = await context
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
@ -93,12 +95,14 @@ class _HeadingOrTextItem extends StatelessWidget {
|
|||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
editorState.selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {
|
editorState.selection,
|
||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
extraInfo: {
|
||||||
selectionExtraInfoDoNotAttachTextService: true,
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
},
|
selectionExtraInfoDoNotAttachTextService: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
@ -23,13 +25,15 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
|||||||
|
|
||||||
// delay to wait the keyboard closed.
|
// delay to wait the keyboard closed.
|
||||||
Future.delayed(const Duration(milliseconds: 100), () async {
|
Future.delayed(const Duration(milliseconds: 100), () async {
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
extraInfo: {
|
selection,
|
||||||
selectionExtraInfoDisableMobileToolbarKey: true,
|
extraInfo: {
|
||||||
selectionExtraInfoDisableFloatingToolbar: true,
|
selectionExtraInfoDisableMobileToolbarKey: true,
|
||||||
selectionExtraInfoDoNotAttachTextService: true,
|
selectionExtraInfoDisableFloatingToolbar: true,
|
||||||
},
|
selectionExtraInfoDoNotAttachTextService: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
final didAddBlock = await showAddBlockMenu(
|
final didAddBlock = await showAddBlockMenu(
|
||||||
@ -38,8 +42,10 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
|
|||||||
selection: selection!,
|
selection: selection!,
|
||||||
);
|
);
|
||||||
if (didAddBlock != true) {
|
if (didAddBlock != true) {
|
||||||
editorState.updateSelectionWithReason(
|
unawaited(
|
||||||
selection,
|
editorState.updateSelectionWithReason(
|
||||||
|
selection,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -190,14 +190,14 @@ class _AutoCompletionBlockComponentState
|
|||||||
|
|
||||||
Future<void> _onGenerate() async {
|
Future<void> _onGenerate() async {
|
||||||
final loading = Loading(context);
|
final loading = Loading(context);
|
||||||
loading.start();
|
await loading.start();
|
||||||
|
|
||||||
await _updateEditingText();
|
await _updateEditingText();
|
||||||
|
|
||||||
final userProfile = await UserBackendService.getCurrentUserProfile()
|
final userProfile = await UserBackendService.getCurrentUserProfile()
|
||||||
.then((value) => value.toOption().toNullable());
|
.then((value) => value.toOption().toNullable());
|
||||||
if (userProfile == null) {
|
if (userProfile == null) {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showSnackBarMessage(
|
showSnackBarMessage(
|
||||||
context,
|
context,
|
||||||
@ -217,10 +217,12 @@ class _AutoCompletionBlockComponentState
|
|||||||
await openAIRepository.getStreamedCompletions(
|
await openAIRepository.getStreamedCompletions(
|
||||||
prompt: controller.text,
|
prompt: controller.text,
|
||||||
onStart: () async {
|
onStart: () async {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
barrierDialog = BarrierDialog(context);
|
if (mounted) {
|
||||||
barrierDialog?.show();
|
barrierDialog = BarrierDialog(context);
|
||||||
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
await barrierDialog?.show();
|
||||||
|
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onProcess: (response) async {
|
onProcess: (response) async {
|
||||||
if (response.choices.isNotEmpty) {
|
if (response.choices.isNotEmpty) {
|
||||||
@ -235,12 +237,14 @@ class _AutoCompletionBlockComponentState
|
|||||||
await barrierDialog?.dismiss();
|
await barrierDialog?.dismiss();
|
||||||
},
|
},
|
||||||
onError: (error) async {
|
onError: (error) async {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
showSnackBarMessage(
|
if (mounted) {
|
||||||
context,
|
showSnackBarMessage(
|
||||||
error.message,
|
context,
|
||||||
showCancel: true,
|
error.message,
|
||||||
);
|
showCancel: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await _updateGenerationCount();
|
await _updateGenerationCount();
|
||||||
@ -261,7 +265,7 @@ class _AutoCompletionBlockComponentState
|
|||||||
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_onExit();
|
return _onExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onRewrite() async {
|
Future<void> _onRewrite() async {
|
||||||
@ -271,7 +275,7 @@ class _AutoCompletionBlockComponentState
|
|||||||
}
|
}
|
||||||
|
|
||||||
final loading = Loading(context);
|
final loading = Loading(context);
|
||||||
loading.start();
|
await loading.start();
|
||||||
// clear previous response
|
// clear previous response
|
||||||
final selection = startSelection;
|
final selection = startSelection;
|
||||||
if (selection != null) {
|
if (selection != null) {
|
||||||
@ -290,7 +294,7 @@ class _AutoCompletionBlockComponentState
|
|||||||
final userProfile = await UserBackendService.getCurrentUserProfile()
|
final userProfile = await UserBackendService.getCurrentUserProfile()
|
||||||
.then((value) => value.toOption().toNullable());
|
.then((value) => value.toOption().toNullable());
|
||||||
if (userProfile == null) {
|
if (userProfile == null) {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showSnackBarMessage(
|
showSnackBarMessage(
|
||||||
context,
|
context,
|
||||||
@ -308,7 +312,7 @@ class _AutoCompletionBlockComponentState
|
|||||||
await openAIRepository.getStreamedCompletions(
|
await openAIRepository.getStreamedCompletions(
|
||||||
prompt: _rewritePrompt(previousOutput),
|
prompt: _rewritePrompt(previousOutput),
|
||||||
onStart: () async {
|
onStart: () async {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
||||||
},
|
},
|
||||||
onProcess: (response) async {
|
onProcess: (response) async {
|
||||||
@ -322,12 +326,14 @@ class _AutoCompletionBlockComponentState
|
|||||||
},
|
},
|
||||||
onEnd: () async {},
|
onEnd: () async {},
|
||||||
onError: (error) async {
|
onError: (error) async {
|
||||||
loading.stop();
|
await loading.stop();
|
||||||
showSnackBarMessage(
|
if (mounted) {
|
||||||
context,
|
showSnackBarMessage(
|
||||||
error.message,
|
context,
|
||||||
showCancel: true,
|
error.message,
|
||||||
);
|
showCancel: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await _updateGenerationCount();
|
await _updateGenerationCount();
|
||||||
|
@ -128,7 +128,7 @@ class _SmartEditBlockComponentWidgetState
|
|||||||
if (state.result.isEmpty) {
|
if (state.result.isEmpty) {
|
||||||
completer.complete(true);
|
completer.complete(true);
|
||||||
} else {
|
} else {
|
||||||
showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return DiscardDialog(
|
return DiscardDialog(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/core/config/kv_keys.dart';
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
import 'package:appflowy/util/color_to_hex_string.dart';
|
import 'package:appflowy/util/color_to_hex_string.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
@ -96,102 +98,84 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
|||||||
|
|
||||||
Future<void> syncFontSize(double fontSize) async {
|
Future<void> syncFontSize(double fontSize) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
prefs.setDouble(KVKeys.kDocumentAppearanceFontSize, fontSize);
|
await prefs.setDouble(KVKeys.kDocumentAppearanceFontSize, fontSize);
|
||||||
|
|
||||||
if (isClosed) {
|
if (!isClosed) {
|
||||||
return;
|
emit(state.copyWith(fontSize: fontSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
fontSize: fontSize,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> syncFontFamily(String fontFamily) async {
|
Future<void> syncFontFamily(String fontFamily) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
prefs.setString(KVKeys.kDocumentAppearanceFontFamily, fontFamily);
|
await prefs.setString(KVKeys.kDocumentAppearanceFontFamily, fontFamily);
|
||||||
|
|
||||||
if (isClosed) {
|
if (!isClosed) {
|
||||||
return;
|
emit(state.copyWith(fontFamily: fontFamily));
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> syncDefaultTextDirection(String? direction) async {
|
Future<void> syncDefaultTextDirection(String? direction) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
if (direction == null) {
|
if (direction == null) {
|
||||||
prefs.remove(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
await prefs.remove(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
||||||
} else {
|
} else {
|
||||||
prefs.setString(
|
await prefs.setString(
|
||||||
KVKeys.kDocumentAppearanceDefaultTextDirection,
|
KVKeys.kDocumentAppearanceDefaultTextDirection,
|
||||||
direction,
|
direction,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClosed) {
|
if (!isClosed) {
|
||||||
return;
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
defaultTextDirection: direction,
|
||||||
|
textDirectionIsNull: direction == null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
defaultTextDirection: direction,
|
|
||||||
textDirectionIsNull: direction == null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> syncCursorColor(Color? cursorColor) async {
|
Future<void> syncCursorColor(Color? cursorColor) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
if (cursorColor == null) {
|
if (cursorColor == null) {
|
||||||
prefs.remove(KVKeys.kDocumentAppearanceCursorColor);
|
await prefs.remove(KVKeys.kDocumentAppearanceCursorColor);
|
||||||
} else {
|
} else {
|
||||||
prefs.setString(
|
await prefs.setString(
|
||||||
KVKeys.kDocumentAppearanceCursorColor,
|
KVKeys.kDocumentAppearanceCursorColor,
|
||||||
cursorColor.toHexString(),
|
cursorColor.toHexString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClosed) {
|
if (!isClosed) {
|
||||||
return;
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
cursorColor: cursorColor,
|
||||||
|
cursorColorIsNull: cursorColor == null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
cursorColor: cursorColor,
|
|
||||||
cursorColorIsNull: cursorColor == null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> syncSelectionColor(Color? selectionColor) async {
|
Future<void> syncSelectionColor(Color? selectionColor) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
if (selectionColor == null) {
|
if (selectionColor == null) {
|
||||||
prefs.remove(KVKeys.kDocumentAppearanceSelectionColor);
|
await prefs.remove(KVKeys.kDocumentAppearanceSelectionColor);
|
||||||
} else {
|
} else {
|
||||||
prefs.setString(
|
await prefs.setString(
|
||||||
KVKeys.kDocumentAppearanceSelectionColor,
|
KVKeys.kDocumentAppearanceSelectionColor,
|
||||||
selectionColor.toHexString(),
|
selectionColor.toHexString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isClosed) {
|
if (!isClosed) {
|
||||||
return;
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
selectionColor: selectionColor,
|
||||||
|
selectionColorIsNull: selectionColor == null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
selectionColor: selectionColor,
|
|
||||||
selectionColorIsNull: selectionColor == null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ class InlinePageReferenceService {
|
|||||||
await editorState.insertReferencePage(view, view.layout);
|
await editorState.insertReferencePage(view, view.layout);
|
||||||
} on FlowyError catch (e) {
|
} on FlowyError catch (e) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Dialogs.show(
|
return Dialogs.show(
|
||||||
context,
|
context,
|
||||||
child: FlowyErrorPage.message(
|
child: FlowyErrorPage.message(
|
||||||
e.msg,
|
e.msg,
|
||||||
|
@ -84,69 +84,69 @@ class AppFlowyCloudDeepLink {
|
|||||||
Uri? uri,
|
Uri? uri,
|
||||||
) async {
|
) async {
|
||||||
_stateNotifier?.value = DeepLinkResult(state: DeepLinkState.none);
|
_stateNotifier?.value = DeepLinkResult(state: DeepLinkState.none);
|
||||||
if (uri != null) {
|
|
||||||
_isAuthCallbackDeeplink(uri).fold(
|
|
||||||
(_) async {
|
|
||||||
final deviceId = await getDeviceId();
|
|
||||||
final payload = OauthSignInPB(
|
|
||||||
authenticator: AuthenticatorPB.AppFlowyCloud,
|
|
||||||
map: {
|
|
||||||
AuthServiceMapKeys.signInURL: uri.toString(),
|
|
||||||
AuthServiceMapKeys.deviceId: deviceId,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
_stateNotifier?.value = DeepLinkResult(state: DeepLinkState.loading);
|
|
||||||
final result = await UserEventOauthSignIn(payload)
|
|
||||||
.send()
|
|
||||||
.then((value) => value.swap());
|
|
||||||
|
|
||||||
_stateNotifier?.value = DeepLinkResult(
|
if (uri == null) {
|
||||||
state: DeepLinkState.finish,
|
|
||||||
result: result,
|
|
||||||
);
|
|
||||||
// If there is no completer, runAppFlowy() will be called.
|
|
||||||
if (_completer == null) {
|
|
||||||
result.fold(
|
|
||||||
(err) {
|
|
||||||
Log.error(err);
|
|
||||||
final context = AppGlobals.rootNavKey.currentState?.context;
|
|
||||||
if (context != null) {
|
|
||||||
showSnackBarMessage(
|
|
||||||
context,
|
|
||||||
err.msg,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(_) async {
|
|
||||||
await runAppFlowy();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_completer?.complete(result);
|
|
||||||
_completer = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err) {
|
|
||||||
Log.error('onDeepLinkError: Unexpect deep link: $err');
|
|
||||||
if (_completer == null) {
|
|
||||||
final context = AppGlobals.rootNavKey.currentState?.context;
|
|
||||||
if (context != null) {
|
|
||||||
showSnackBarMessage(
|
|
||||||
context,
|
|
||||||
err.msg,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_completer?.complete(left(err));
|
|
||||||
_completer = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Log.error('onDeepLinkError: Unexpect empty deep link callback');
|
Log.error('onDeepLinkError: Unexpect empty deep link callback');
|
||||||
_completer?.complete(left(AuthError.emptyDeeplink));
|
_completer?.complete(left(AuthError.emptyDeeplink));
|
||||||
_completer = null;
|
_completer = null;
|
||||||
}
|
}
|
||||||
|
return _isAuthCallbackDeeplink(uri!).fold(
|
||||||
|
(_) async {
|
||||||
|
final deviceId = await getDeviceId();
|
||||||
|
final payload = OauthSignInPB(
|
||||||
|
authenticator: AuthenticatorPB.AppFlowyCloud,
|
||||||
|
map: {
|
||||||
|
AuthServiceMapKeys.signInURL: uri.toString(),
|
||||||
|
AuthServiceMapKeys.deviceId: deviceId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
_stateNotifier?.value = DeepLinkResult(state: DeepLinkState.loading);
|
||||||
|
final result = await UserEventOauthSignIn(payload)
|
||||||
|
.send()
|
||||||
|
.then((value) => value.swap());
|
||||||
|
|
||||||
|
_stateNotifier?.value = DeepLinkResult(
|
||||||
|
state: DeepLinkState.finish,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
// If there is no completer, runAppFlowy() will be called.
|
||||||
|
if (_completer == null) {
|
||||||
|
await result.fold(
|
||||||
|
(err) {
|
||||||
|
Log.error(err);
|
||||||
|
final context = AppGlobals.rootNavKey.currentState?.context;
|
||||||
|
if (context != null) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
err.msg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_) async {
|
||||||
|
await runAppFlowy();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_completer?.complete(result);
|
||||||
|
_completer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) {
|
||||||
|
Log.error('onDeepLinkError: Unexpect deep link: $err');
|
||||||
|
if (_completer == null) {
|
||||||
|
final context = AppGlobals.rootNavKey.currentState?.context;
|
||||||
|
if (context != null) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
err.msg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_completer?.complete(left(err));
|
||||||
|
_completer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Either<(), FlowyError> _isAuthCallbackDeeplink(Uri uri) {
|
Either<(), FlowyError> _isAuthCallbackDeeplink(Uri uri) {
|
||||||
|
@ -11,7 +11,7 @@ class DebugTask extends LaunchTask {
|
|||||||
Future<void> initialize(LaunchContext context) async {
|
Future<void> initialize(LaunchContext context) async {
|
||||||
// the hotkey manager is not supported on mobile
|
// the hotkey manager is not supported on mobile
|
||||||
if (PlatformExtension.isMobile && kDebugMode) {
|
if (PlatformExtension.isMobile && kDebugMode) {
|
||||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
await SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class InitPlatformServiceTask extends LaunchTask {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> initialize(LaunchContext context) async {
|
Future<void> initialize(LaunchContext context) async {
|
||||||
getIt<NetworkListener>().start();
|
return getIt<NetworkListener>().start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -69,7 +69,7 @@ Future<Directory> appFlowyApplicationDataDirectory() async {
|
|||||||
switch (integrationMode()) {
|
switch (integrationMode()) {
|
||||||
case IntegrationMode.develop:
|
case IntegrationMode.develop:
|
||||||
final Directory documentsDir = await getApplicationSupportDirectory()
|
final Directory documentsDir = await getApplicationSupportDirectory()
|
||||||
..create();
|
.then((directory) => directory.create());
|
||||||
return Directory(path.join(documentsDir.path, 'data_dev')).create();
|
return Directory(path.join(documentsDir.path, 'data_dev')).create();
|
||||||
case IntegrationMode.release:
|
case IntegrationMode.release:
|
||||||
final Directory documentsDir = await getApplicationSupportDirectory();
|
final Directory documentsDir = await getApplicationSupportDirectory();
|
||||||
|
@ -37,7 +37,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
title: title,
|
title: title,
|
||||||
);
|
);
|
||||||
|
|
||||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
await windowManager.show();
|
await windowManager.show();
|
||||||
await windowManager.focus();
|
await windowManager.focus();
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
super.onWindowResize();
|
super.onWindowResize();
|
||||||
|
|
||||||
final currentWindowSize = await windowManager.getSize();
|
final currentWindowSize = await windowManager.getSize();
|
||||||
WindowSizeManager().setSize(currentWindowSize);
|
return WindowSizeManager().setSize(currentWindowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -61,7 +61,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
super.onWindowMaximize();
|
super.onWindowMaximize();
|
||||||
|
|
||||||
final currentWindowSize = await windowManager.getSize();
|
final currentWindowSize = await windowManager.getSize();
|
||||||
WindowSizeManager().setSize(currentWindowSize);
|
return WindowSizeManager().setSize(currentWindowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -69,7 +69,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
super.onWindowMoved();
|
super.onWindowMoved();
|
||||||
|
|
||||||
final position = await windowManager.getPosition();
|
final position = await windowManager.getPosition();
|
||||||
WindowSizeManager().setPosition(position);
|
return WindowSizeManager().setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -228,7 +228,7 @@ Completer<Either<FlowyError, UserProfilePB>> supabaseLoginCompleter({
|
|||||||
user.email ?? user.newEmail ?? '',
|
user.email ?? user.newEmail ?? '',
|
||||||
);
|
);
|
||||||
// Only cancel the subscription if the Event is signedIn.
|
// Only cancel the subscription if the Event is signedIn.
|
||||||
subscription.cancel();
|
await subscription.cancel();
|
||||||
completer.complete(response);
|
completer.complete(response);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -32,11 +32,10 @@ class EncryptSecretBloc extends Bloc<EncryptSecretEvent, EncryptSecretState> {
|
|||||||
..encryptionSign = user.encryptionSign
|
..encryptionSign = user.encryptionSign
|
||||||
..encryptionType = user.encryptionType
|
..encryptionType = user.encryptionType
|
||||||
..userId = user.id;
|
..userId = user.id;
|
||||||
UserEventSetEncryptionSecret(payload).send().then((result) {
|
final result = await UserEventSetEncryptionSecret(payload).send();
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(EncryptSecretEvent.didFinishCheck(result));
|
add(EncryptSecretEvent.didFinishCheck(result));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
loadingState: const LoadingState.loading(),
|
loadingState: const LoadingState.loading(),
|
||||||
|
@ -27,7 +27,7 @@ class SupabaseRealtimeService {
|
|||||||
},
|
},
|
||||||
onInvalidAuth: (message) async {
|
onInvalidAuth: (message) async {
|
||||||
Log.error(message);
|
Log.error(message);
|
||||||
channel?.unsubscribe();
|
await channel?.unsubscribe();
|
||||||
channel = null;
|
channel = null;
|
||||||
if (!isLoggingOut) {
|
if (!isLoggingOut) {
|
||||||
isLoggingOut = true;
|
isLoggingOut = true;
|
||||||
|
@ -31,14 +31,10 @@ class WorkspaceErrorBloc
|
|||||||
final payload = ResetWorkspacePB.create()
|
final payload = ResetWorkspacePB.create()
|
||||||
..workspaceId = userFolder.workspaceId
|
..workspaceId = userFolder.workspaceId
|
||||||
..uid = userFolder.uid;
|
..uid = userFolder.uid;
|
||||||
UserEventResetWorkspace(payload).send().then(
|
final result = await UserEventResetWorkspace(payload).send();
|
||||||
(result) {
|
if (!isClosed) {
|
||||||
if (isClosed) {
|
add(WorkspaceErrorEvent.didResetWorkspace(result));
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
add(WorkspaceErrorEvent.didResetWorkspace(result));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
didResetWorkspace: (result) {
|
didResetWorkspace: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
|
@ -61,10 +61,10 @@ class AuthRouter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pushEncryptionScreen(
|
void pushEncryptionScreen(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
UserProfilePB userProfile,
|
UserProfilePB userProfile,
|
||||||
) async {
|
) {
|
||||||
// After log in,push EncryptionScreen on the top SignInScreen
|
// After log in,push EncryptionScreen on the top SignInScreen
|
||||||
context.push(
|
context.push(
|
||||||
EncryptSecretScreen.routeName,
|
EncryptSecretScreen.routeName,
|
||||||
@ -104,12 +104,11 @@ class SplashRouter {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
FolderEventGetCurrentWorkspaceSetting().send().then((result) {
|
final result = await FolderEventGetCurrentWorkspaceSetting().send();
|
||||||
result.fold(
|
result.fold(
|
||||||
(workspaceSettingPB) => pushHomeScreen(context),
|
(workspaceSettingPB) => pushHomeScreen(context),
|
||||||
(r) => null,
|
(r) => null,
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushHomeScreen(
|
void pushHomeScreen(
|
||||||
|
@ -102,7 +102,7 @@ class MobileSignInScreen extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
decoration: TextDecoration.underline,
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () {
|
||||||
context.push(MobileLaunchSettingsPage.routeName);
|
context.push(MobileLaunchSettingsPage.routeName);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -68,7 +68,7 @@ class SplashScreen extends StatelessWidget {
|
|||||||
|
|
||||||
/// After a user is authenticated, this function checks if encryption is required.
|
/// After a user is authenticated, this function checks if encryption is required.
|
||||||
final result = await UserEventCheckEncryptionSign().send();
|
final result = await UserEventCheckEncryptionSign().send();
|
||||||
result.fold(
|
await result.fold(
|
||||||
(check) async {
|
(check) async {
|
||||||
/// If encryption is needed, the user is navigated to the encryption screen.
|
/// If encryption is needed, the user is navigated to the encryption screen.
|
||||||
/// Otherwise, it fetches the current workspace for the user and navigates them
|
/// Otherwise, it fetches the current workspace for the user and navigates them
|
||||||
|
@ -28,7 +28,7 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
|
|||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _userListener.stop();
|
await _userListener.stop();
|
||||||
await _userWorkspaceListener.stop();
|
await _userWorkspaceListener.stop();
|
||||||
super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
|
@ -68,7 +68,7 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
|
|||||||
/// with the AppTheme named [themeName].
|
/// with the AppTheme named [themeName].
|
||||||
Future<void> setTheme(String themeName) async {
|
Future<void> setTheme(String themeName) async {
|
||||||
_appearanceSettings.theme = themeName;
|
_appearanceSettings.theme = themeName;
|
||||||
_saveAppearanceSettings();
|
unawaited(_saveAppearanceSettings());
|
||||||
emit(state.copyWith(appTheme: await AppTheme.fromName(themeName)));
|
emit(state.copyWith(appTheme: await AppTheme.fromName(themeName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,25 +236,21 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveDateTimeSettings() async {
|
Future<void> _saveDateTimeSettings() async {
|
||||||
UserSettingsBackendService()
|
final result = await UserSettingsBackendService()
|
||||||
.setDateTimeSettings(_dateTimeSettings)
|
.setDateTimeSettings(_dateTimeSettings);
|
||||||
.then((result) {
|
result.fold(
|
||||||
result.fold(
|
(error) => Log.error(error),
|
||||||
(error) => Log.error(error),
|
(_) => null,
|
||||||
(_) => null,
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveAppearanceSettings() async {
|
Future<void> _saveAppearanceSettings() async {
|
||||||
UserSettingsBackendService()
|
final result = await UserSettingsBackendService()
|
||||||
.setAppearanceSetting(_appearanceSettings)
|
.setAppearanceSetting(_appearanceSettings);
|
||||||
.then((result) {
|
result.fold(
|
||||||
result.fold(
|
(l) => null,
|
||||||
(l) => null,
|
(error) => Log.error(error),
|
||||||
(error) => Log.error(error),
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class AppFlowyCloudSettingBloc
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
_listener.stop();
|
await _listener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class ApplicationDataStorage {
|
|||||||
await directory.create(recursive: true);
|
await directory.create(recursive: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setPath(path);
|
await setPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setPath(String path) async {
|
Future<void> setPath(String path) async {
|
||||||
|
@ -38,20 +38,18 @@ class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
_saveNotificationSettings();
|
await _saveNotificationSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveNotificationSettings() async {
|
Future<void> _saveNotificationSettings() async {
|
||||||
await _initCompleter.future;
|
await _initCompleter.future;
|
||||||
|
|
||||||
UserSettingsBackendService()
|
final result = await UserSettingsBackendService()
|
||||||
.setNotificationSettings(_notificationSettings)
|
.setNotificationSettings(_notificationSettings);
|
||||||
.then((result) {
|
result.fold(
|
||||||
result.fold(
|
(error) => Log.error(error),
|
||||||
(error) => Log.error(error),
|
(r) => null,
|
||||||
(r) => null,
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,11 @@ class SettingFileImportBloc
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(loadingState: const LoadingState.loading()),
|
state.copyWith(loadingState: const LoadingState.loading()),
|
||||||
);
|
);
|
||||||
UserEventImportAppFlowyDataFolder(payload).send().then((result) {
|
final result =
|
||||||
if (!isClosed) {
|
await UserEventImportAppFlowyDataFolder(payload).send();
|
||||||
add(SettingFileImportEvent.finishImport(result));
|
if (!isClosed) {
|
||||||
}
|
add(SettingFileImportEvent.finishImport(result));
|
||||||
});
|
}
|
||||||
},
|
},
|
||||||
finishImport: (result) {
|
finishImport: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
|
@ -32,7 +32,7 @@ class SettingsDialogBloc
|
|||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _userListener.stop();
|
await _userListener.stop();
|
||||||
super.close();
|
await super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
|
@ -26,7 +26,7 @@ class SupabaseCloudSettingBloc
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
_listener.stop();
|
await _listener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ class SupabaseCloudSettingBloc
|
|||||||
},
|
},
|
||||||
enableSync: (bool enable) async {
|
enableSync: (bool enable) async {
|
||||||
final update = UpdateCloudConfigPB.create()..enableSync = enable;
|
final update = UpdateCloudConfigPB.create()..enableSync = enable;
|
||||||
updateCloudConfig(update);
|
await updateCloudConfig(update);
|
||||||
},
|
},
|
||||||
didReceiveSetting: (CloudSettingPB setting) {
|
didReceiveSetting: (CloudSettingPB setting) {
|
||||||
emit(
|
emit(
|
||||||
|
@ -24,7 +24,7 @@ class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
|
|||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _userListener.stop();
|
await _userListener.stop();
|
||||||
super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
|
@ -134,7 +134,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
(error) => state.copyWith(successOrFailure: right(error)),
|
(error) => state.copyWith(successOrFailure: right(error)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
RecentService().updateRecentViews([view.id], false);
|
await RecentService().updateRecentViews([view.id], false);
|
||||||
},
|
},
|
||||||
duplicate: (e) async {
|
duplicate: (e) async {
|
||||||
final result = await ViewBackendService.duplicate(view: view);
|
final result = await ViewBackendService.duplicate(view: view);
|
||||||
|
@ -23,7 +23,7 @@ Future<void> createViewAndShowRenameDialogIfNeeded(
|
|||||||
);
|
);
|
||||||
final showRenameDialog = value.fold(() => false, (r) => r);
|
final showRenameDialog = value.fold(() => false, (r) => r);
|
||||||
if (context.mounted && showRenameDialog) {
|
if (context.mounted && showRenameDialog) {
|
||||||
NavigatorTextFieldDialog(
|
await NavigatorTextFieldDialog(
|
||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
autoSelectAllText: true,
|
autoSelectAllText: true,
|
||||||
|
@ -301,7 +301,7 @@ class EmojiPickerState extends State<EmojiPicker> {
|
|||||||
) async {
|
) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
final emojiJson = jsonEncode(emojis);
|
final emojiJson = jsonEncode(emojis);
|
||||||
prefs.setString(title, emojiJson);
|
await prefs.setString(title, emojiJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns list of recently used emoji from cache
|
// Returns list of recently used emoji from cache
|
||||||
@ -335,6 +335,6 @@ class EmojiPickerState extends State<EmojiPicker> {
|
|||||||
min(widget.config.recentsLimit, recentEmojiList.length),
|
min(widget.config.recentsLimit, recentEmojiList.length),
|
||||||
);
|
);
|
||||||
// save locally
|
// save locally
|
||||||
prefs.setString('recent', jsonEncode(recentEmojiList));
|
await prefs.setString('recent', jsonEncode(recentEmojiList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class AppFlowyCloudViewSetting extends StatelessWidget {
|
|||||||
const AppFlowyCloudEnableSync(),
|
const AppFlowyCloudEnableSync(),
|
||||||
const VSpace(12),
|
const VSpace(12),
|
||||||
RestartButton(
|
RestartButton(
|
||||||
onClick: () async {
|
onClick: () {
|
||||||
NavigatorAlertDialog(
|
NavigatorAlertDialog(
|
||||||
title: LocaleKeys.settings_menu_restartAppTip.tr(),
|
title: LocaleKeys.settings_menu_restartAppTip.tr(),
|
||||||
confirm: () async {
|
confirm: () async {
|
||||||
@ -176,7 +176,7 @@ class AppFlowyCloudURLs extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const VSpace(8),
|
const VSpace(8),
|
||||||
RestartButton(
|
RestartButton(
|
||||||
onClick: () async {
|
onClick: () {
|
||||||
NavigatorAlertDialog(
|
NavigatorAlertDialog(
|
||||||
title: LocaleKeys.settings_menu_restartAppTip.tr(),
|
title: LocaleKeys.settings_menu_restartAppTip.tr(),
|
||||||
confirm: () {
|
confirm: () {
|
||||||
|
@ -235,7 +235,7 @@ class _OpenStorageButton extends StatelessWidget {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final uri = Directory(usingPath).uri;
|
final uri = Directory(usingPath).uri;
|
||||||
if (await canLaunchUrl(uri)) {
|
if (await canLaunchUrl(uri)) {
|
||||||
launchUrl(uri);
|
await launchUrl(uri);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -534,7 +534,7 @@ class SettingLogoutButton extends StatelessWidget {
|
|||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () {
|
||||||
NavigatorAlertDialog(
|
NavigatorAlertDialog(
|
||||||
title: logoutPromptMessage(),
|
title: logoutPromptMessage(),
|
||||||
confirm: () async {
|
confirm: () async {
|
||||||
|
@ -34,7 +34,7 @@ class ThemeUploadLearnMoreButton extends StatelessWidget {
|
|||||||
await launchUrl(uri);
|
await launchUrl(uri);
|
||||||
} else {
|
} else {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Dialogs.show(
|
await Dialogs.show(
|
||||||
context,
|
context,
|
||||||
child: FlowyDialog(
|
child: FlowyDialog(
|
||||||
child: FlowyErrorPage.message(
|
child: FlowyErrorPage.message(
|
||||||
|
@ -129,10 +129,10 @@ class _BubbleActionListState extends State<BubbleActionList> {
|
|||||||
|
|
||||||
class _DebugToast {
|
class _DebugToast {
|
||||||
void show() async {
|
void show() async {
|
||||||
var debugInfo = "";
|
String debugInfo = "";
|
||||||
debugInfo += await _getDeviceInfo();
|
debugInfo += await _getDeviceInfo();
|
||||||
debugInfo += await _getDocumentPath();
|
debugInfo += await _getDocumentPath();
|
||||||
Clipboard.setData(ClipboardData(text: debugInfo));
|
await Clipboard.setData(ClipboardData(text: debugInfo));
|
||||||
|
|
||||||
showMessageToast(LocaleKeys.questionBubble_debug_success.tr());
|
showMessageToast(LocaleKeys.questionBubble_debug_success.tr());
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ void main() {
|
|||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
final textField = context.textFieldContext();
|
final textField = context.textFieldContext();
|
||||||
service.insertTextFilter(
|
await service.insertTextFilter(
|
||||||
fieldId: textField.id,
|
fieldId: textField.id,
|
||||||
condition: TextFilterConditionPB.TextIsEmpty,
|
condition: TextFilterConditionPB.TextIsEmpty,
|
||||||
content: "",
|
content: "",
|
||||||
@ -94,11 +94,11 @@ void main() {
|
|||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
final controller = context.makeTextCellController(0);
|
final controller = context.makeTextCellController(0);
|
||||||
controller.saveCellData("edit text cell content");
|
await controller.saveCellData("edit text cell content");
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
assert(gridBloc.state.rowInfos.length == 2);
|
assert(gridBloc.state.rowInfos.length == 2);
|
||||||
|
|
||||||
controller.saveCellData("");
|
await controller.saveCellData("");
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
assert(gridBloc.state.rowInfos.length == 3);
|
assert(gridBloc.state.rowInfos.length == 3);
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@ void main() {
|
|||||||
final service = FilterBackendService(viewId: context.gridView.id);
|
final service = FilterBackendService(viewId: context.gridView.id);
|
||||||
|
|
||||||
final controller = context.makeCheckboxCellController(0);
|
final controller = context.makeCheckboxCellController(0);
|
||||||
controller.saveCellData("Yes");
|
await controller.saveCellData("Yes");
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
// create a new filter
|
// create a new filter
|
||||||
@ -37,7 +37,7 @@ void main() {
|
|||||||
final service = FilterBackendService(viewId: context.gridView.id);
|
final service = FilterBackendService(viewId: context.gridView.id);
|
||||||
|
|
||||||
final controller = context.makeCheckboxCellController(0);
|
final controller = context.makeCheckboxCellController(0);
|
||||||
controller.saveCellData("Yes");
|
await controller.saveCellData("Yes");
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
// create a new filter
|
// create a new filter
|
||||||
|
@ -21,7 +21,6 @@ Future<GridTestContext> createTestFilterGrid(AppFlowyGridTest gridTest) async {
|
|||||||
final result = await context.gridController.open();
|
final result = await context.gridController.open();
|
||||||
|
|
||||||
await editCells(context);
|
await editCells(context);
|
||||||
await gridResponseFuture(milliseconds: 500);
|
|
||||||
result.fold((l) => null, (r) => throw Exception(r));
|
result.fold((l) => null, (r) => throw Exception(r));
|
||||||
return context;
|
return context;
|
||||||
},
|
},
|
||||||
@ -36,7 +35,8 @@ Future<void> editCells(GridTestContext context) async {
|
|||||||
final controller0 = context.makeTextCellController(0);
|
final controller0 = context.makeTextCellController(0);
|
||||||
final controller1 = context.makeTextCellController(1);
|
final controller1 = context.makeTextCellController(1);
|
||||||
|
|
||||||
controller0.saveCellData('A');
|
await controller0.saveCellData('A');
|
||||||
|
await gridResponseFuture();
|
||||||
|
await controller1.saveCellData('B');
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
controller1.saveCellData('B');
|
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ void main() {
|
|||||||
commandShortcutEvent.updateCommand(command: newCommand);
|
commandShortcutEvent.updateCommand(command: newCommand);
|
||||||
|
|
||||||
//saving the updated shortcuts
|
//saving the updated shortcuts
|
||||||
service.saveAllShortcuts(currentCommandShortcuts);
|
await service.saveAllShortcuts(currentCommandShortcuts);
|
||||||
|
|
||||||
//now directly fetching the shortcuts from loadShortcuts
|
//now directly fetching the shortcuts from loadShortcuts
|
||||||
final commandShortcuts = await service.getCustomizeShortcuts();
|
final commandShortcuts = await service.getCustomizeShortcuts();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:appflowy/main.dart';
|
|
||||||
import 'package:appflowy/startup/launch_configuration.dart';
|
import 'package:appflowy/startup/launch_configuration.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||||
@ -11,18 +10,8 @@ import 'package:flowy_infra/uuid.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:integration_test/integration_test.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class AppFlowyIntegrateTest {
|
|
||||||
static Future<AppFlowyIntegrateTest> ensureInitialized() async {
|
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
SharedPreferences.setMockInitialValues({});
|
|
||||||
main();
|
|
||||||
return AppFlowyIntegrateTest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AppFlowyUnitTest {
|
class AppFlowyUnitTest {
|
||||||
late UserProfilePB userProfile;
|
late UserProfilePB userProfile;
|
||||||
late UserBackendService userService;
|
late UserBackendService userService;
|
||||||
|
Reference in New Issue
Block a user