Skip to content

Commit

Permalink
Merge pull request #48 from koji-1009/feat/sealed_class
Browse files Browse the repository at this point in the history
refactor: Update TaroResizeOption to use sealed classes
  • Loading branch information
koji-1009 authored Aug 1, 2024
2 parents a77a9b9 + 1a614ad commit 40c0c85
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 134 deletions.
12 changes: 4 additions & 8 deletions lib/src/taro.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ class Taro {
final _loader = TaroLoader();

/// The [TaroResizeOption] used to resize images.
TaroResizeOption _resizeOption = const (
mode: TaroResizeMode.skip,
maxWidth: null,
maxHeight: null,
);
TaroResizeOption _resizeOption = const TaroResizeOptionSkip();

/// The [TaroResizeOption] used to resize images.
/// Changing this option will affect all image loading.
Expand Down Expand Up @@ -94,10 +90,10 @@ class Taro {
headerOption: headerOption ?? _headerOption,
);

if (resizeOption?.mode == TaroResizeMode.memory) {
if (resizeOption is TaroResizeOptionMemory) {
return ResizeImage.resizeIfNeeded(
resizeOption?.maxWidth,
resizeOption?.maxHeight,
resizeOption.maxWidth,
resizeOption.maxHeight,
image,
);
}
Expand Down
187 changes: 94 additions & 93 deletions lib/src/taro_resizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,116 +16,117 @@ class TaroResizer {
required String contentType,
required TaroResizeOption resizeOption,
}) async {
if (resizeOption.mode case TaroResizeMode.skip || TaroResizeMode.memory) {
// do nothing
return (
bytes: bytes,
contentType: contentType,
);
}
switch (resizeOption) {
case TaroResizeOptionSkip() || TaroResizeOptionMemory():
// do nothing
return (
bytes: bytes,
contentType: contentType,
);
case TaroResizeOptionDisk(
format: final optionFormat,
maxWidth: final optionMaxWidth,
maxHeight: final optionMaxHeight,
):
final originalImage = img.decodeImage(bytes);
if (originalImage == null) {
return throw TaroResizeException(
exception: Exception('Failed to decode image.'),
);
}

final originalImage = img.decodeImage(bytes);
if (originalImage == null) {
return throw TaroResizeException(
exception: Exception('Failed to decode image.'),
);
}
final int maxWidth;
if (optionMaxWidth != null) {
maxWidth = min(optionMaxWidth, originalImage.width);
} else {
maxWidth = originalImage.width;
}

final int maxWidth;
if (resizeOption.maxWidth != null) {
maxWidth = min(resizeOption.maxWidth!, originalImage.width);
} else {
maxWidth = originalImage.width;
}
final int maxHeight;
if (optionMaxHeight != null) {
maxHeight = min(optionMaxHeight, originalImage.height);
} else {
maxHeight = originalImage.height;
}

final int maxHeight;
if (resizeOption.maxHeight != null) {
maxHeight = min(resizeOption.maxHeight!, originalImage.height);
} else {
maxHeight = originalImage.height;
}
if (maxWidth == originalImage.width &&
maxHeight == originalImage.height) {
return (
bytes: bytes,
contentType: contentType,
);
}

if (maxWidth == originalImage.width && maxHeight == originalImage.height) {
return (
bytes: bytes,
contentType: contentType,
);
}
final cmd = img.Command()
..image(originalImage)
..copyResize(
width: maxWidth,
height: maxHeight,
);

final cmd = img.Command()
..image(originalImage)
..copyResize(
width: maxWidth,
height: maxHeight,
);
final String encodeImageType;
switch (optionFormat) {
case TaroResizeFormat.original:
switch (contentType) {
case 'image/gif':
case 'image/jpeg':
case 'image/png':
case 'image/bmp':
case 'image/x-icon':
case 'image/tiff':
encodeImageType = contentType;
default:
encodeImageType = 'image/png';
}
case TaroResizeFormat.gif:
encodeImageType = 'image/gif';
case TaroResizeFormat.jpeg:
encodeImageType = 'image/jpeg';
case TaroResizeFormat.png:
encodeImageType = 'image/png';
case TaroResizeFormat.bmp:
encodeImageType = 'image/bmp';
case TaroResizeFormat.ico:
encodeImageType = 'image/x-icon';
case TaroResizeFormat.tiff:
encodeImageType = 'image/tiff';
}

final String encodeImageType;
switch (resizeOption.mode) {
case TaroResizeMode.skip:
// this case is not possible
throw Exception('This case is not possible.');
case TaroResizeMode.original:
switch (contentType) {
switch (encodeImageType) {
case 'image/gif':
cmd.encodeGif();
case 'image/jpeg':
cmd.encodeJpg();
case 'image/png':
cmd.encodePng();
case 'image/bmp':
cmd.encodeBmp();
case 'image/x-icon':
cmd.encodeIco();
case 'image/tiff':
encodeImageType = contentType;
cmd.encodeTiff();
default:
encodeImageType = 'image/png';
// if the contentType is not supported, encode the image to png
cmd.encodePng();
}
case TaroResizeMode.gif:
encodeImageType = 'image/gif';
case TaroResizeMode.jpeg:
encodeImageType = 'image/jpeg';
case TaroResizeMode.png:
encodeImageType = 'image/png';
case TaroResizeMode.bmp:
encodeImageType = 'image/bmp';
case TaroResizeMode.ico:
encodeImageType = 'image/x-icon';
case TaroResizeMode.tiff:
encodeImageType = 'image/tiff';
default:
encodeImageType = 'image/png';
}

switch (encodeImageType) {
case 'image/gif':
cmd.encodeGif();
case 'image/jpeg':
cmd.encodeJpg();
case 'image/png':
cmd.encodePng();
case 'image/bmp':
cmd.encodeBmp();
case 'image/x-icon':
cmd.encodeIco();
case 'image/tiff':
cmd.encodeTiff();
default:
// if the contentType is not supported, encode the image to png
cmd.encodePng();
}
final Uint8List? result;
try {
result = await cmd.getBytesThread();
} on Exception catch (exception) {
throw TaroResizeException(
exception: exception,
);
}

final Uint8List? result;
try {
result = await cmd.getBytesThread();
} on Exception catch (exception) {
throw TaroResizeException(
exception: exception,
);
}
if (result == null) {
throw const TaroResizeFailedException();
}

if (result == null) {
throw const TaroResizeFailedException();
return (
bytes: result,
contentType: encodeImageType,
);
}

return (
bytes: result,
contentType: encodeImageType,
);
}
}
68 changes: 45 additions & 23 deletions lib/src/taro_type.dart
Original file line number Diff line number Diff line change
@@ -1,43 +1,65 @@
/// [TaroRequestOption] is used to configure the options for a resizing request.
typedef TaroResizeOption = ({
/// The resize mode of the image.
TaroResizeMode mode,
/// The [TaroResizeOption] is used to determine how images are resized and saved.
/// Please refer to [https://pub.dev/packages/image] for supported formats.
sealed class TaroResizeOption {
const TaroResizeOption();
}

/// The maximum width of the image. If null, the width is not limited.
int? maxWidth,
/// The image is not resized, saved original size and format.
class TaroResizeOptionSkip extends TaroResizeOption {
const TaroResizeOptionSkip();
}

/// The maximum height of the image. If null, the height is not limited.
int? maxHeight,
});
/// The image is resized in memory, saved original size and format.
class TaroResizeOptionMemory extends TaroResizeOption {
const TaroResizeOptionMemory({
required this.maxWidth,
required this.maxHeight,
});

/// The [TaroResizeMode] enum is used to determine how images are resized.
/// Please refer to [https://pub.dev/packages/image] for supported formats.
enum TaroResizeMode {
/// The image is not resized.
skip,
/// The maximum width of the image.
final int maxWidth;

/// The image is resized and saved original image.
memory,
/// The maximum height of the image.
final int maxHeight;
}

class TaroResizeOptionDisk extends TaroResizeOption {
const TaroResizeOptionDisk({
required this.format,
this.maxWidth,
this.maxHeight,
});

/// The format of the image.
final TaroResizeFormat format;

/// The maximum width of the image. If null, the width is not limited.
final int? maxWidth;

/// The maximum height of the image. If null, the height is not limited.
final int? maxHeight;
}

/// The image is resized to the original contentType and saved cache.
enum TaroResizeFormat {
/// The original format of the image.
original,

/// The image is resized to a gif and saved cache.
/// The image is saved as a gif.
gif,

/// The image is resized to a jpg and saved cache.
/// The image is saved as a jpeg.
jpeg,

/// The image is resized to a png and saved cache.
/// The image is saved as a png.
png,

/// The image is resized to a bmp and saved cache.
/// The image is saved as a bmp.
bmp,

/// The image is resized to a ico and saved cache.
/// The image is saved as an icon.
ico,

/// The image is resized to a tiff and saved cache.
/// The image is saved as a tiff.
tiff,
}

Expand Down
6 changes: 1 addition & 5 deletions test/taro_loader_network_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ void main() {
);

final bodyBytes = Uint8List(100);
const resizeOption = (
mode: TaroResizeMode.skip,
maxWidth: null,
maxHeight: null,
);
const resizeOption = TaroResizeOptionSkip();
const headerOption = (
checkMaxAgeIfExist: false,
ifThrowMaxAgeHeaderError: false,
Expand Down
6 changes: 1 addition & 5 deletions test/taro_loader_network_test.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,7 @@ class MockTaroResizer extends _i1.Mock implements _i5.TaroResizer {
_i3.Future<({_i4.Uint8List bytes, String contentType})> resizeIfNeeded({
required _i4.Uint8List? bytes,
required String? contentType,
required ({
int? maxHeight,
int? maxWidth,
_i6.TaroResizeMode mode
})? resizeOption,
required _i6.TaroResizeOption? resizeOption,
}) =>
(super.noSuchMethod(
Invocation.method(
Expand Down

0 comments on commit 40c0c85

Please sign in to comment.