update to satisfy null safety

This commit is contained in:
Wenqi Li 2021-03-30 22:30:21 +08:00
parent 7f3911d89b
commit 184b728f12
11 changed files with 74 additions and 131 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
location = "self:">
</FileRef>
</Workspace>

View File

@ -18,7 +18,7 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
List<Album> _albums;
List<Album>? _albums;
bool _loading = false;
@override
@ -150,7 +150,7 @@ class AlbumPage extends StatefulWidget {
}
class AlbumPageState extends State<AlbumPage> {
List<Medium> _media;
List<Medium>? _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<VideoProvider> {
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<VideoProvider> {
Future<void> 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<VideoProvider> {
@override
Widget build(BuildContext context) {
return _controller == null || !_controller.value.initialized
return _controller == null || !_controller!.value.isInitialized
? Container()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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,
),
),
],

View File

@ -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:

View File

@ -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<int>.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<int>.from(bytes);
}
/// get medium file by medium id

View File

@ -7,7 +7,7 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProvider> {
this.mediumType,
this.height,
this.width,
this.highQuality,
this.highQuality = false,
});
final String mediumId;

View File

@ -37,6 +37,7 @@ void main() {
MediaPage expected = Generator.generateMediaPage(
album: allAlbum,
mediumType: mediumType,
total: allAlbum.count,
skip: skip,
take: take,
);

View File

@ -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<Album> generateAlbums({required MediumType mediumType}) {
static List<Album> generateAlbums({MediumType? mediumType}) {
return Generator.generateAlbumsJson(mediumType: mediumType)
.map<Album>((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<int> 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));
}

View File

@ -6,32 +6,32 @@ import 'generator.dart';
Future<dynamic> 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<dynamic> 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;