Merge branch 'develop'
This commit is contained in:
commit
9d689b74d1
16 changed files with 226 additions and 75 deletions
62
.github/workflows/main.yml
vendored
Normal file
62
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
name: Release an APK and an App Bundle on tagging
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build and release artifacts.
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: '11.x'
|
||||||
|
|
||||||
|
- uses: subosito/flutter-action@v1
|
||||||
|
with:
|
||||||
|
channel: 'stable'
|
||||||
|
|
||||||
|
# Workaround for this Android Gradle Plugin issue (supposedly fixed in AGP 4.1):
|
||||||
|
# https://issuetracker.google.com/issues/144111441
|
||||||
|
- name: Install NDK
|
||||||
|
run: echo "y" | sudo /usr/local/lib/android/sdk/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT}
|
||||||
|
|
||||||
|
- name: Clone the repository.
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Get packages for the Flutter project.
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
- name: Update the flutter version file.
|
||||||
|
working-directory: ${{ github.workspace }}/scripts
|
||||||
|
run: ./update_flutter_version.sh
|
||||||
|
|
||||||
|
# `flutter test` fails if test directory is missing
|
||||||
|
#- name: Run the unit tests.
|
||||||
|
# run: flutter test
|
||||||
|
|
||||||
|
- name: Build signed artifacts.
|
||||||
|
# `KEY_JKS` should contain the result of:
|
||||||
|
# gpg -c --armor keystore.jks
|
||||||
|
# `KEY_JKS_PASSPHRASE` should contain the passphrase used for the command above
|
||||||
|
run: |
|
||||||
|
echo "${{ secrets.KEY_JKS }}" > release.keystore.asc
|
||||||
|
gpg -d --passphrase "${{ secrets.KEY_JKS_PASSPHRASE }}" --batch release.keystore.asc > $AVES_STORE_FILE
|
||||||
|
rm release.keystore.asc
|
||||||
|
flutter build apk
|
||||||
|
flutter build appbundle
|
||||||
|
rm $AVES_STORE_FILE
|
||||||
|
env:
|
||||||
|
AVES_STORE_FILE: ${{ github.workspace }}/key.jks
|
||||||
|
AVES_STORE_PASSWORD: ${{ secrets.AVES_STORE_PASSWORD }}
|
||||||
|
AVES_KEY_ALIAS: ${{ secrets.AVES_KEY_ALIAS }}
|
||||||
|
AVES_KEY_PASSWORD: ${{ secrets.AVES_KEY_PASSWORD }}
|
||||||
|
AVES_GOOGLE_API_KEY: ${{ secrets.AVES_GOOGLE_API_KEY }}
|
||||||
|
|
||||||
|
- name: Create a release with the APK and App Bundle.
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
artifacts: "build/app/outputs/apk/release/*.apk,build/app/outputs/bundle/release/*.aab"
|
||||||
|
token: ${{ secrets.RELEASE_WORKFLOW_TOKEN }}
|
|
@ -27,7 +27,17 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
// for release using credentials stored in a local file
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
|
} else {
|
||||||
|
// for release using credentials in environment variables set up by Github Actions
|
||||||
|
// warning: in property file, single quotes should be escaped with a backslash
|
||||||
|
// but they should not be escaped when stored in env variables
|
||||||
|
keystoreProperties['storeFile'] = System.getenv('AVES_STORE_FILE')
|
||||||
|
keystoreProperties['storePassword'] = System.getenv('AVES_STORE_PASSWORD')
|
||||||
|
keystoreProperties['keyAlias'] = System.getenv('AVES_KEY_ALIAS')
|
||||||
|
keystoreProperties['keyPassword'] = System.getenv('AVES_KEY_PASSWORD')
|
||||||
|
keystoreProperties['googleApiKey'] = System.getenv('AVES_GOOGLE_API_KEY')
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package deckers.thibault.aves.model.provider;
|
package deckers.thibault.aves.model.provider;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -11,7 +9,6 @@ import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.media.MediaScannerConnection;
|
import android.media.MediaScannerConnection;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package deckers.thibault.aves.utils;
|
package deckers.thibault.aves.utils;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.UriPermission;
|
import android.content.UriPermission;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -20,7 +19,6 @@ import androidx.core.app.ActivityCompat;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class PermissionManager {
|
public class PermissionManager {
|
||||||
private static final String LOG_TAG = Utils.createLogTag(PermissionManager.class);
|
private static final String LOG_TAG = Utils.createLogTag(PermissionManager.class);
|
||||||
|
|
|
@ -45,7 +45,10 @@ public class StorageUtils {
|
||||||
* Volume paths
|
* Volume paths
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// volume paths, with trailing "/"
|
||||||
private static String[] mStorageVolumePaths;
|
private static String[] mStorageVolumePaths;
|
||||||
|
|
||||||
|
// primary volume path, with trailing "/"
|
||||||
private static String mPrimaryVolumePath;
|
private static String mPrimaryVolumePath;
|
||||||
|
|
||||||
private static String getPrimaryVolumePath() {
|
private static String getPrimaryVolumePath() {
|
||||||
|
@ -90,8 +93,8 @@ public class StorageUtils {
|
||||||
|
|
||||||
private static String findPrimaryVolumePath() {
|
private static String findPrimaryVolumePath() {
|
||||||
String primaryVolumePath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
String primaryVolumePath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||||
if (!primaryVolumePath.endsWith("/")) {
|
if (!primaryVolumePath.endsWith(File.separator)) {
|
||||||
primaryVolumePath += "/";
|
primaryVolumePath += File.separator;
|
||||||
}
|
}
|
||||||
return primaryVolumePath;
|
return primaryVolumePath;
|
||||||
}
|
}
|
||||||
|
@ -167,8 +170,8 @@ public class StorageUtils {
|
||||||
String[] paths = rv.toArray(new String[0]);
|
String[] paths = rv.toArray(new String[0]);
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
String path = paths[i];
|
String path = paths[i];
|
||||||
if (path.endsWith(File.separator)) {
|
if (!path.endsWith(File.separator)) {
|
||||||
paths[i] = path.substring(0, path.length() - 1);
|
paths[i] = path + File.separator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return paths;
|
return paths;
|
||||||
|
@ -361,8 +364,11 @@ public class StorageUtils {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static boolean requireAccessPermission(@NonNull String anyPath) {
|
public static boolean requireAccessPermission(@NonNull String anyPath) {
|
||||||
|
// on Android R, we should always require access permission, even on primary volume
|
||||||
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
boolean onPrimaryVolume = anyPath.startsWith(getPrimaryVolumePath());
|
boolean onPrimaryVolume = anyPath.startsWith(getPrimaryVolumePath());
|
||||||
// TODO TLAD on Android R, we should require access permission even on primary
|
|
||||||
return !onPrimaryVolume;
|
return !onPrimaryVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
lib/flutter_version.dart
Normal file
10
lib/flutter_version.dart
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// run `scripts/update_flutter_version.sh` to update with the content of `flutter --version --machine`
|
||||||
|
const Map<String, String> version = {
|
||||||
|
'channel': 'unknown',
|
||||||
|
'dartSdkVersion': 'unknown',
|
||||||
|
'engineRevision': 'unknown',
|
||||||
|
'frameworkCommitDate': 'unknown',
|
||||||
|
'frameworkRevision': 'unknown',
|
||||||
|
'frameworkVersion': 'unknown',
|
||||||
|
'repositoryUrl': 'unknown',
|
||||||
|
};
|
|
@ -62,7 +62,7 @@ class _AvesAppState extends State<AvesApp> {
|
||||||
future: _appSetup,
|
future: _appSetup,
|
||||||
builder: (context, AsyncSnapshot<void> snapshot) {
|
builder: (context, AsyncSnapshot<void> snapshot) {
|
||||||
if (snapshot.hasError) return const Icon(AIcons.error);
|
if (snapshot.hasError) return const Icon(AIcons.error);
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return const Scaffold();
|
||||||
return settings.hasAcceptedTerms ? const HomePage() : const WelcomePage();
|
return settings.hasAcceptedTerms ? const HomePage() : const WelcomePage();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
@ -86,7 +88,10 @@ class AndroidAppService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> share(Map<String, List<String>> urisByMimeType) async {
|
static Future<void> share(Set<ImageEntry> entries) async {
|
||||||
|
// loosen mime type to a generic one, so we can share with badly defined apps
|
||||||
|
// e.g. Google Lens declares receiving "image/jpeg" only, but it can actually handle more formats
|
||||||
|
final urisByMimeType = groupBy<ImageEntry, String>(entries, (e) => e.mimeTypeAnySubtype).map((k, v) => MapEntry(k, v.map((e) => e.uri).toList()));
|
||||||
try {
|
try {
|
||||||
await platform.invokeMethod('share', <String, dynamic>{
|
await platform.invokeMethod('share', <String, dynamic>{
|
||||||
'title': 'Share via:',
|
'title': 'Share via:',
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
import 'package:aves/flutter_version.dart';
|
||||||
import 'package:aves/widgets/about/licenses.dart';
|
import 'package:aves/widgets/about/licenses.dart';
|
||||||
|
import 'package:aves/widgets/common/aves_logo.dart';
|
||||||
import 'package:aves/widgets/common/link_chip.dart';
|
import 'package:aves/widgets/common/link_chip.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||||
|
import 'package:package_info/package_info.dart';
|
||||||
|
|
||||||
class AboutPage extends StatelessWidget {
|
class AboutPage extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
|
@ -19,31 +22,8 @@ class AboutPage extends StatelessWidget {
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate(
|
||||||
[
|
[
|
||||||
Center(
|
AppReference(),
|
||||||
child: Column(
|
const SizedBox(height: 16),
|
||||||
children: [
|
|
||||||
Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
const TextSpan(text: 'Made with ❤️ and '),
|
|
||||||
WidgetSpan(
|
|
||||||
child: FlutterLogo(
|
|
||||||
size: Theme.of(context).textTheme.bodyText2.fontSize * 1.25,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
const LinkChip(
|
|
||||||
text: 'Sources',
|
|
||||||
url: 'https://github.com/deckerst/aves',
|
|
||||||
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
const Divider(),
|
const Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -57,3 +37,71 @@ class AboutPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AppReference extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_AppReferenceState createState() => _AppReferenceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppReferenceState extends State<AppReference> {
|
||||||
|
Future<PackageInfo> packageInfoLoader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
packageInfoLoader = PackageInfo.fromPlatform();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildAvesLine(),
|
||||||
|
_buildFlutterLine(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAvesLine() {
|
||||||
|
final textTheme = Theme.of(context).textTheme;
|
||||||
|
final style = textTheme.headline6.copyWith(fontWeight: FontWeight.bold);
|
||||||
|
|
||||||
|
return FutureBuilder<PackageInfo>(
|
||||||
|
future: packageInfoLoader,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return LinkChip(
|
||||||
|
leading: AvesLogo(
|
||||||
|
size: style.fontSize * 1.25,
|
||||||
|
),
|
||||||
|
text: 'Aves ${snapshot.data?.version}',
|
||||||
|
url: 'https://github.com/deckerst/aves',
|
||||||
|
textStyle: style,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFlutterLine() {
|
||||||
|
final style = DefaultTextStyle.of(context).style;
|
||||||
|
final subColor = style.color.withOpacity(.6);
|
||||||
|
|
||||||
|
return Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 4),
|
||||||
|
child: FlutterLogo(
|
||||||
|
size: style.fontSize * 1.25,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(text: 'Flutter ${version['frameworkVersion']}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: TextStyle(color: subColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -64,9 +64,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
AndroidAppService.setAs(entry.uri, entry.mimeType);
|
AndroidAppService.setAs(entry.uri, entry.mimeType);
|
||||||
break;
|
break;
|
||||||
case EntryAction.share:
|
case EntryAction.share:
|
||||||
AndroidAppService.share({
|
AndroidAppService.share({entry});
|
||||||
entry.mimeType: [entry.uri]
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case EntryAction.debug:
|
case EntryAction.debug:
|
||||||
_goToDebug(context, entry);
|
_goToDebug(context, entry);
|
||||||
|
|
|
@ -17,7 +17,6 @@ import 'package:aves/widgets/common/action_delegates/permission_aware.dart';
|
||||||
import 'package:aves/widgets/common/entry_actions.dart';
|
import 'package:aves/widgets/common/entry_actions.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/filter_grid_page.dart';
|
import 'package:aves/widgets/filter_grid_page.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
@ -38,7 +37,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
_showDeleteDialog(context);
|
_showDeleteDialog(context);
|
||||||
break;
|
break;
|
||||||
case EntryAction.share:
|
case EntryAction.share:
|
||||||
_share();
|
AndroidAppService.share(collection.selection);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -229,11 +228,6 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _share() {
|
|
||||||
final urisByMimeType = groupBy<ImageEntry, String>(collection.selection, (e) => e.mimeType).map((k, v) => MapEntry(k, v.map((e) => e.uri).toList()));
|
|
||||||
AndroidAppService.share(urisByMimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// selection action report overlay
|
// selection action report overlay
|
||||||
|
|
||||||
OverlayEntry _opReportOverlayEntry;
|
OverlayEntry _opReportOverlayEntry;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class LinkChip extends StatelessWidget {
|
class LinkChip extends StatelessWidget {
|
||||||
|
final Widget leading;
|
||||||
final String text;
|
final String text;
|
||||||
final String url;
|
final String url;
|
||||||
final Color color;
|
final Color color;
|
||||||
|
@ -12,6 +13,7 @@ class LinkChip extends StatelessWidget {
|
||||||
|
|
||||||
const LinkChip({
|
const LinkChip({
|
||||||
Key key,
|
Key key,
|
||||||
|
this.leading,
|
||||||
@required this.text,
|
@required this.text,
|
||||||
@required this.url,
|
@required this.url,
|
||||||
this.color,
|
this.color,
|
||||||
|
@ -20,10 +22,9 @@ class LinkChip extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final effectiveTextStyle = (textStyle ?? DefaultTextStyle.of(context).style).copyWith(
|
return DefaultTextStyle.merge(
|
||||||
color: color,
|
style: (textStyle ?? const TextStyle()).copyWith(color: color),
|
||||||
);
|
child: InkWell(
|
||||||
return InkWell(
|
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (await canLaunch(url)) {
|
if (await canLaunch(url)) {
|
||||||
|
@ -35,17 +36,21 @@ class LinkChip extends StatelessWidget {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
if (leading != null) ...[
|
||||||
text,
|
leading,
|
||||||
style: effectiveTextStyle,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Icon(
|
|
||||||
AIcons.openInNew,
|
|
||||||
size: Theme.of(context).textTheme.bodyText2.fontSize,
|
|
||||||
color: color,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
|
Text(text),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Builder(
|
||||||
|
builder: (context) => Icon(
|
||||||
|
AIcons.openInNew,
|
||||||
|
size: DefaultTextStyle.of(context).style.fontSize,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -96,7 +96,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
future: _appSetup,
|
future: _appSetup,
|
||||||
builder: (context, AsyncSnapshot<void> snapshot) {
|
builder: (context, AsyncSnapshot<void> snapshot) {
|
||||||
if (snapshot.hasError) return const Icon(AIcons.error);
|
if (snapshot.hasError) return const Icon(AIcons.error);
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return const Scaffold();
|
||||||
if (AvesApp.mode == AppMode.view) {
|
if (AvesApp.mode == AppMode.view) {
|
||||||
return SingleFullscreenPage(entry: _viewerEntry);
|
return SingleFullscreenPage(entry: _viewerEntry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,6 +260,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.1"
|
version: "0.1.1"
|
||||||
|
package_info:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: package_info
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.1"
|
||||||
palette_generator:
|
palette_generator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -11,7 +11,7 @@ description: A new Flutter application.
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.0.8+9
|
version: 1.0.9+10
|
||||||
|
|
||||||
# video_player (as of v0.10.8+2, backed by ExoPlayer):
|
# video_player (as of v0.10.8+2, backed by ExoPlayer):
|
||||||
# - does not support content URIs (by default, but trivial by fork)
|
# - does not support content URIs (by default, but trivial by fork)
|
||||||
|
@ -57,6 +57,7 @@ dependencies:
|
||||||
google_maps_flutter:
|
google_maps_flutter:
|
||||||
intl:
|
intl:
|
||||||
outline_material_icons:
|
outline_material_icons:
|
||||||
|
package_info:
|
||||||
palette_generator:
|
palette_generator:
|
||||||
pdf:
|
pdf:
|
||||||
pedantic:
|
pedantic:
|
||||||
|
|
10
scripts/update_flutter_version.sh
Executable file
10
scripts/update_flutter_version.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
FILE_PATH="../lib/flutter_version.dart"
|
||||||
|
rm "$FILE_PATH"
|
||||||
|
echo "Updating flutter_version.dart:"
|
||||||
|
{
|
||||||
|
echo "const Map<String, String> version = "
|
||||||
|
flutter --version --machine
|
||||||
|
echo ";"
|
||||||
|
} >> "$FILE_PATH"
|
||||||
|
cat "$FILE_PATH"
|
Loading…
Reference in a new issue