shortcut: icon from entry
This commit is contained in:
parent
8052347895
commit
097a051b37
8 changed files with 40 additions and 15 deletions
|
@ -38,8 +38,6 @@ import deckers.thibault.aves.utils.Utils;
|
||||||
import io.flutter.plugin.common.MethodCall;
|
import io.flutter.plugin.common.MethodCall;
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
import static com.bumptech.glide.request.RequestOptions.centerCropTransform;
|
|
||||||
|
|
||||||
public class AppAdapterHandler implements MethodChannel.MethodCallHandler {
|
public class AppAdapterHandler implements MethodChannel.MethodCallHandler {
|
||||||
private static final String LOG_TAG = Utils.createLogTag(AppAdapterHandler.class);
|
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)
|
FutureTarget<Bitmap> target = Glide.with(context)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.apply(options)
|
.apply(options)
|
||||||
.apply(centerCropTransform())
|
.centerCrop()
|
||||||
.load(uri)
|
.load(uri)
|
||||||
.signature(signature)
|
.signature(signature)
|
||||||
.submit(size, size);
|
.submit(size, size);
|
||||||
|
|
|
@ -2,6 +2,8 @@ package deckers.thibault.aves.channel.calls;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -10,6 +12,9 @@ import androidx.core.content.pm.ShortcutInfoCompat;
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
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 java.util.List;
|
||||||
|
|
||||||
import deckers.thibault.aves.MainActivity;
|
import deckers.thibault.aves.MainActivity;
|
||||||
|
@ -35,8 +40,9 @@ public class AppShortcutHandler implements MethodChannel.MethodCallHandler {
|
||||||
}
|
}
|
||||||
case "pin": {
|
case "pin": {
|
||||||
String label = call.argument("label");
|
String label = call.argument("label");
|
||||||
|
byte[] iconBytes = call.argument("iconBytes");
|
||||||
List<String> filters = call.argument("filters");
|
List<String> filters = call.argument("filters");
|
||||||
pin(label, filters);
|
new Thread(() -> pin(label, iconBytes, filters)).start();
|
||||||
result.success(null);
|
result.success(null);
|
||||||
break;
|
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) {
|
if (!ShortcutManagerCompat.isRequestPinShortcutSupported(context) || filters == null) {
|
||||||
return;
|
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))
|
ShortcutInfoCompat shortcut = new ShortcutInfoCompat.Builder(context, "collection-" + TextUtils.join("-", filters))
|
||||||
.setShortLabel(label)
|
.setShortLabel(label)
|
||||||
.setIcon(IconCompat.createWithResource(context, R.mipmap.ic_shortcut_collection))
|
.setIcon(icon)
|
||||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, context, MainActivity.class)
|
.setIntent(intent)
|
||||||
.putExtra("page", "/collection")
|
|
||||||
.putExtra("filters", filters.toArray(new String[0])))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ShortcutManagerCompat.requestPinShortcut(context, shortcut, null);
|
ShortcutManagerCompat.requestPinShortcut(context, shortcut, null);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import 'package:aves/model/filters/filters.dart';
|
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/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
@ -22,10 +24,12 @@ class AppShortcutService {
|
||||||
return false;
|
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 {
|
try {
|
||||||
await platform.invokeMethod('pin', <String, dynamic>{
|
await platform.invokeMethod('pin', <String, dynamic>{
|
||||||
'label': label,
|
'label': label,
|
||||||
|
'iconBytes': iconBytes,
|
||||||
'filters': filters.map((filter) => filter.toJson()).toList(),
|
'filters': filters.map((filter) => filter.toJson()).toList(),
|
||||||
});
|
});
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
|
|
|
@ -356,7 +356,8 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
);
|
);
|
||||||
if (name == null || name.isEmpty) return;
|
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() {
|
void _goToSearch() {
|
||||||
|
|
|
@ -87,8 +87,7 @@ class SectionHeader extends StatelessWidget {
|
||||||
// force a higher first line to match leading icon/selector dimension
|
// force a higher first line to match leading icon/selector dimension
|
||||||
style: TextStyle(height: 2.3 * textScaleFactor),
|
style: TextStyle(height: 2.3 * textScaleFactor),
|
||||||
), // 23 hair spaces match a width of 40.0
|
), // 23 hair spaces match a width of 40.0
|
||||||
if (hasTrailing)
|
if (hasTrailing) TextSpan(text: '\u200A' * 17),
|
||||||
TextSpan(text: '\u200A' * 17),
|
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: text,
|
text: text,
|
||||||
style: Constants.titleTextStyle,
|
style: Constants.titleTextStyle,
|
||||||
|
|
|
@ -43,7 +43,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
||||||
labelText: 'Shortcut label',
|
labelText: 'Shortcut label',
|
||||||
),
|
),
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
maxLength: 10,
|
maxLength: 25,
|
||||||
onChanged: (_) => _validate(),
|
onChanged: (_) => _validate(),
|
||||||
onSubmitted: (_) => _submit(context),
|
onSubmitted: (_) => _submit(context),
|
||||||
),
|
),
|
||||||
|
|
|
@ -66,6 +66,7 @@ class ThumbnailProviderKey {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
final double extent;
|
final double extent;
|
||||||
final double scale;
|
final double scale;
|
||||||
|
|
||||||
// do not access `contentId` via `entry` for hashCode and equality purposes
|
// do not access `contentId` via `entry` for hashCode and equality purposes
|
||||||
// as an entry is not constant and its contentId can change
|
// as an entry is not constant and its contentId can change
|
||||||
final int contentId;
|
final int contentId;
|
||||||
|
|
|
@ -75,7 +75,12 @@ class ScaleLayer extends StatelessWidget {
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final center = map.center;
|
final center = map.center;
|
||||||
final latitude = center.latitude.abs();
|
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 distance = scale[max(0, min(20, level))].toDouble();
|
||||||
final start = map.project(center);
|
final start = map.project(center);
|
||||||
final targetPoint = util.calculateEndingGlobalCoordinates(center, 90, distance);
|
final targetPoint = util.calculateEndingGlobalCoordinates(center, 90, distance);
|
||||||
|
|
Loading…
Reference in a new issue