mirror of
https://github.com/haorendashu/nowser.git
synced 2025-12-18 02:04:18 +01:00
simple support for android signer
This commit is contained in:
@@ -37,10 +37,16 @@ class _AuthAppInfoComponent extends State<AuthAppInfoComponent> {
|
||||
rightList.add(Text(
|
||||
name!,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
));
|
||||
}
|
||||
if (StringUtil.isNotBlank(des)) {
|
||||
rightList.add(Text(des!));
|
||||
rightList.add(Text(
|
||||
des!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
));
|
||||
}
|
||||
|
||||
return Stack(
|
||||
|
||||
@@ -10,7 +10,7 @@ import 'package:nowser/component/webview/web_info.dart';
|
||||
import 'package:nowser/const/app_type.dart';
|
||||
import 'package:nowser/const/auth_type.dart';
|
||||
import 'package:nowser/main.dart';
|
||||
import 'package:nowser/util/permission_check_mixin.dart';
|
||||
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||
|
||||
import '../../const/auth_result.dart';
|
||||
import '../../data/app.dart';
|
||||
@@ -248,7 +248,8 @@ class _WebViewComponent extends State<WebViewComponent>
|
||||
}, (app, signer) async {
|
||||
var tags = eventObj["tags"];
|
||||
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
||||
eventObj["content"]);
|
||||
eventObj["content"],
|
||||
publishAt: eventObj["created_at"]);
|
||||
event = await signer.signEvent(event);
|
||||
if (event == null) {
|
||||
return;
|
||||
|
||||
@@ -8,8 +8,10 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:nostr_sdk/utils/string_util.dart';
|
||||
import 'package:nowser/data/db.dart';
|
||||
import 'package:nowser/provider/android_signer_mixin.dart';
|
||||
import 'package:nowser/provider/app_provider.dart';
|
||||
import 'package:nowser/provider/key_provider.dart';
|
||||
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||
import 'package:nowser/provider/web_provider.dart';
|
||||
import 'package:nowser/router/index/index_router.dart';
|
||||
import 'package:nowser/router/keys/keys_router.dart';
|
||||
@@ -68,6 +70,11 @@ class _MyApp extends State<MyApp> {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Locale? _locale;
|
||||
@@ -78,7 +85,6 @@ class _MyApp extends State<MyApp> {
|
||||
ThemeData? defaultDarkTheme;
|
||||
defaultTheme = lightTheme;
|
||||
defaultDarkTheme = darkTheme;
|
||||
|
||||
routes = {
|
||||
RouterPath.INDEX: (context) => IndexRouter(),
|
||||
RouterPath.WEB_TABS: (context) => WebTabsSelectRouter(),
|
||||
|
||||
160
lib/provider/android_signer_mixin.dart
Normal file
160
lib/provider/android_signer_mixin.dart
Normal file
@@ -0,0 +1,160 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:nostr_sdk/event.dart';
|
||||
import 'package:nostr_sdk/utils/string_util.dart';
|
||||
import 'package:nowser/const/app_type.dart';
|
||||
import 'package:nowser/const/auth_result.dart';
|
||||
import 'package:nowser/const/auth_type.dart';
|
||||
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||
import 'package:receive_intent/receive_intent.dart' as receiveIntent;
|
||||
|
||||
mixin AndroidSignerMixin on PermissionCheckMixin {
|
||||
// StreamSubscription? _sub;
|
||||
// void listenIntent() {
|
||||
// print("listenIntent call");
|
||||
// _sub = receiveIntent.ReceiveIntent.receivedIntentStream.listen(
|
||||
// (receiveIntent.Intent? intent) {
|
||||
// log("receive intent!!!!!");
|
||||
// if (intent != null) {
|
||||
// log(intent.toString());
|
||||
// log("from ${intent.fromPackageName}");
|
||||
// log("action ${intent.action}");
|
||||
// log("data ${intent.data}");
|
||||
// log("categories ${intent.categories}");
|
||||
// log("extra ${intent.extra}");
|
||||
// }
|
||||
// }, onError: (err) {
|
||||
// print("listen error ");
|
||||
// print(err);
|
||||
// });
|
||||
// }
|
||||
|
||||
static const String PREFIX = "nostrsigner:";
|
||||
|
||||
Future<void> handleInitialIntent(BuildContext context) async {
|
||||
final intent = await receiveIntent.ReceiveIntent.getInitialIntent();
|
||||
if (intent != null) {
|
||||
log(intent.toString());
|
||||
log("from ${intent.fromPackageName}");
|
||||
log("action ${intent.action}");
|
||||
log("data ${intent.data}");
|
||||
log("categories ${intent.categories}");
|
||||
log("extra ${intent.extra}");
|
||||
|
||||
if (StringUtil.isNotBlank(intent.data) &&
|
||||
intent.data!.startsWith(PREFIX)) {
|
||||
// This is an android signer intent
|
||||
var code = intent.fromPackageName;
|
||||
// Maybe it should check this signature
|
||||
// intent.fromSignatures;
|
||||
var extra = intent.extra;
|
||||
|
||||
if (intent.extra != null) {
|
||||
var callId = extra!["id"];
|
||||
var authTypeStr = extra["type"];
|
||||
var currentUser = extra["current_user"];
|
||||
var pubkey = extra["pubKey"];
|
||||
pubkey ??= extra["pubkey"];
|
||||
|
||||
if (StringUtil.isNotBlank(callId) &&
|
||||
StringUtil.isNotBlank(authTypeStr) &&
|
||||
StringUtil.isNotBlank(code)) {
|
||||
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;
|
||||
}
|
||||
|
||||
var playload = intent.data!.replaceFirst(PREFIX, "");
|
||||
int? eventKind;
|
||||
dynamic eventObj;
|
||||
if (authType == AuthType.SIGN_EVENT) {
|
||||
print(playload);
|
||||
eventObj = jsonDecode(playload);
|
||||
if (eventObj != null) {
|
||||
eventKind = eventObj["kind"];
|
||||
print("eventKind $eventKind");
|
||||
}
|
||||
}
|
||||
|
||||
checkPermission(context, AppType.ANDROID_APP, code!, authType,
|
||||
eventKind: eventKind, authDetail: playload, () {
|
||||
// this place should do some about reject
|
||||
// saveAuthLog(app, authType, eventKind, playload, AuthResult.OK);
|
||||
}, (app, signer) async {
|
||||
print("checkPermission confrim $code");
|
||||
// confirm
|
||||
Map<String, Object?> data = {};
|
||||
data["id"] = callId;
|
||||
|
||||
if (authType == AuthType.GET_PUBLIC_KEY) {
|
||||
// TODO should handle permissions
|
||||
// var permissions = extra["permissions"];
|
||||
data["signature"] = await signer.getPublicKey();
|
||||
data["package"] = "com.github.haorendashu.nowser";
|
||||
} else if (authType == AuthType.SIGN_EVENT) {
|
||||
var tags = eventObj["tags"];
|
||||
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
||||
eventObj["content"],
|
||||
publishAt: eventObj["created_at"]);
|
||||
event = await signer.signEvent(event);
|
||||
if (event == null) {
|
||||
return;
|
||||
}
|
||||
data["signature"] = event.sig;
|
||||
data["event"] = jsonEncode(event.toJson());
|
||||
print("sig ${event.sig}");
|
||||
} else if (authType == AuthType.GET_RELAYS) {
|
||||
// TODO
|
||||
} else if (authType == AuthType.NIP04_ENCRYPT) {
|
||||
var result = await signer.encrypt(pubkey, playload);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data["signature"] = result;
|
||||
}
|
||||
} else if (authType == AuthType.NIP04_DECRYPT) {
|
||||
var result = await signer.decrypt(pubkey, playload);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data["signature"] = result;
|
||||
}
|
||||
} else if (authType == AuthType.NIP44_ENCRYPT) {
|
||||
var result = await signer.nip44Encrypt(pubkey, playload);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data["signature"] = result;
|
||||
}
|
||||
} else if (authType == AuthType.NIP44_DECRYPT) {
|
||||
var result = await signer.nip44Decrypt(pubkey, playload);
|
||||
if (StringUtil.isNotBlank(result)) {
|
||||
data["signature"] = result;
|
||||
}
|
||||
}
|
||||
|
||||
saveAuthLog(app, authType, eventKind, playload, AuthResult.OK);
|
||||
|
||||
print("setResult ok");
|
||||
print(data);
|
||||
|
||||
receiveIntent.ReceiveIntent.setResult(
|
||||
receiveIntent.kActivityResultOk,
|
||||
data: data,
|
||||
shouldFinish: true,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import 'package:nowser/router/index/index_web_component.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../component/webview/webview_component.dart';
|
||||
import '../../provider/android_signer_mixin.dart';
|
||||
import '../../provider/permission_check_mixin.dart';
|
||||
|
||||
class IndexRouter extends StatefulWidget {
|
||||
@override
|
||||
@@ -13,11 +15,16 @@ class IndexRouter extends StatefulWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _IndexRouter extends State<IndexRouter> {
|
||||
class _IndexRouter extends State<IndexRouter>
|
||||
with PermissionCheckMixin, AndroidSignerMixin {
|
||||
Map<String, WebViewComponent> webViewComponentMap = {};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
handleInitialIntent(context);
|
||||
});
|
||||
|
||||
webProvider.checkBlank();
|
||||
|
||||
var main = Selector<WebProvider, WebNumInfo>(
|
||||
|
||||
Reference in New Issue
Block a user