Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
deckerst committed Sep 9, 2020
2 parents dc907a0 + 7fcd0da commit 60a778f
Show file tree
Hide file tree
Showing 68 changed files with 1,028 additions and 255 deletions.
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ dependencies {
// enable support for Java 8 language APIs (stream, optional, etc.)
// coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'

implementation 'androidx.core:core:1.5.0-alpha02' // v1.5.0-alpha02 for ShortcutManagerCompat.setDynamicShortcuts
implementation "androidx.exifinterface:exifinterface:1.2.0"
implementation 'com.commonsware.cwac:document:0.4.1'
implementation 'com.drewnoakes:metadata-extractor:2.14.0'
Expand Down
12 changes: 9 additions & 3 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,41 +45,47 @@

<application
android:name="io.flutter.app.FlutterApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/AppTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="false" />

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="image/*" />
<data android:mimeType="video/*" />
<data android:mimeType="vnd.android.cursor.dir/image" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />

<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="image/*" />
<data android:mimeType="video/*" />
<data android:mimeType="vnd.android.cursor.dir/image" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="image/*" />
<data android:mimeType="video/*" />
<data android:mimeType="vnd.android.cursor.dir/image" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.RequiresApi;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import app.loup.streams_channel.StreamsChannel;
import deckers.thibault.aves.channel.calls.AppAdapterHandler;
import deckers.thibault.aves.channel.calls.AppShortcutHandler;
import deckers.thibault.aves.channel.calls.ImageFileHandler;
import deckers.thibault.aves.channel.calls.MetadataHandler;
import deckers.thibault.aves.channel.calls.StorageHandler;
Expand All @@ -29,7 +38,7 @@ public class MainActivity extends FlutterActivity {

public static final String VIEWER_CHANNEL = "deckers.thibault/aves/viewer";

private Map<String, String> intentDataMap;
private Map<String, Object> intentDataMap;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -40,6 +49,7 @@ protected void onCreate(Bundle savedInstanceState) {
BinaryMessenger messenger = Objects.requireNonNull(getFlutterEngine()).getDartExecutor().getBinaryMessenger();

new MethodChannel(messenger, AppAdapterHandler.CHANNEL).setMethodCallHandler(new AppAdapterHandler(this));
new MethodChannel(messenger, AppShortcutHandler.CHANNEL).setMethodCallHandler(new AppShortcutHandler(this));
new MethodChannel(messenger, ImageFileHandler.CHANNEL).setMethodCallHandler(new ImageFileHandler(this));
new MethodChannel(messenger, MetadataHandler.CHANNEL).setMethodCallHandler(new MetadataHandler(this));
new MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(new StorageHandler(this));
Expand Down Expand Up @@ -69,6 +79,32 @@ protected void onCreate(Bundle savedInstanceState) {
finish();
}
});

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
setupShortcuts();
}
}

@RequiresApi(Build.VERSION_CODES.N_MR1)
private void setupShortcuts() {
// do not use 'route' as extra key, as the Flutter framework acts on it

ShortcutInfoCompat search = new ShortcutInfoCompat.Builder(this, "search")
.setShortLabel(getString(R.string.search_shortcut_short_label))
.setIcon(IconCompat.createWithResource(this, R.mipmap.ic_shortcut_search))
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
.putExtra("page", "/search"))
.build();

ShortcutInfoCompat videos = new ShortcutInfoCompat.Builder(this, "videos")
.setShortLabel(getString(R.string.videos_shortcut_short_label))
.setIcon(IconCompat.createWithResource(this, R.mipmap.ic_shortcut_movie))
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
.putExtra("page", "/collection")
.putExtra("filters", new String[]{"{\"type\":\"mime\",\"mime\":\"video/*\"}"}))
.build();

ShortcutManagerCompat.setDynamicShortcuts(this, Arrays.asList(videos, search));
}

private void handleIntent(Intent intent) {
Expand All @@ -77,6 +113,15 @@ private void handleIntent(Intent intent) {
String action = intent.getAction();
if (action == null) return;
switch (action) {
case Intent.ACTION_MAIN:
String page = intent.getStringExtra("page");
if (page != null) {
intentDataMap = new HashMap<>();
intentDataMap.put("page", page);
String[] filters = intent.getStringArrayExtra("filters");
intentDataMap.put("filters", filters != null ? new ArrayList<>(Arrays.asList(filters)) : null);
}
break;
case Intent.ACTION_VIEW:
Uri uri = intent.getData();
String mimeType = intent.getType();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package deckers.thibault.aves.channel.calls;

import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;

import java.util.List;

import deckers.thibault.aves.MainActivity;
import deckers.thibault.aves.R;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

public class AppShortcutHandler implements MethodChannel.MethodCallHandler {
public static final String CHANNEL = "deckers.thibault/aves/shortcut";

private Context context;

public AppShortcutHandler(Context context) {
this.context = context;
}

@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
switch (call.method) {
case "canPin": {
result.success(ShortcutManagerCompat.isRequestPinShortcutSupported(context));
break;
}
case "pin": {
String label = call.argument("label");
List<String> filters = call.argument("filters");
pin(label, filters);
result.success(null);
break;
}
default:
result.notImplemented();
break;
}
}

private void pin(String label, @Nullable List<String> filters) {
if (!ShortcutManagerCompat.isRequestPinShortcutSupported(context) || filters == null) {
return;
}

ShortcutInfoCompat shortcut = new ShortcutInfoCompat.Builder(context, "collection-" + TextUtils.join("-", filters))
.setShortLabel(label)
.setIcon(IconCompat.createWithResource(context, R.mipmap.ic_shortcut_collection))
.setIntent(new Intent(Intent.ACTION_MAIN, null, context, MainActivity.class)
.putExtra("page", "/collection")
.putExtra("filters", filters.toArray(new String[0])))
.build();

ShortcutManagerCompat.requestPinShortcut(context, shortcut, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#455A64">
<group android:scaleX="1.7226"
android:scaleY="1.7226"
android:translateX="33.3288"
android:translateY="33.3288">
<path
android:fillColor="@android:color/white"
android:pathData="M20,4v12L8,16L8,4h12m0,-2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM11.5,11.67l1.69,2.26 2.48,-3.1L19,15L9,15zM2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6L2,6z"/>
</group>
</vector>
15 changes: 15 additions & 0 deletions android/app/src/main/res/drawable/ic_shortcut_movie_foreground.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#455A64">
<group android:scaleX="1.7226"
android:scaleY="1.7226"
android:translateX="33.3288"
android:translateY="33.3288">
<path
android:fillColor="@android:color/white"
android:pathData="M4,6.47L5.76,10H20v8H4V6.47M22,4h-4l2,4h-3l-2,-4h-2l2,4h-3l-2,-4H8l2,4H7L5,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V4z"/>
</group>
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#455A64">
<group android:scaleX="1.7226"
android:scaleY="1.7226"
android:translateX="33.3288"
android:translateY="33.3288">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</group>
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_shortcut_background"/>
<foreground android:drawable="@drawable/ic_shortcut_collection_foreground"/>
</adaptive-icon>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_shortcut_background"/>
<foreground android:drawable="@drawable/ic_shortcut_movie_foreground"/>
</adaptive-icon>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_shortcut_background"/>
<foreground android:drawable="@drawable/ic_shortcut_search_foreground"/>
</adaptive-icon>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
<color name="ic_shortcut_background">#FFFFFF</color>
</resources>
2 changes: 2 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Aves</string>
<string name="search_shortcut_short_label">Search</string>
<string name="videos_shortcut_short_label">Videos</string>
</resources>
13 changes: 13 additions & 0 deletions lib/model/filters/album.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ class AlbumFilter extends CollectionFilter {

const AlbumFilter(this.album, this.uniqueName);

AlbumFilter.fromJson(Map<String, dynamic> json)
: this(
json['album'],
json['uniqueName'],
);

@override
Map<String, dynamic> toJson() => {
'type': type,
'album': album,
'uniqueName': uniqueName,
};

@override
bool filter(ImageEntry entry) => entry.directory == album;

Expand Down
5 changes: 5 additions & 0 deletions lib/model/filters/favourite.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import 'package:flutter/widgets.dart';
class FavouriteFilter extends CollectionFilter {
static const type = 'favourite';

@override
Map<String, dynamic> toJson() => {
'type': type,
};

@override
bool filter(ImageEntry entry) => entry.isFavourite;

Expand Down
25 changes: 25 additions & 0 deletions lib/model/filters/filters.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:aves/model/filters/album.dart';
import 'package:aves/model/filters/favourite.dart';
import 'package:aves/model/filters/location.dart';
Expand All @@ -20,8 +22,31 @@ abstract class CollectionFilter implements Comparable<CollectionFilter> {
TagFilter.type,
];

static CollectionFilter fromJson(String jsonString) {
final jsonMap = jsonDecode(jsonString);
final type = jsonMap['type'];
switch (type) {
case AlbumFilter.type:
return AlbumFilter.fromJson(jsonMap);
case FavouriteFilter.type:
return FavouriteFilter();
case LocationFilter.type:
return LocationFilter.fromJson(jsonMap);
case MimeFilter.type:
return MimeFilter.fromJson(jsonMap);
case QueryFilter.type:
return QueryFilter.fromJson(jsonMap);
case TagFilter.type:
return TagFilter.fromJson(jsonMap);
}
debugPrint('failed to parse filter from json=$jsonString');
return null;
}

const CollectionFilter();

Map<String, dynamic> toJson();

bool filter(ImageEntry entry);

bool get isUnique => true;
Expand Down
Loading

0 comments on commit 60a778f

Please sign in to comment.