Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

delete previous image on cover change #6368

Merged
merged 9 commits into from
Dec 31, 2024
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,14 @@ class EditorMigration {
},
};
}
} else {
extra = {
ViewExtKeys.coverKey: {
ViewExtKeys.coverTypeKey:
PageStyleCoverImageType.localImage.toString(),
ViewExtKeys.coverValueKey: coverDetails,
},
};
}
break;
default:
Expand Down
Loading