Skip to content

Commit

Permalink
chore: prepare v3.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TesteurManiak committed Aug 3, 2023
1 parent a36fa04 commit 435cd33
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 146 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ example/ios/Flutter/
example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java

example/android/local.properties

custom_lint.log
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.1.0

* Updated Dart SDK constraint to `>=3.0.0 <4.0.0`
* Updated linting rules
* Changed license to MIT

## 3.0.0+1

* Fixed README.md
Expand Down
64 changes: 4 additions & 60 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,61 +1,5 @@
# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
# Google internally enforced rules. See README.md for more information,
# including a list of lints that are intentionally _not_ enforced.
include: package:fd_lints/dart.yaml

linter:
rules:
- always_declare_return_types
- always_require_non_null_named_parameters
- annotate_overrides
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
- avoid_relative_lib_imports
- avoid_return_types_on_setters
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_types_as_parameter_names
- await_only_futures
- camel_case_extensions
- curly_braces_in_flow_control_structures
- empty_catches
- empty_constructor_bodies
- library_names
- library_prefixes
- no_duplicate_case_values
- null_closures
- omit_local_variable_types
- prefer_adjacent_string_concatenation
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_for_elements_to_map_fromIterable
- prefer_generic_function_type_aliases
- prefer_if_null_operators
- prefer_inlined_adds
- prefer_is_empty
- prefer_is_not_empty
- prefer_iterable_whereType
- prefer_single_quotes
- prefer_spread_collections
- recursive_getters
- slash_for_doc_comments
- sort_child_properties_last
- type_init_formals
- unawaited_futures
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
- unnecessary_new
- unnecessary_null_in_if_null_operators
- unnecessary_this
- unrelated_type_equality_checks
- unsafe_html
- use_full_hex_values_for_flutter_colors
- use_function_type_syntax_for_parameters
- use_rethrow_when_possible
- valid_regexps
analyzer:
plugins:
- custom_lint
2 changes: 1 addition & 1 deletion example/lib/big_video_upload/big_video_upload_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class _BigVideoUploadViewState extends State<BigVideoUploadView> {
Future<void> _createVideo(Uint8List bytes) async {
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
_controller = VideoPlayerController.network(url);
_controller = VideoPlayerController.networkUrl(Uri.parse(url));
await _controller?.initialize();
setState(() {});
}
Expand Down
2 changes: 1 addition & 1 deletion example/lib/multi_video_upload/multi_video_upload.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class _MultiVideoUploadViewState extends State<MultiVideoUploadView> {
for (final bytes in bytesList) {
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final controller = VideoPlayerController.network(url);
final controller = VideoPlayerController.networkUrl(Uri.parse(url));
await controller.initialize();
_controllers.add(controller);
}
Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ description: Demonstrates how to use the image_picker_web plugin.
publish_to: "none"

environment:
sdk: ">=2.18.0 <3.0.0"
sdk: ">=3.0.0 <4.0.0"

dependencies:
flutter:
sdk: flutter
video_player: ^2.4.7
video_player: ^2.7.0

dev_dependencies:
flutter_test:
Expand Down
67 changes: 34 additions & 33 deletions lib/image_picker_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import 'dart:html' as html;
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:image_picker_web/src/extensions/file_extensions.dart'
show FileModifier;
import 'package:image_picker_web/src/models/media_info.dart';
import 'package:image_picker_web/src/web_image_picker.dart';

import 'src/Models/Types.dart';
import 'src/extensions/file_extensions.dart' show FileModifier;
import 'src/web_image_picker.dart';

export 'src/Models/Types.dart';
export 'src/models/media_info.dart';

class ImagePickerWeb {
static void registerWith(Registrar registrar) {
final channel = MethodChannel(
'image_picker_web', const StandardMethodCodec(), registrar);
'image_picker_web',
const StandardMethodCodec(),
registrar,
);
final instance = WebImagePicker();
channel.setMethodCallHandler((call) async {
switch (call.method) {
Expand All @@ -35,22 +38,21 @@ class ImagePickerWeb {

static Future<html.File?> _pickFile(String type) async {
final completer = Completer<List<html.File>?>();
final input = html.FileUploadInputElement() as html.InputElement;
input.accept = '$type/*';
final input = html.FileUploadInputElement()..accept = '$type/*';

var changeEventTriggered = false;
bool changeEventTriggered = false;
void changeEventListener(html.Event e) {
if (changeEventTriggered) return;
changeEventTriggered = true;

final files = input.files!;
final files = input.files ?? [];
final resultFuture = files.map<Future<html.File>>((file) async {
final reader = html.FileReader();
reader.readAsDataUrl(file);
final reader = html.FileReader()..readAsDataUrl(file);
reader.onError.listen(completer.completeError);
return file;
});
Future.wait(resultFuture).then((results) => completer.complete(results));

Future.wait(resultFuture).then(completer.complete);
}

// Cancel event management inspired by:
Expand All @@ -61,7 +63,7 @@ class ImagePickerWeb {
// This listener is called before the input changed event,
// and the `uploadInput.files` value is still null
// Wait for results from js to dart
Future.delayed(Duration(milliseconds: 500)).then((value) {
Future<void>.delayed(const Duration(milliseconds: 500)).whenComplete(() {
if (!changeEventTriggered) {
changeEventTriggered = true;
completer.complete(null);
Expand All @@ -78,7 +80,7 @@ class ImagePickerWeb {
input.click();

// Need to append on mobile Safari.
html.document.body!.append(input);
html.document.body?.append(input);

final results = await completer.future;
if (results == null || results.isEmpty) return null;
Expand All @@ -88,24 +90,22 @@ class ImagePickerWeb {
/// source: https://stackoverflow.com/a/59420655/9942346
Future<List<html.File>?> _pickMultiFiles(String type) async {
final completer = Completer<List<html.File>?>();
final input = html.FileUploadInputElement();
input.multiple = true;
input.accept = '$type/*';
final input = html.FileUploadInputElement()
..multiple = true
..accept = '$type/*';

var changeEventTriggered = false;
void changeEventListener(html.Event e) {
if (changeEventTriggered) return;
changeEventTriggered = true;

final files = input.files!;
final files = input.files ?? [];
final resultsFutures = files.map<Future<html.File>>((file) async {
final reader = html.FileReader();
reader.readAsDataUrl(file);
final reader = html.FileReader()..readAsDataUrl(file);
reader.onError.listen(completer.completeError);
return file;
});
Future.wait(resultsFutures)
.then((results) => completer.complete(results));
Future.wait(resultsFutures).then(completer.complete);
}

// Cancel event management inspired by:
Expand All @@ -116,7 +116,7 @@ class ImagePickerWeb {
// This listener is called before the input changed event,
// and the `uploadInput.files` value is still null
// Wait for results from js to dart
Future.delayed(Duration(milliseconds: 500)).then((value) {
Future<void>.delayed(const Duration(milliseconds: 500)).whenComplete(() {
if (!changeEventTriggered) {
changeEventTriggered = true;
completer.complete(null);
Expand All @@ -133,7 +133,7 @@ class ImagePickerWeb {
input.click();

// Need to append on mobile Safari.
html.document.body!.append(input);
html.document.body?.append(input);
final results = await completer.future;
if (results == null || results.isEmpty) return null;
return results;
Expand Down Expand Up @@ -166,7 +166,7 @@ class ImagePickerWeb {
/// Return an object [MediaInfo] containing image's informations.
static Future<MediaInfo?> get getImageInfo async {
final data =
await (_methodChannel.invokeMapMethod<String, dynamic>('pickImage'));
await _methodChannel.invokeMapMethod<String, dynamic>('pickImage');
if (data == null) return null;
return MediaInfo.fromJson(data);
}
Expand All @@ -176,7 +176,7 @@ class ImagePickerWeb {
static Future<List<Uint8List>?> getMultiImagesAsBytes() async {
final images = await ImagePickerWeb()._pickMultiFiles('image');
if (images == null) return null;
var files = <Uint8List>[];
final files = <Uint8List>[];
for (final img in images) {
files.add(await img.asBytes());
}
Expand All @@ -188,12 +188,12 @@ class ImagePickerWeb {
static Future<List<Image>?> getMultiImagesAsWidget() async {
final images = await ImagePickerWeb()._pickMultiFiles('image');
if (images == null) return null;
var files = <Uint8List>[];
final files = <Uint8List>[];
for (final img in images) {
files.add(await img.asBytes());
}
if (files.isEmpty) return null;
return files.map<Image>((e) => Image.memory(e)).toList();
return files.map<Image>(Image.memory).toList();
}

/// Picker that allows multi-image selection and return a [html.File] list of
Expand All @@ -205,10 +205,11 @@ class ImagePickerWeb {
/// Picker that close after selecting 1 video and return a [Uint8List] of the
/// selected video.
static Future<Uint8List?> getVideoAsBytes() async {
final data =
final dataMap =
await _methodChannel.invokeMapMethod<String, dynamic>('pickVideo');
if (data == null) return null;
final imageData = base64.decode(data['data']);
final data = dataMap?['data'];
if (data == null || data is! String) return null;
final imageData = base64.decode(data);
return imageData;
}

Expand All @@ -233,7 +234,7 @@ class ImagePickerWeb {
static Future<List<Uint8List>?> getMultiVideosAsBytes() async {
final videos = await ImagePickerWeb()._pickMultiFiles('video');
if (videos == null) return null;
var files = <Uint8List>[];
final files = <Uint8List>[];
for (final video in videos) {
files.add(await video.asBytes());
}
Expand Down
13 changes: 12 additions & 1 deletion lib/src/extensions/file_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ import 'dart:html' as html;

import 'dart:typed_data';

typedef _ByteResult = FutureOr<List<int>>;

extension FileModifier on html.File {
Future<Uint8List> asBytes() async {
final bytesFile = Completer<List<int>>();
final reader = html.FileReader();
reader.onLoad.listen(
(event) => bytesFile.complete(reader.result as FutureOr<List<int>>?));
(_) {
final result = reader.result;
if (result is! _ByteResult?) {
bytesFile.completeError('Result is not a byte result');
return;
}

bytesFile.complete(result);
},
);
reader.readAsArrayBuffer(this);
return Uint8List.fromList(await bytesFile.future);
}
Expand Down
37 changes: 27 additions & 10 deletions lib/src/Models/Types.dart → lib/src/models/media_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,33 @@ import 'dart:typed_data';

/// Class used to return informations retrieved from an image or video.
class MediaInfo {
MediaInfo({
this.fileName,
this.base64,
this.base64WithScheme,
this.data,
});

/// Factory constructor to generate [MediaInfo] from [Map<String, dynamic>].
factory MediaInfo.fromJson(Map<String, dynamic> json) {
switch (json) {
case {
'name': final String? name,
'base64': final String? base64,
'data_scheme': final String? dataScheme,
'data': final String data,
}:
return MediaInfo(
fileName: name,
base64: base64,
base64WithScheme: dataScheme,
data: base64Decode(data),
);
default:
throw const FormatException('Invalid media info format');
}
}

/// Name of the file.
final String? fileName;

Expand All @@ -16,16 +43,6 @@ class MediaInfo {
/// File's bytes data.
final Uint8List? data;

MediaInfo({this.fileName, this.base64, this.base64WithScheme, this.data});

/// Factory constructor to generate [MediaInfo] from [Map<String, dynamic>].
factory MediaInfo.fromJson(Map<String, dynamic> json) => MediaInfo(
fileName: json['name'],
base64: json['data'],
base64WithScheme: json['data_scheme'],
data: base64Decode(json['data']),
);

/// Convert [MediaInfo] to [Map<String, dynamic>] format
Map<String, dynamic> toJson() => {
'name': fileName,
Expand Down
Loading

0 comments on commit 435cd33

Please sign in to comment.