diff --git a/example/ios/Podfile b/example/ios/Podfile
index 6697f0a..1e8c3c9 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -10,78 +10,32 @@ project 'Runner', {
'Release' => :release,
}
-def parse_KV_file(file, separator='=')
- file_abs_path = File.expand_path(file)
- if !File.exists? file_abs_path
- return [];
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
- generated_key_values = {}
- skip_line_start_symbols = ["#", "/"]
- File.foreach(file_abs_path) do |line|
- next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
- plugin = line.split(pattern=separator)
- if plugin.length == 2
- podname = plugin[0].strip()
- path = plugin[1].strip()
- podpath = File.expand_path("#{path}", file_abs_path)
- generated_key_values[podname] = podpath
- else
- puts "Invalid plugin specification: #{line}"
- end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
end
- generated_key_values
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
target 'Runner' do
use_frameworks!
use_modular_headers!
- # Flutter Pod
-
- copied_flutter_dir = File.join(__dir__, 'Flutter')
- copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
- copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
- unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
- # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
- # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
- # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
-
- generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
- unless File.exist?(generated_xcode_build_settings_path)
- raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
- end
- generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
- cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
-
- unless File.exist?(copied_framework_path)
- FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
- end
- unless File.exist?(copied_podspec_path)
- FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
- end
- end
-
- # Keep pod path relative so it can be checked into Podfile.lock.
- pod 'Flutter', :path => 'Flutter'
-
- # Plugin Pods
-
- # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
- # referring to absolute paths on developers' machines.
- system('rm -rf .symlinks')
- system('mkdir -p .symlinks/plugins')
- plugin_pods = parse_KV_file('../.flutter-plugins')
- plugin_pods.each do |name, path|
- symlink = File.join('.symlinks', 'plugins', name)
- File.symlink(path, symlink)
- pod name, :path => File.join(symlink, 'ios')
- end
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
- target.build_configurations.each do |config|
- config.build_settings['ENABLE_BITCODE'] = 'NO'
- end
+ flutter_additional_ios_build_settings(target)
end
end
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 6e880e6..0a8204d 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1,20 +1,17 @@
PODS:
- Flutter (1.0.0)
- - "permission_handler (5.0.1+1)":
+ - "permission_handler (5.1.0+2)":
- Flutter
- photo_gallery (0.0.1):
- Flutter
- video_player (0.0.1):
- Flutter
- - video_player_web (0.0.1):
- - Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
- photo_gallery (from `.symlinks/plugins/photo_gallery/ios`)
- video_player (from `.symlinks/plugins/video_player/ios`)
- - video_player_web (from `.symlinks/plugins/video_player_web/ios`)
EXTERNAL SOURCES:
Flutter:
@@ -25,16 +22,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/photo_gallery/ios"
video_player:
:path: ".symlinks/plugins/video_player/ios"
- video_player_web:
- :path: ".symlinks/plugins/video_player_web/ios"
SPEC CHECKSUMS:
- Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
- permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6
+ Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
+ permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
photo_gallery: 9f95e57747cd22c10676ece3660d1ffe6c603ee5
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
- video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7
-PODFILE CHECKSUM: c34e2287a9ccaa606aeceab922830efb9a6ff69a
+PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
-COCOAPODS: 1.9.3
+COCOAPODS: 1.10.1
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index a69fa81..4322482 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -261,17 +261,12 @@
buildActionMask = 2147483647;
files = (
);
- inputPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
- "${PODS_ROOT}/../Flutter/Flutter.framework",
- "${BUILT_PRODUCTS_DIR}/photo_gallery/photo_gallery.framework",
- "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework",
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
- outputPaths = (
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_gallery.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework",
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -314,7 +309,6 @@
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -391,7 +385,6 @@
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -447,7 +440,6 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1d526a1..919434a 100644
--- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:">
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 3af9f6e..aef3313 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -18,7 +18,7 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State {
- List _albums;
+ List? _albums;
bool _loading = false;
@override
@@ -150,7 +150,7 @@ class AlbumPage extends StatefulWidget {
}
class AlbumPageState extends State {
- List _media;
+ List? _media;
@override
void initState() {
@@ -213,7 +213,7 @@ class ViewerPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
- DateTime date = medium.creationDate ?? medium.modifiedDate;
+ DateTime? date = medium.creationDate ?? medium.modifiedDate;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
@@ -221,7 +221,7 @@ class ViewerPage extends StatelessWidget {
onPressed: () => Navigator.of(context).pop(),
icon: Icon(Icons.arrow_back_ios),
),
- title: Text(date?.toLocal().toString()),
+ title: date != null ? Text(date.toLocal().toString()) : null,
),
body: Container(
alignment: Alignment.center,
@@ -244,7 +244,7 @@ class VideoProvider extends StatefulWidget {
final String mediumId;
const VideoProvider({
- @required this.mediumId,
+ required this.mediumId,
});
@override
@@ -252,12 +252,12 @@ class VideoProvider extends StatefulWidget {
}
class _VideoProviderState extends State {
- VideoPlayerController _controller;
- File _file;
+ VideoPlayerController? _controller;
+ File? _file;
@override
void initState() {
- WidgetsBinding.instance.addPostFrameCallback((_) {
+ WidgetsBinding.instance?.addPostFrameCallback((_) {
initAsync();
});
super.initState();
@@ -266,8 +266,8 @@ class _VideoProviderState extends State {
Future initAsync() async {
try {
_file = await PhotoGallery.getFile(mediumId: widget.mediumId);
- _controller = VideoPlayerController.file(_file);
- _controller.initialize().then((_) {
+ _controller = VideoPlayerController.file(_file!);
+ _controller?.initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
@@ -278,25 +278,25 @@ class _VideoProviderState extends State {
@override
Widget build(BuildContext context) {
- return _controller == null || !_controller.value.initialized
+ return _controller == null || !_controller!.value.isInitialized
? Container()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AspectRatio(
- aspectRatio: _controller.value.aspectRatio,
- child: VideoPlayer(_controller),
+ aspectRatio: _controller!.value.aspectRatio,
+ child: VideoPlayer(_controller!),
),
FlatButton(
onPressed: () {
setState(() {
- _controller.value.isPlaying
- ? _controller.pause()
- : _controller.play();
+ _controller!.value.isPlaying
+ ? _controller!.pause()
+ : _controller!.play();
});
},
child: Icon(
- _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
+ _controller!.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
],
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 3e161b9..8d6e7d4 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -6,7 +6,7 @@ description: Demonstrates how to use the photo_gallery plugin.
# publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment:
- sdk: ">=2.7.0 <3.0.0"
+ sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
@@ -22,10 +22,10 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^0.1.3
- transparent_image: ^1.0.0
- permission_handler: ^5.0.1+1
- video_player: ^0.10.12
+ cupertino_icons: ^1.0.2
+ transparent_image: ^2.0.0
+ permission_handler: ^6.1.1
+ video_player: ^2.1.0
dev_dependencies:
flutter_test:
diff --git a/lib/photo_gallery.dart b/lib/photo_gallery.dart
index 539c4b7..f543388 100644
--- a/lib/photo_gallery.dart
+++ b/lib/photo_gallery.dart
@@ -67,7 +67,7 @@ class PhotoGallery {
MediumType? mediumType,
int? width,
int? height,
- bool? highQuality,
+ bool? highQuality = false,
}) async {
final bytes = await _channel.invokeMethod('getThumbnail', {
'mediumId': mediumId,
@@ -76,7 +76,7 @@ class PhotoGallery {
'height': height,
'highQuality': highQuality,
});
- return bytes;
+ return new List.from(bytes);
}
/// Get album thumbnail by album id
@@ -85,7 +85,7 @@ class PhotoGallery {
MediumType? mediumType,
int? width,
int? height,
- bool? highQuality,
+ bool? highQuality = false,
}) async {
final bytes = await _channel.invokeMethod('getAlbumThumbnail', {
'albumId': albumId,
@@ -94,7 +94,7 @@ class PhotoGallery {
'height': height,
'highQuality': highQuality,
});
- return bytes;
+ return new List.from(bytes);
}
/// get medium file by medium id
diff --git a/lib/src/image_providers/thumbnail_provider.dart b/lib/src/image_providers/thumbnail_provider.dart
index d77c450..37cd53e 100644
--- a/lib/src/image_providers/thumbnail_provider.dart
+++ b/lib/src/image_providers/thumbnail_provider.dart
@@ -7,7 +7,7 @@ class ThumbnailProvider extends ImageProvider {
this.mediumType,
this.height,
this.width,
- this.highQuality,
+ this.highQuality = false,
});
final String mediumId;
diff --git a/test/photo_gallery_test.dart b/test/photo_gallery_test.dart
index ac2164a..41ba21c 100644
--- a/test/photo_gallery_test.dart
+++ b/test/photo_gallery_test.dart
@@ -37,6 +37,7 @@ void main() {
MediaPage expected = Generator.generateMediaPage(
album: allAlbum,
mediumType: mediumType,
+ total: allAlbum.count,
skip: skip,
take: take,
);
diff --git a/test/utils/generator.dart b/test/utils/generator.dart
index c96284e..b9e81e3 100644
--- a/test/utils/generator.dart
+++ b/test/utils/generator.dart
@@ -3,7 +3,8 @@ import 'dart:io';
import 'package:photo_gallery/photo_gallery.dart';
class Generator {
- static dynamic generateAlbumsJson({MediumType mediumType = MediumType.image}) {
+ static dynamic generateAlbumsJson(
+ {MediumType? mediumType = MediumType.image}) {
return [
{
"id": "__ALL__",
@@ -20,7 +21,7 @@ class Generator {
];
}
- static List generateAlbums({required MediumType mediumType}) {
+ static List generateAlbums({MediumType? mediumType}) {
return Generator.generateAlbumsJson(mediumType: mediumType)
.map((x) => Album.fromJson(x))
.toList();
@@ -28,8 +29,8 @@ class Generator {
static dynamic generateMediaPageJson({
required String albumId,
- required MediumType mediumType,
- required int total,
+ MediumType? mediumType,
+ int total = 10,
int? skip,
int? take,
}) {
@@ -53,7 +54,7 @@ class Generator {
static dynamic generateMediaJson({
required String mediumId,
- required MediumType mediumType,
+ MediumType? mediumType,
}) {
return {
"id": mediumId,
@@ -69,14 +70,15 @@ class Generator {
static MediaPage generateMediaPage({
required Album album,
- required MediumType mediumType,
+ MediumType? mediumType,
+ required int total,
int? skip,
int? take,
}) {
dynamic json = generateMediaPageJson(
albumId: album.id,
mediumType: mediumType,
- total: album.count,
+ total: total,
skip: skip,
take: take,
);
@@ -85,7 +87,7 @@ class Generator {
static Medium generateMedia({
required String mediumId,
- required MediumType mediumType,
+ MediumType? mediumType,
}) {
return Medium.fromJson(
generateMediaJson(mediumId: mediumId, mediumType: mediumType),
@@ -94,7 +96,7 @@ class Generator {
static List generateMockThumbnail({
required String mediumId,
- required MediumType mediumType,
+ MediumType? mediumType,
}) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9];
}
@@ -107,14 +109,14 @@ class Generator {
static String generateFilePath({
required String mediumId,
- required MediumType mediumType,
+ MediumType? mediumType,
}) {
return "/path/to/file";
}
static File generateFile({
required String mediumId,
- required MediumType mediumType,
+ MediumType? mediumType,
}) {
return File(generateFilePath(mediumId: mediumId, mediumType: mediumType));
}
diff --git a/test/utils/mock_handler.dart b/test/utils/mock_handler.dart
index 83ab030..f2b104d 100644
--- a/test/utils/mock_handler.dart
+++ b/test/utils/mock_handler.dart
@@ -6,32 +6,32 @@ import 'generator.dart';
Future mockMethodCallHandler(MethodCall call) async {
if (call.method == "listAlbums") {
- MediumType mediumType = jsonToMediumType(call.arguments['mediumType']);
+ MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
dynamic albums = Generator.generateAlbumsJson(mediumType: mediumType);
return albums;
} else if (call.method == "listMedia") {
String albumId = call.arguments['albumId'];
MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
- int total = call.arguments['total'];
- int skip = call.arguments['skip'];
- int take = call.arguments['take'];
+ int? total = call.arguments['total'];
+ int? skip = call.arguments['skip'];
+ int? take = call.arguments['take'];
dynamic mediaPage = Generator.generateMediaPageJson(
albumId: albumId,
mediumType: mediumType,
- total: total,
+ total: total ?? 10,
skip: skip,
take: take,
);
return mediaPage;
} else if (call.method == "getMedium") {
String mediumId = call.arguments['mediumId'];
- MediumType mediumType = jsonToMediumType(call.arguments['mediumType']);
+ MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
dynamic media =
Generator.generateMediaJson(mediumId: mediumId, mediumType: mediumType);
return media;
} else if (call.method == "getThumbnail") {
String mediumId = call.arguments['mediumId'];
- MediumType mediumType = jsonToMediumType(call.arguments['mediumType']);
+ MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
dynamic thumbnail = Generator.generateMockThumbnail(
mediumId: mediumId, mediumType: mediumType);
return thumbnail;
@@ -41,7 +41,7 @@ Future mockMethodCallHandler(MethodCall call) async {
return thumbnail;
} else if (call.method == "getFile") {
String mediumId = call.arguments['mediumId'];
- MediumType mediumType = jsonToMediumType(call.arguments['mediumType']);
+ MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
dynamic path =
Generator.generateFilePath(mediumId: mediumId, mediumType: mediumType);
return path;