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

Paintroid-638 : Add a placeholder name when saving #50

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: a62623f56f2d1d0e85a4a3c73509cd2832d5c86f

COCOAPODS: 1.14.3
COCOAPODS: 1.15.0
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ void main() {
expect(saveProjectButton, findsOneWidget);

await tester.tap(saveProjectButton);
when(fileService.getNextProjectNumber()).thenAnswer((_) async => 1);
await tester.pumpAndSettle();

final textFormField = find.widgetWithText(TextFormField, 'Project name');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,13 @@ class MockIFileService extends _i1.Mock implements _i9.IFileService {
_i1.throwOnMissingStub(this);
}

@override
Future<int> getNextProjectNumber() => super.noSuchMethod(
Invocation.method(#getNextProjectNumber, []),
returnValue: Future<int>.value(1),
returnValueForMissingStub: Future<int>.value(-1),
);

@override
_i3.Future<_i5.Result<_i11.File, _i9.Failure>> save(
String? filename,
Expand Down
54 changes: 52 additions & 2 deletions packages/io_library/lib/src/service/file_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:io_library/io_library.dart';
import 'package:oxidized/oxidized.dart';

import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

abstract class IFileService {
Future<Result<File, Failure>> save(String filename, Uint8List data);
Expand All @@ -18,6 +19,13 @@ abstract class IFileService {

Result<File, Failure> getFile(String path);


// Declare the new methods in the interface
vishad-tyagi marked this conversation as resolved.
Show resolved Hide resolved
Future<int> getNextImageNumber();
Future<int> getNextProjectNumber();
//end


static final provider = Provider<IFileService>((ref) => FileService());

Future<bool> checkIfFileExistsInApplicationDirectory(String fileName);
Expand All @@ -31,7 +39,7 @@ class FileService with LoggableMixin implements IFileService {
Future<Result<File, Failure>> pick() async {
try {
final result =
await FilePicker.platform.pickFiles(allowCompression: false);
await FilePicker.platform.pickFiles(allowCompression: false);
if (result == null) {
return const Result.err(LoadImageFailure.userCancelled);
}
Expand All @@ -54,7 +62,7 @@ class FileService with LoggableMixin implements IFileService {
return const Result.err(SaveImageFailure.userCancelled);
}
final file =
await File('$saveDirectory/$filename').create(recursive: true);
await File('$saveDirectory/$filename').create(recursive: true);
return Result.ok(await file.writeAsBytes(data));
} catch (err, stacktrace) {
logger.severe('Could not save file', err, stacktrace);
Expand Down Expand Up @@ -107,4 +115,46 @@ class FileService with LoggableMixin implements IFileService {
return const Result.err(LoadImageFailure.unidentified);
}
}

vishad-tyagi marked this conversation as resolved.
Show resolved Hide resolved



@override
Future<int> getNextImageNumber() async {
final prefs = await SharedPreferences.getInstance();
int lastNumber = prefs.getInt('lastImageNumber') ?? 0;
int nextNumber = lastNumber + 1;
await prefs.setInt('lastImageNumber', nextNumber);
return nextNumber;
}




@override
Future<int> getNextProjectNumber() async {
final directory = await getApplicationDocumentsDirectory();
final files = await directory.list().toList();
int maxNum = 0;

for (var file in files) {
if (file is File) {
final fileName = file.path.split('/').last;

if (fileName.startsWith('project')) {
final match = RegExp(r'project(\d+)').firstMatch(fileName);
if (match != null) {
final num = int.tryParse(match.group(1)!) ?? 0;
vishad-tyagi marked this conversation as resolved.
Show resolved Hide resolved

if (num > maxNum) maxNum = num;
}
}
}
}

return maxNum + 1;
}



}
41 changes: 36 additions & 5 deletions packages/io_library/lib/src/ui/save_image_dialog.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
import 'package:io_library/io_library.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';


/// Returns [null] if user dismissed the dialog by tapping outside
Future<ImageMetaData?> showSaveImageDialog(
BuildContext context, bool savingProject) =>
BuildContext context, bool savingProject) =>
showGeneralDialog<ImageMetaData?>(
context: context,
pageBuilder: (_, __, ___) =>
SaveImageDialog(savingProject: savingProject),
barrierDismissible: true,
barrierLabel: 'Dismiss save image dialog box');

class SaveImageDialog extends StatefulWidget {
class SaveImageDialog extends ConsumerStatefulWidget {
final bool savingProject;

const SaveImageDialog({Key? key, required this.savingProject})
: super(key: key);

@override
State<SaveImageDialog> createState() => _SaveImageDialogState();
SaveImageDialogState createState() => SaveImageDialogState();
}

class _SaveImageDialogState extends State<SaveImageDialog> {
class SaveImageDialogState extends ConsumerState<SaveImageDialog> {
final TextEditingController nameFieldController = TextEditingController();
final formKey = GlobalKey<FormState>(debugLabel: 'SaveImageDialog Form');
var selectedFormat = ImageFormat.jpg;
Expand All @@ -31,12 +33,41 @@ class _SaveImageDialogState extends State<SaveImageDialog> {
@override
void initState() {
super.initState();

if (widget.savingProject) {
selectedFormat = ImageFormat.catrobatImage;
}


WidgetsBinding.instance.addPostFrameCallback((_) {
_setDefaultFileName();
});
}




Future<void> _setDefaultFileName() async {
final fileService = ref.read(IFileService.provider);
String defaultName;
if (widget.savingProject) {
final nextNumber = await fileService.getNextProjectNumber();
defaultName = 'project$nextNumber';
}
else {

final nextNumber = await fileService.getNextImageNumber();
defaultName = 'image$nextNumber';

}

setState(() {
nameFieldController.text = defaultName;
});
}




void _dismissDialogWithData() {
late ImageMetaData data;
switch (selectedFormat) {
Expand Down
1 change: 1 addition & 0 deletions packages/io_library/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies:
oxidized: ^5.2.0
intl: ^0.18.0
json_annotation: ^4.8.1
shared_preferences: ^2.0.15

# Internal packages:
component_library:
Expand Down
Loading