diff --git a/README.md b/README.md index e8316e1fa..eb56922e6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Aves logo][] +![Aves logo][] [Get it on Google Play](https://play.google.com/store/apps/details?id=deckers.thibault.aves&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1) Aves is a gallery and metadata explorer app. It is built for Android, with Flutter. @@ -13,6 +13,7 @@ Aves is a gallery and metadata explorer app. It is built for Android, with Flutt - favorites - statistics - handle intents to view or pick images +- support Android API 24 ~ 29 (Nougat ~ Android 10) ## Roadmap @@ -28,12 +29,23 @@ If time permits, I intend to eventually add these: - subsampling/tiling ## Known Issues + - privacy: cannot opt out of Crashlytics reporting (cf [flutterfire issue #1143](https://github.com/FirebaseExtended/flutterfire/issues/1143)) - gesture: double tap on image does not zoom on tapped area (cf [photo_view issue #82](https://github.com/renancaraujo/photo_view/issues/82)) - performance: image info page stutters the first time it loads a Google Maps view (cf [flutter issue #28493](https://github.com/flutter/flutter/issues/28493)) - performance: image decoding is slow +## Test Devices + +| Model | Name | Android Version | API | +| ----------- | -------------------------- | --------------- | ---:| +| SM-G970N | Samsung Galaxy S10e | 10 (Android10) | 29 | +| SM-P580 | Samsung Galaxy Tab A 10.1 | 8.1.0 (Oreo) | 27 | +| SM-G930S | Samsung Galaxy S7 | 8.0.0 (Oreo) | 26 | +| E5823 | Sony Xperia Z5 Compact | 7.1.1 (Nougat) | 25 | + ## Project Setup + Create a file named `/android/key.properties`. It should contain a reference to a keystore for app signing, and other necessary credentials. See `/android/key_template.properties` for the expected keys. [Aves logo]: https://github.com/deckerst/aves/blob/master/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/android/app/build.gradle b/android/app/build.gradle index 9947a77a4..3e314b977 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -43,6 +43,7 @@ android { // Gradle plugin 4.0 desugaring features allow targeting older SDKs // but Flutter (as of v1.17.3) fails to run in release mode when using Gradle plugin 4.0: // https://github.com/flutter/flutter/issues/58247 + // but there is a workaround (cf `afterEvaluate` section below) minSdkVersion 24 targetSdkVersion 29 // same as compileSdkVersion versionCode flutterVersionCode.toInteger() @@ -80,6 +81,22 @@ flutter { source '../..' } +// workaround to https://github.com/flutter/flutter/issues/58247 +afterEvaluate { + android.productFlavors.all { flavor -> + def debugLintTask = tasks.findByName("lint${flavor.name.capitalize()}Debug") + def releaseLintTask = tasks.findByName("lint${flavor.name.capitalize()}Release") + + if (debugLintTask != null) { + debugLintTask.dependsOn ':flutter:assemble' + } + + if (releaseLintTask != null) { + releaseLintTask.dependsOn ':flutter:assemble' + } + } +} + repositories { maven { url "https://s3.amazonaws.com/repo.commonsware.com" diff --git a/android/build.gradle b/android/build.gradle index cb1faadbe..687287c52 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:4.0.0' classpath 'com.google.gms:google-services:4.3.3' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1' } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 33268b8ca..0285b73ef 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Apr 21 13:20:37 KST 2020 +#Fri Jul 03 23:16:00 KST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip \ No newline at end of file +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee85..e8efba114 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee85..399e9340e 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 000000000..6697f0a53 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,87 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + 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 + end + generated_key_values +end + +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 +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 + end +end diff --git a/lib/widgets/fullscreen/fullscreen_body.dart b/lib/widgets/fullscreen/fullscreen_body.dart index 74ce87dd3..8f8dfc7e4 100644 --- a/lib/widgets/fullscreen/fullscreen_body.dart +++ b/lib/widgets/fullscreen/fullscreen_body.dart @@ -514,6 +514,10 @@ class _FullscreenVerticalPageViewState extends State _oldEntry?.imageChangeNotifier?.removeListener(_onImageChanged); entry?.imageChangeNotifier?.addListener(_onImageChanged); _oldEntry = entry; + // make sure to locate the entry, + // so that we can display the address instead of coordinates + // even when background locating has not reached this entry yet + entry?.locate(); } // when the entry image itself changed (e.g. after rotation) diff --git a/lib/widgets/fullscreen/info/info_page.dart b/lib/widgets/fullscreen/info/info_page.dart index 1b10df6bd..478c0703f 100644 --- a/lib/widgets/fullscreen/info/info_page.dart +++ b/lib/widgets/fullscreen/info/info_page.dart @@ -34,33 +34,6 @@ class InfoPageState extends State { CollectionLens get collection => widget.collection; - @override - void initState() { - super.initState(); - _registerWidget(widget); - } - - @override - void didUpdateWidget(InfoPage oldWidget) { - super.didUpdateWidget(oldWidget); - _unregisterWidget(oldWidget); - _registerWidget(widget); - } - - @override - void dispose() { - _unregisterWidget(widget); - super.dispose(); - } - - void _registerWidget(InfoPage widget) { - widget.entryNotifier.addListener(_onEntryChanged); - } - - void _unregisterWidget(InfoPage widget) { - widget.entryNotifier.removeListener(_onEntryChanged); - } - @override Widget build(BuildContext context) { const horizontalPadding = EdgeInsets.symmetric(horizontal: 8); @@ -147,10 +120,6 @@ class InfoPageState extends State { ); } - void _onEntryChanged() { - widget.entryNotifier.value?.locate(); - } - bool _handleTopScroll(Notification notification) { if (notification is ScrollNotification) { if (notification is ScrollStartNotification) { diff --git a/pubspec.lock b/pubspec.lock index 7ad5f2be1..813cb8ea0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -127,7 +127,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: "2dfc79b79b9544ecbc205c158c6246293fb2be8f" + resolved-ref: e32cd834e1c76fa172efbd6600a3b1464416100c url: "git://github.com/deckerst/flutter_ijkplayer.git" source: git version: "0.3.6" @@ -315,7 +315,7 @@ packages: name: permission_handler url: "https://pub.dartlang.org" source: hosted - version: "5.0.1" + version: "5.0.1+1" permission_handler_platform_interface: dependency: transitive description: @@ -546,7 +546,7 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.1+6" + version: "0.1.2" utf: dependency: transitive description: @@ -560,7 +560,7 @@ packages: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index acaf7e1c3..42fac79a4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: A new Flutter application. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.5+6 +version: 1.0.6+7 # video_player (as of v0.10.8+2, backed by ExoPlayer): # - does not support content URIs (by default, but trivial by fork) @@ -29,10 +29,6 @@ version: 1.0.5+6 # - does not support AC3 (by default, but possible by custom build) # - can play if only the video or audio stream is supported -# TODO TLAD flutter_ijkplayer: custom ijkplayer build to add AC3 support (only buildable on linux/mac) -# cf https://github.com/CaiJingLong/flutter_ijkplayer/blob/master/compile.md -# flags for AC3? --enable-decoder=ac3 --enable-decoder=ac3_fixed --enable-demuxer=ac3 - dependencies: flutter: sdk: flutter