feat: Add an API for creating direct share shortcuts
This commit is contained in:
parent
3bc880079c
commit
052a4e4700
@ -23,8 +23,8 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.6.10'
|
ext.kotlin_version = '1.8.21'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -26,6 +26,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,25 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
'$_counter',
|
'$_counter',
|
||||||
style: Theme.of(context).textTheme.headline4,
|
style: Theme.of(context).textTheme.headline4,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
MoxplatformPlugin.contacts.recordSentMessage('Hallo', 'Welt');
|
||||||
|
},
|
||||||
|
child: Text('Test recordSentMessage (no fallback)'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
MoxplatformPlugin.contacts.recordSentMessage('Person', 'Person', fallbackIcon: FallbackIconType.person);
|
||||||
|
},
|
||||||
|
child: Text('Test recordSentMessage (person fallback)'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
MoxplatformPlugin.contacts.recordSentMessage('Notes', 'Notes', fallbackIcon: FallbackIconType.notes);
|
||||||
|
},
|
||||||
|
child: Text('Test recordSentMessage (notes fallback)'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
117
flake.lock
117
flake.lock
@ -1,6 +1,66 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"android-nixpkgs": {
|
||||||
|
"inputs": {
|
||||||
|
"devshell": "devshell",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689798050,
|
||||||
|
"narHash": "sha256-ZyFPra7N0MF803o55dYQQyX9b/BmXr6QTCyN7slRThY=",
|
||||||
|
"owner": "tadfisher",
|
||||||
|
"repo": "android-nixpkgs",
|
||||||
|
"rev": "9aa0e2990da86de8ca203af313668851dcb9ea6e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "tadfisher",
|
||||||
|
"repo": "android-nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devshell": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"android-nixpkgs",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1688380630,
|
||||||
|
"narHash": "sha256-8ilApWVb1mAi4439zS3iFeIT0ODlbrifm/fegWwgHjA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "devshell",
|
||||||
|
"rev": "f9238ec3d75cefbb2b42a44948c4e8fb1ae9a205",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "devshell",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689068808,
|
||||||
|
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1649676176,
|
"lastModified": 1649676176,
|
||||||
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
|
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
|
||||||
@ -17,11 +77,27 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1660551188,
|
"lastModified": 1689679375,
|
||||||
"narHash": "sha256-a1LARMMYQ8DPx1BgoI/UN4bXe12hhZkCNqdxNi6uS0g=",
|
"narHash": "sha256-LHUC52WvyVDi9PwyL1QCpaxYWBqp4ir4iL6zgOkmcb8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "441dc5d512153039f19ef198e662e4f3dbb9fd65",
|
"rev": "684c17c429c42515bafb3ad775d2a710947f3d67",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689752456,
|
||||||
|
"narHash": "sha256-VOChdECcEI8ixz8QY+YC4JaNEFwQd1V8bA0G4B28Ki0=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "7f256d7da238cb627ef189d56ed590739f42f13b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -33,8 +109,39 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"android-nixpkgs": "android-nixpkgs",
|
||||||
"nixpkgs": "nixpkgs"
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
54
flake.nix
54
flake.nix
@ -3,9 +3,10 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
android-nixpkgs.url = "github:tadfisher/android-nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let
|
outputs = { self, nixpkgs, flake-utils, android-nixpkgs }: flake-utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
config = {
|
config = {
|
||||||
@ -13,29 +14,32 @@
|
|||||||
allowUnfree = true;
|
allowUnfree = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
android = pkgs.androidenv.composeAndroidPackages {
|
# Everything to make Flutter happy
|
||||||
# TODO: Find a way to pin these
|
sdk = android-nixpkgs.sdk.${system} (sdkPkgs: with sdkPkgs; [
|
||||||
#toolsVersion = "26.1.1";
|
cmdline-tools-latest
|
||||||
#platformToolsVersion = "31.0.3";
|
build-tools-30-0-3
|
||||||
#buildToolsVersions = [ "31.0.0" ];
|
build-tools-33-0-2
|
||||||
#includeEmulator = true;
|
build-tools-34-0-0
|
||||||
#emulatorVersion = "30.6.3";
|
platform-tools
|
||||||
platformVersions = [ "28" ];
|
emulator
|
||||||
includeSources = false;
|
patcher-v4
|
||||||
includeSystemImages = true;
|
platforms-android-30
|
||||||
systemImageTypes = [ "default" ];
|
platforms-android-31
|
||||||
abiVersions = [ "x86_64" ];
|
platforms-android-33
|
||||||
includeNDK = false;
|
]);
|
||||||
useGoogleAPIs = false;
|
pinnedJDK = pkgs.jdk17;
|
||||||
useGoogleTVAddOns = false;
|
|
||||||
};
|
|
||||||
pinnedJDK = pkgs.jdk;
|
|
||||||
in {
|
in {
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
flutter pinnedJDK android.platform-tools dart # Flutter
|
# Android
|
||||||
gitlint jq # Code hygiene
|
pinnedJDK
|
||||||
ripgrep # General utilities
|
sdk
|
||||||
|
|
||||||
|
# Flutter
|
||||||
|
flutter dart
|
||||||
|
|
||||||
|
# Code hygiene
|
||||||
|
gitlint
|
||||||
|
|
||||||
# Flutter dependencies for linux desktop
|
# Flutter dependencies for linux desktop
|
||||||
atk
|
atk
|
||||||
@ -59,9 +63,13 @@
|
|||||||
CPATH = "${pkgs.xorg.libX11.dev}/include:${pkgs.xorg.xorgproto}/include";
|
CPATH = "${pkgs.xorg.libX11.dev}/include:${pkgs.xorg.xorgproto}/include";
|
||||||
LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath [ atk cairo epoxy gdk-pixbuf glib gtk3 harfbuzz pango ];
|
LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath [ atk cairo epoxy gdk-pixbuf glib gtk3 harfbuzz pango ];
|
||||||
|
|
||||||
ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk";
|
ANDROID_HOME = "${sdk}/share/android-sdk";
|
||||||
|
ANDROID_SDK_ROOT = "${sdk}/share/android-sdk";
|
||||||
JAVA_HOME = pinnedJDK;
|
JAVA_HOME = pinnedJDK;
|
||||||
ANDROID_AVD_HOME = (toString ./.) + "/.android/avd";
|
|
||||||
|
# Fix an issue with Flutter using an older version of aapt2, which does not know
|
||||||
|
# an used parameter.
|
||||||
|
GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${sdk}/share/android-sdk/build-tools/34.0.0/aapt2";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,5 @@ class MoxplatformPlugin {
|
|||||||
static IsolateHandler get handler => MoxplatformInterface.handler;
|
static IsolateHandler get handler => MoxplatformInterface.handler;
|
||||||
static MediaScannerImplementation get media => MoxplatformInterface.media;
|
static MediaScannerImplementation get media => MoxplatformInterface.media;
|
||||||
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
||||||
|
static ContactsImplementation get contacts => MoxplatformInterface.contacts;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ android {
|
|||||||
compileSdkVersion 31
|
compileSdkVersion 31
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_14
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_14
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@ -36,4 +36,5 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
||||||
|
implementation 'androidx.core:core:1.10.1'
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -6,17 +6,28 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.drawable.Icon;
|
||||||
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.app.Person;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||||
|
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||||
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.CipherOutputStream;
|
import javax.crypto.CipherOutputStream;
|
||||||
@ -191,12 +202,79 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
});
|
});
|
||||||
hashingThread.start();
|
hashingThread.start();
|
||||||
break;
|
break;
|
||||||
|
case "recordSentMessage":
|
||||||
|
ArrayList rargs = (ArrayList) call.arguments;
|
||||||
|
try {
|
||||||
|
recordSentMessage(
|
||||||
|
(String) rargs.get(0),
|
||||||
|
(String) rargs.get(1),
|
||||||
|
(String) rargs.get(2),
|
||||||
|
(int) rargs.get(3)
|
||||||
|
);
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
Log.e(TAG, "Failed to get classname");
|
||||||
|
Log.e(TAG, ex.getMessage());
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result.notImplemented();
|
result.notImplemented();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recordSentMessage(String name, String jid, String avatarPath, int fallbackIconType) throws ClassNotFoundException {
|
||||||
|
// Very much inspired (or copied) from https://github.com/ShoutSocial/share_handler
|
||||||
|
final String pkgName = context.getPackageName();
|
||||||
|
final Intent intent = new Intent(context, Class.forName(pkgName + ".MainActivity"));
|
||||||
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
|
|
||||||
|
// Compatibility with share_handler
|
||||||
|
intent.putExtra("conversationIdentifier", jid);
|
||||||
|
|
||||||
|
final String shortcutTarget = pkgName + ".dynamic_share_target";
|
||||||
|
final ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(context, name);
|
||||||
|
builder
|
||||||
|
.setShortLabel(name)
|
||||||
|
.setIsConversation()
|
||||||
|
.setCategories(Set.of(shortcutTarget))
|
||||||
|
.setIntent(intent)
|
||||||
|
.setLongLived(true);
|
||||||
|
|
||||||
|
// TODO: This is dumb. Maybe just raise the minimum Android version
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
|
||||||
|
final Person.Builder personBuilder = new Person.Builder()
|
||||||
|
.setKey(jid)
|
||||||
|
.setName(name);
|
||||||
|
|
||||||
|
if (avatarPath != null) {
|
||||||
|
final Bitmap bitmap = BitmapFactory.decodeFile(avatarPath);
|
||||||
|
final IconCompat icon = IconCompat.createWithAdaptiveBitmap(bitmap);
|
||||||
|
builder.setIcon(icon);
|
||||||
|
personBuilder.setIcon(icon);
|
||||||
|
} else {
|
||||||
|
if (fallbackIconType == 0 || fallbackIconType == 1) {
|
||||||
|
final int id = switch (fallbackIconType) {
|
||||||
|
default:
|
||||||
|
case 0: yield R.mipmap.person;
|
||||||
|
case 1: yield R.mipmap.notes;
|
||||||
|
};
|
||||||
|
final IconCompat personIcon = IconCompat.createWithResource(
|
||||||
|
context,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
builder.setIcon(personIcon);
|
||||||
|
personBuilder.setIcon(personIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setPerson(personBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
final ShortcutInfoCompat shortcut = builder.build();
|
||||||
|
ShortcutManagerCompat.addDynamicShortcuts(context, List.of(shortcut));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.getAction() == null) return;
|
if (intent.getAction() == null) return;
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<group android:scaleX="0.42988887"
|
||||||
|
android:scaleY="0.42988887"
|
||||||
|
android:translateX="6.8413334"
|
||||||
|
android:translateY="6.8413334">
|
||||||
|
<path
|
||||||
|
android:pathData="M3,18h12v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h18v-2L3,11v2z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<group android:scaleX="0.483625"
|
||||||
|
android:scaleY="0.483625"
|
||||||
|
android:translateX="6.1965"
|
||||||
|
android:translateY="6.1965">
|
||||||
|
<path
|
||||||
|
android:pathData="m12,12c2.21,0 4,-1.79 4,-4C16,5.79 14.21,4 12,4 9.79,4 8,5.79 8,8c0,2.21 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"
|
||||||
|
android:fillColor="#fffff9"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
@ -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/notes_background"/>
|
||||||
|
<foreground android:drawable="@drawable/notes_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -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/person_background"/>
|
||||||
|
<foreground android:drawable="@drawable/person_foreground"/>
|
||||||
|
</adaptive-icon>
|
Binary file not shown.
After Width: | Height: | Size: 650 B |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="notes_background">#CF4AFF</color>
|
||||||
|
</resources>
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="person_background">#CF4AFF</color>
|
||||||
|
</resources>
|
32
packages/moxplatform_android/lib/src/contacts_android.dart
Normal file
32
packages/moxplatform_android/lib/src/contacts_android.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
||||||
|
|
||||||
|
class AndroidContactsImplementation extends ContactsImplementation {
|
||||||
|
final _methodChannel = const MethodChannel('me.polynom.moxplatform_android');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> recordSentMessage(
|
||||||
|
String name,
|
||||||
|
String jid, {
|
||||||
|
String? avatarPath,
|
||||||
|
FallbackIconType fallbackIcon = FallbackIconType.none,
|
||||||
|
}) async {
|
||||||
|
// Ensure we always have an icon
|
||||||
|
if (avatarPath != null) {
|
||||||
|
assert(
|
||||||
|
fallbackIcon != FallbackIconType.none,
|
||||||
|
'If no avatar is specified, then a fallbackIcon must be set',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _methodChannel.invokeMethod<void>(
|
||||||
|
'recordSentMessage',
|
||||||
|
[
|
||||||
|
name,
|
||||||
|
jid,
|
||||||
|
avatarPath,
|
||||||
|
fallbackIcon.id,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:moxplatform_android/src/contacts_android.dart';
|
||||||
import 'package:moxplatform_android/src/crypto_android.dart';
|
import 'package:moxplatform_android/src/crypto_android.dart';
|
||||||
import 'package:moxplatform_android/src/isolate_android.dart';
|
import 'package:moxplatform_android/src/isolate_android.dart';
|
||||||
import 'package:moxplatform_android/src/media_android.dart';
|
import 'package:moxplatform_android/src/media_android.dart';
|
||||||
@ -7,9 +8,10 @@ class MoxplatformAndroidPlugin extends MoxplatformInterface {
|
|||||||
static void registerWith() {
|
static void registerWith() {
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
print('MoxplatformAndroidPlugin: Registering implementation');
|
print('MoxplatformAndroidPlugin: Registering implementation');
|
||||||
|
MoxplatformInterface.contacts = AndroidContactsImplementation();
|
||||||
|
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
||||||
MoxplatformInterface.handler = AndroidIsolateHandler();
|
MoxplatformInterface.handler = AndroidIsolateHandler();
|
||||||
MoxplatformInterface.media = AndroidMediaScannerImplementation();
|
MoxplatformInterface.media = AndroidMediaScannerImplementation();
|
||||||
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
library moxplatform_platform_interface;
|
library moxplatform_platform_interface;
|
||||||
|
|
||||||
|
export 'src/contacts.dart';
|
||||||
|
export 'src/contacts_stub.dart';
|
||||||
export 'src/crypto.dart';
|
export 'src/crypto.dart';
|
||||||
export 'src/crypto_stub.dart';
|
export 'src/crypto_stub.dart';
|
||||||
export 'src/interface.dart';
|
export 'src/interface.dart';
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
// The type of icon to use when no avatar path is provided.
|
||||||
|
enum FallbackIconType {
|
||||||
|
none(-1),
|
||||||
|
person(0),
|
||||||
|
notes(1);
|
||||||
|
|
||||||
|
const FallbackIconType(this.id);
|
||||||
|
|
||||||
|
// The ID of the fallback icon.
|
||||||
|
final int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapper around various contact APIs.
|
||||||
|
// ignore: one_member_abstracts
|
||||||
|
abstract class ContactsImplementation {
|
||||||
|
Future<void> recordSentMessage(
|
||||||
|
String name,
|
||||||
|
String jid, {
|
||||||
|
String? avatarPath,
|
||||||
|
FallbackIconType fallbackIcon = FallbackIconType.none,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import 'package:moxplatform_platform_interface/src/contacts.dart';
|
||||||
|
|
||||||
|
class StubContactsImplementation extends ContactsImplementation {
|
||||||
|
@override
|
||||||
|
Future<void> recordSentMessage(
|
||||||
|
String name,
|
||||||
|
String jid, {
|
||||||
|
String? avatarPath,
|
||||||
|
FallbackIconType fallbackIcon = FallbackIconType.none,
|
||||||
|
}) async {}
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:moxplatform_platform_interface/src/contacts.dart';
|
||||||
|
import 'package:moxplatform_platform_interface/src/contacts_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/crypto.dart';
|
import 'package:moxplatform_platform_interface/src/crypto.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
||||||
@ -14,6 +16,7 @@ abstract class MoxplatformInterface extends PlatformInterface {
|
|||||||
static IsolateHandler handler = StubIsolateHandler();
|
static IsolateHandler handler = StubIsolateHandler();
|
||||||
static MediaScannerImplementation media = StubMediaScannerImplementation();
|
static MediaScannerImplementation media = StubMediaScannerImplementation();
|
||||||
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
||||||
|
static ContactsImplementation contacts = StubContactsImplementation();
|
||||||
|
|
||||||
/// Return the current platform name.
|
/// Return the current platform name.
|
||||||
Future<String?> getPlatformName();
|
Future<String?> getPlatformName();
|
||||||
|
Reference in New Issue
Block a user