mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-09-23 07:27:58 +00:00
feat: delete the previous image when the cover changes in local mode (#6368)
* remove unecessary images from localstorage * feat: Add handler for deleting previous cover image on cover image change * fix: add local image case for versions after 0.5.5 * fix: add try catch block and delete action to bottom of function * chore: add test case for uploading and deleting image in localmode --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
parent
73463cd7e3
commit
b965a5f3ae
@ -1,15 +1,23 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/header/document_cover_widget.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
||||
import 'package:appflowy/shared/icon_emoji_picker/flowy_icon_emoji_picker.dart';
|
||||
import 'package:appflowy/shared/icon_emoji_picker/recent_icons.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import '../../shared/emoji.dart';
|
||||
import '../../shared/mock/mock_file_picker.dart';
|
||||
import '../../shared/util.dart';
|
||||
|
||||
void main() {
|
||||
@ -60,6 +68,59 @@ void main() {
|
||||
tester.expectToSeeNoDocumentCover();
|
||||
});
|
||||
|
||||
testWidgets('document cover local image tests', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
||||
tester.expectToSeeNoDocumentCover();
|
||||
|
||||
// Hover over cover toolbar to show 'Add Cover' and 'Add Icon' buttons
|
||||
await tester.editor.hoverOnCoverToolbar();
|
||||
|
||||
// Insert a document cover
|
||||
await tester.editor.tapOnAddCover();
|
||||
tester.expectToSeeDocumentCover(CoverType.asset);
|
||||
|
||||
// Hover over the cover to show the 'Change Cover' and delete buttons
|
||||
await tester.editor.hoverOnCover();
|
||||
tester.expectChangeCoverAndDeleteButton();
|
||||
|
||||
// Change cover to a local image image
|
||||
final imagePath = await rootBundle.load('assets/test/images/sample.jpeg');
|
||||
final tempDirectory = await getTemporaryDirectory();
|
||||
final localImagePath = p.join(tempDirectory.path, 'sample.jpeg');
|
||||
final imageFile = File(localImagePath)
|
||||
..writeAsBytesSync(imagePath.buffer.asUint8List());
|
||||
|
||||
await tester.editor.hoverOnCover();
|
||||
await tester.editor.tapOnChangeCover();
|
||||
|
||||
final uploadButton = find.findTextInFlowyText(
|
||||
LocaleKeys.document_imageBlock_upload_label.tr(),
|
||||
);
|
||||
await tester.tapButton(uploadButton);
|
||||
|
||||
mockPickFilePaths(paths: [localImagePath]);
|
||||
await tester.tapButtonWithName(
|
||||
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
tester.expectToSeeDocumentCover(CoverType.file);
|
||||
|
||||
// Remove the cover
|
||||
await tester.editor.hoverOnCover();
|
||||
await tester.editor.tapOnRemoveCover();
|
||||
tester.expectToSeeNoDocumentCover();
|
||||
|
||||
// Test if deleteImageFromLocalStorage(localImagePath) function is called once
|
||||
await tester.pump(kDoubleTapTimeout);
|
||||
expect(deleteImageTestCounter, 1);
|
||||
|
||||
// delete temp files
|
||||
await imageFile.delete();
|
||||
});
|
||||
|
||||
testWidgets('document icon tests', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
|
@ -763,15 +763,29 @@ class DocumentCoverState extends State<DocumentCover> {
|
||||
}
|
||||
|
||||
Future<void> onCoverChanged(CoverType type, String? details) async {
|
||||
if (type == CoverType.file && details != null && !isURL(details)) {
|
||||
final previousType = CoverType.fromString(
|
||||
widget.node.attributes[DocumentHeaderBlockKeys.coverType],
|
||||
);
|
||||
final previousDetails =
|
||||
widget.node.attributes[DocumentHeaderBlockKeys.coverDetails];
|
||||
|
||||
bool isFileType(CoverType type, String? details) =>
|
||||
type == CoverType.file && details != null && !isURL(details);
|
||||
|
||||
if (isFileType(type, details)) {
|
||||
if (_isLocalMode()) {
|
||||
details = await saveImageToLocalStorage(details);
|
||||
details = await saveImageToLocalStorage(details!);
|
||||
} else {
|
||||
// else we should save the image to cloud storage
|
||||
(details, _) = await saveImageToCloudStorage(details, widget.view.id);
|
||||
(details, _) = await saveImageToCloudStorage(details!, widget.view.id);
|
||||
}
|
||||
}
|
||||
widget.onChangeCover(type, details);
|
||||
|
||||
// After cover change,delete from localstorage if previous cover was image type
|
||||
if (isFileType(previousType, previousDetails) && _isLocalMode()) {
|
||||
await deleteImageFromLocalStorage(previousDetails);
|
||||
}
|
||||
}
|
||||
|
||||
void setOverlayButtonsHidden(bool value) {
|
||||
|
@ -117,3 +117,16 @@ Future<List<ImageBlockData>> extractAndUploadImages(
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
int deleteImageTestCounter = 0;
|
||||
|
||||
Future<void> deleteImageFromLocalStorage(String localImagePath) async {
|
||||
try {
|
||||
await File(localImagePath)
|
||||
.delete()
|
||||
.whenComplete(() => deleteImageTestCounter++);
|
||||
} catch (e) {
|
||||
Log.error('cannot delete image file', e);
|
||||
}
|
||||
}
|
||||
|
@ -226,6 +226,14 @@ class EditorMigration {
|
||||
},
|
||||
};
|
||||
}
|
||||
} else {
|
||||
extra = {
|
||||
ViewExtKeys.coverKey: {
|
||||
ViewExtKeys.coverTypeKey:
|
||||
PageStyleCoverImageType.localImage.toString(),
|
||||
ViewExtKeys.coverValueKey: coverDetails,
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user