shortcut: icon from entry

This commit is contained in:
Thibault Deckers 2020-09-28 13:43:25 +09:00
parent 8052347895
commit 097a051b37
8 changed files with 40 additions and 15 deletions

View file

@ -38,8 +38,6 @@ import deckers.thibault.aves.utils.Utils;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import static com.bumptech.glide.request.RequestOptions.centerCropTransform;
public class AppAdapterHandler implements MethodChannel.MethodCallHandler {
private static final String LOG_TAG = Utils.createLogTag(AppAdapterHandler.class);
@ -184,7 +182,7 @@ public class AppAdapterHandler implements MethodChannel.MethodCallHandler {
FutureTarget<Bitmap> target = Glide.with(context)
.asBitmap()
.apply(options)
.apply(centerCropTransform())
.centerCrop()
.load(uri)
.signature(signature)
.submit(size, size);

View file

@ -2,6 +2,8 @@ package deckers.thibault.aves.channel.calls;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import androidx.annotation.NonNull;
@ -10,6 +12,9 @@ import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool;
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
import java.util.List;
import deckers.thibault.aves.MainActivity;
@ -35,8 +40,9 @@ public class AppShortcutHandler implements MethodChannel.MethodCallHandler {
}
case "pin": {
String label = call.argument("label");
byte[] iconBytes = call.argument("iconBytes");
List<String> filters = call.argument("filters");
pin(label, filters);
new Thread(() -> pin(label, iconBytes, filters)).start();
result.success(null);
break;
}
@ -46,17 +52,28 @@ public class AppShortcutHandler implements MethodChannel.MethodCallHandler {
}
}
private void pin(String label, @Nullable List<String> filters) {
private void pin(String label, byte[] iconBytes, @Nullable List<String> filters) {
if (!ShortcutManagerCompat.isRequestPinShortcutSupported(context) || filters == null) {
return;
}
IconCompat icon;
if (iconBytes != null && iconBytes.length > 0) {
Bitmap bitmap = BitmapFactory.decodeByteArray(iconBytes, 0, iconBytes.length);
bitmap = TransformationUtils.centerCrop(new LruBitmapPool(2 << 24), bitmap, 256, 256);
icon = IconCompat.createWithBitmap(bitmap);
} else {
icon = IconCompat.createWithResource(context, R.mipmap.ic_shortcut_collection);
}
Intent intent = new Intent(Intent.ACTION_MAIN, null, context, MainActivity.class)
.putExtra("page", "/collection")
.putExtra("filters", filters.toArray(new String[0]));
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])))
.setIcon(icon)
.setIntent(intent)
.build();
ShortcutManagerCompat.requestPinShortcut(context, shortcut, null);

View file

@ -1,4 +1,6 @@
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/services/image_file_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
@ -22,10 +24,12 @@ class AppShortcutService {
return false;
}
static Future<void> pin(String label, Set<CollectionFilter> filters) async {
static Future<void> pin(String label, ImageEntry iconEntry, Set<CollectionFilter> filters) async {
final iconBytes = iconEntry != null ? await ImageFileService.getThumbnail(iconEntry, 256, 256) : null;
try {
await platform.invokeMethod('pin', <String, dynamic>{
'label': label,
'iconBytes': iconBytes,
'filters': filters.map((filter) => filter.toJson()).toList(),
});
} on PlatformException catch (e) {

View file

@ -356,7 +356,8 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
);
if (name == null || name.isEmpty) return;
unawaited(AppShortcutService.pin(name, collection.filters));
final iconEntry = collection.sortedEntries.isNotEmpty ? collection.sortedEntries.first : null;
unawaited(AppShortcutService.pin(name, iconEntry, collection.filters));
}
void _goToSearch() {

View file

@ -87,8 +87,7 @@ class SectionHeader extends StatelessWidget {
// force a higher first line to match leading icon/selector dimension
style: TextStyle(height: 2.3 * textScaleFactor),
), // 23 hair spaces match a width of 40.0
if (hasTrailing)
TextSpan(text: '\u200A' * 17),
if (hasTrailing) TextSpan(text: '\u200A' * 17),
TextSpan(
text: text,
style: Constants.titleTextStyle,

View file

@ -43,7 +43,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
labelText: 'Shortcut label',
),
autofocus: true,
maxLength: 10,
maxLength: 25,
onChanged: (_) => _validate(),
onSubmitted: (_) => _submit(context),
),

View file

@ -66,6 +66,7 @@ class ThumbnailProviderKey {
final ImageEntry entry;
final double extent;
final double scale;
// do not access `contentId` via `entry` for hashCode and equality purposes
// as an entry is not constant and its contentId can change
final int contentId;

View file

@ -75,7 +75,12 @@ class ScaleLayer extends StatelessWidget {
builder: (context, snapshot) {
final center = map.center;
final latitude = center.latitude.abs();
final level = map.zoom.round() + (latitude > 80 ? 4 : latitude > 60 ? 3 : 2);
final level = map.zoom.round() +
(latitude > 80
? 4
: latitude > 60
? 3
: 2);
final distance = scale[max(0, min(20, level))].toDouble();
final start = map.project(center);
final targetPoint = util.calculateEndingGlobalCoordinates(center, 90, distance);