mirror of
https://github.com/haorendashu/nowser.git
synced 2026-02-23 10:24:24 +01:00
nowser add contentresolver support
This commit is contained in:
@@ -34,6 +34,7 @@ import 'const/base.dart';
|
||||
import 'const/colors.dart';
|
||||
import 'const/router_path.dart';
|
||||
import 'generated/l10n.dart';
|
||||
import 'provider/android_signer_content_resolver_provider.dart';
|
||||
import 'provider/data_util.dart';
|
||||
import 'provider/remote_signing_provider.dart';
|
||||
import 'provider/setting_provider.dart';
|
||||
@@ -78,6 +79,12 @@ Future<void> main() async {
|
||||
databaseFactory = databaseFactoryFfi;
|
||||
}
|
||||
|
||||
await doInit();
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
Future<void> doInit() async {
|
||||
keyProvider = KeyProvider();
|
||||
appProvider = AppProvider();
|
||||
|
||||
@@ -92,8 +99,6 @@ Future<void> main() async {
|
||||
settingProvider = futureResultList[0] as SettingProvider;
|
||||
webProvider = WebProvider();
|
||||
remoteSigningProvider = RemoteSigningProvider();
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@@ -330,3 +335,11 @@ Color _getMainColor() {
|
||||
}
|
||||
return color500;
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> nowserSignerProviderEntrypoint() async {
|
||||
// if we call content resolver this should init first, to receive request.
|
||||
// so, doInit() method move to query method.
|
||||
AndroidSignerContentResolverProvider(
|
||||
'com.github.haorendashu.nowser.SIGN_EVENT;com.github.haorendashu.nowser.NIP04_ENCRYPT;com.github.haorendashu.nowser.NIP04_DECRYPT;com.github.haorendashu.nowser.NIP44_ENCRYPT;com.github.haorendashu.nowser.NIP44_DECRYPT;com.github.haorendashu.nowser.GET_PUBLIC_KEY');
|
||||
}
|
||||
|
||||
179
lib/provider/android_signer_content_resolver_provider.dart
Normal file
179
lib/provider/android_signer_content_resolver_provider.dart
Normal file
@@ -0,0 +1,179 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:android_content_provider/android_content_provider.dart';
|
||||
import 'package:nostr_sdk/event.dart';
|
||||
import 'package:nostr_sdk/nip19/nip19.dart';
|
||||
import 'package:nostr_sdk/signer/nostr_signer.dart';
|
||||
import 'package:nostr_sdk/utils/string_util.dart';
|
||||
import 'package:nowser/const/app_type.dart';
|
||||
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||
|
||||
import '../const/auth_result.dart';
|
||||
import '../const/auth_type.dart';
|
||||
import '../data/app.dart';
|
||||
import '../main.dart';
|
||||
|
||||
class AndroidSignerContentResolverProvider extends AndroidContentProvider
|
||||
with PermissionCheckMixin {
|
||||
AndroidSignerContentResolverProvider(super.authority);
|
||||
|
||||
@override
|
||||
Future<int> delete(
|
||||
String uri, String? selection, List<String>? selectionArgs) async {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getType(String uri) async {
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> insert(String uri, ContentValues? values) async {
|
||||
return null;
|
||||
}
|
||||
|
||||
bool inited = false;
|
||||
|
||||
@override
|
||||
Future<CursorData?> query(String uri, List<String>? projection,
|
||||
String? selection, List<String>? selectionArgs, String? sortOrder) async {
|
||||
if (!inited) {
|
||||
await doInit();
|
||||
inited = true;
|
||||
}
|
||||
|
||||
var authTypeStr =
|
||||
uri.replaceAll("content://com.github.haorendashu.nowser.", "");
|
||||
String authDetail = "";
|
||||
String? pubkey;
|
||||
String? currentUser;
|
||||
if (projection != null && projection.isNotEmpty) {
|
||||
authDetail = projection.first;
|
||||
if (projection.length > 1) {
|
||||
pubkey = projection[1];
|
||||
}
|
||||
if (projection.length > 2) {
|
||||
currentUser = projection[2];
|
||||
}
|
||||
}
|
||||
|
||||
var authType = AuthType.GET_PUBLIC_KEY;
|
||||
if (authTypeStr == "GET_PUBLIC_KEY") {
|
||||
authType = AuthType.GET_PUBLIC_KEY;
|
||||
} else if (authTypeStr == "SIGN_EVENT") {
|
||||
authType = AuthType.SIGN_EVENT;
|
||||
} else if (authTypeStr == "GET_RELAYS") {
|
||||
authType = AuthType.GET_RELAYS;
|
||||
} else if (authTypeStr == "NIP04_ENCRYPT") {
|
||||
authType = AuthType.NIP04_ENCRYPT;
|
||||
} else if (authTypeStr == "NIP04_DECRYPT") {
|
||||
authType = AuthType.NIP04_DECRYPT;
|
||||
} else if (authTypeStr == "NIP44_ENCRYPT") {
|
||||
authType = AuthType.NIP44_ENCRYPT;
|
||||
} else if (authTypeStr == "NIP44_DECRYPT") {
|
||||
authType = AuthType.NIP44_DECRYPT;
|
||||
}
|
||||
|
||||
int appType = AppType.ANDROID_APP;
|
||||
String code = "com.github.haorendashu.nostrmo";
|
||||
|
||||
int? eventKind;
|
||||
dynamic eventObj;
|
||||
if (authType == AuthType.SIGN_EVENT) {
|
||||
eventObj = jsonDecode(authDetail);
|
||||
if (eventObj != null) {
|
||||
eventKind = eventObj["kind"];
|
||||
}
|
||||
}
|
||||
|
||||
App? app;
|
||||
NostrSigner? signer;
|
||||
var complete = Completer();
|
||||
|
||||
rejectFunc(_app) {
|
||||
saveAuthLog(_app, authType, eventKind, authDetail, AuthResult.REJECT);
|
||||
complete.complete();
|
||||
}
|
||||
|
||||
confirmFunc(_app, _signer) {
|
||||
app = _app;
|
||||
signer = _signer;
|
||||
complete.complete();
|
||||
}
|
||||
|
||||
checkPermission(null, appType, code, authType, rejectFunc, confirmFunc,
|
||||
eventKind: eventKind, authDetail: authDetail);
|
||||
|
||||
await complete.future;
|
||||
if (signer == null || app == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MatrixCursorData? data;
|
||||
|
||||
if (authType == AuthType.GET_PUBLIC_KEY) {
|
||||
// TODO should handle permissions
|
||||
// var permissions = extra["permissions"];
|
||||
var pubkey = await signer!.getPublicKey();
|
||||
data =
|
||||
MatrixCursorData(columnNames: ["signature"], notificationUris: [uri]);
|
||||
data.addRow([Nip19.encodePubKey(pubkey!)]);
|
||||
} else if (authType == AuthType.SIGN_EVENT) {
|
||||
var tags = eventObj["tags"];
|
||||
Event? event = Event(
|
||||
app!.pubkey!, eventObj["kind"], tags ?? [], eventObj["content"],
|
||||
createdAt: eventObj["created_at"]);
|
||||
log(jsonEncode(event.toJson()));
|
||||
event = await signer!.signEvent(event);
|
||||
if (event == null) {
|
||||
log("sign event fail");
|
||||
return null;
|
||||
}
|
||||
log("sig ${event.sig}");
|
||||
data = MatrixCursorData(
|
||||
columnNames: ["signature", "event"], notificationUris: [uri]);
|
||||
data.addRow([event.sig, jsonEncode(event.toJson())]);
|
||||
} else if (authType == AuthType.GET_RELAYS) {
|
||||
// TODO
|
||||
} else if (authType == AuthType.NIP04_ENCRYPT) {
|
||||
var result = await signer!.encrypt(pubkey, authDetail);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data = MatrixCursorData(
|
||||
columnNames: ["signature"], notificationUris: [uri]);
|
||||
data.addRow([result]);
|
||||
}
|
||||
} else if (authType == AuthType.NIP04_DECRYPT) {
|
||||
var result = await signer!.decrypt(pubkey, authDetail);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data = MatrixCursorData(
|
||||
columnNames: ["signature"], notificationUris: [uri]);
|
||||
data.addRow([result]);
|
||||
}
|
||||
} else if (authType == AuthType.NIP44_ENCRYPT) {
|
||||
var result = await signer!.nip44Encrypt(pubkey, authDetail);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data = MatrixCursorData(
|
||||
columnNames: ["signature"], notificationUris: [uri]);
|
||||
data.addRow([result]);
|
||||
}
|
||||
} else if (authType == AuthType.NIP44_DECRYPT) {
|
||||
var result = await signer!.nip44Decrypt(pubkey, authDetail);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data = MatrixCursorData(
|
||||
columnNames: ["signature"], notificationUris: [uri]);
|
||||
data.addRow([result]);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> update(String uri, ContentValues? values, String? selection,
|
||||
List<String>? selectionArgs) async {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,14 @@ import '../const/connect_type.dart';
|
||||
import '../data/app.dart';
|
||||
|
||||
mixin PermissionCheckMixin {
|
||||
Future<void> checkPermission(BuildContext context, int appType, String code,
|
||||
Future<void> checkPermission(BuildContext? context, int appType, String code,
|
||||
int authType, Function(App?) reject, Function(App, NostrSigner) confirm,
|
||||
{int? eventKind, String? authDetail}) async {
|
||||
if (keyProvider.keys.isEmpty) {
|
||||
// should add a key first
|
||||
await UserLoginDialog.show(context);
|
||||
if (context != null) {
|
||||
await UserLoginDialog.show(context);
|
||||
}
|
||||
if (keyProvider.keys.isEmpty) {
|
||||
return;
|
||||
}
|
||||
@@ -27,7 +29,9 @@ mixin PermissionCheckMixin {
|
||||
if (app == null) {
|
||||
// app is null, app connect
|
||||
var newApp = await getApp(appType, code);
|
||||
await AuthAppConnectDialog.show(context, newApp);
|
||||
if (context != null) {
|
||||
await AuthAppConnectDialog.show(context, newApp);
|
||||
}
|
||||
// reload from provider
|
||||
app = appProvider.getApp(appType, code);
|
||||
}
|
||||
@@ -63,12 +67,14 @@ mixin PermissionCheckMixin {
|
||||
return;
|
||||
}
|
||||
|
||||
var authResult = await AuthDialog.show(context, app, authType,
|
||||
eventKind: eventKind, authDetail: authDetail);
|
||||
if (authResult == AuthResult.OK) {
|
||||
saveAuthLog(app, authType, eventKind, authDetail, AuthResult.OK);
|
||||
confirm(app, signer);
|
||||
return;
|
||||
if (context != null) {
|
||||
var authResult = await AuthDialog.show(context, app, authType,
|
||||
eventKind: eventKind, authDetail: authDetail);
|
||||
if (authResult == AuthResult.OK) {
|
||||
saveAuthLog(app, authType, eventKind, authDetail, AuthResult.OK);
|
||||
confirm(app, signer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user