diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/login.dart b/lib/login.dart index a221f0c..d856ad5 100644 --- a/lib/login.dart +++ b/lib/login.dart @@ -7,46 +7,46 @@ import 'package:ndk/domain_layer/entities/account.dart'; import 'package:ndk/shared/nips/nip01/bip340.dart'; import 'package:ndk/shared/nips/nip19/nip19.dart'; -class Account { +class LoginAccount { final AccountType type; final String pubkey; final String? privateKey; - Account._({required this.type, required this.pubkey, this.privateKey}); + LoginAccount._({required this.type, required this.pubkey, this.privateKey}); - static Account nip19(String key) { + static LoginAccount nip19(String key) { final keyData = Nip19.decode(key); final pubkey = Nip19.isKey("nsec", key) ? Bip340.getPublicKey(keyData) : keyData; final privateKey = Nip19.isKey("npub", key) ? null : keyData; - return Account._( - type: AccountType.privateKey, + return LoginAccount._( + type: Nip19.isKey("npub", key) ? AccountType.publicKey : AccountType.privateKey, pubkey: pubkey, privateKey: privateKey, ); } - static Account privateKeyHex(String key) { - return Account._( + static LoginAccount privateKeyHex(String key) { + return LoginAccount._( type: AccountType.privateKey, privateKey: key, pubkey: Bip340.getPublicKey(key), ); } - static Account externalPublicKeyHex(String key) { - return Account._(type: AccountType.externalSigner, pubkey: key); + static LoginAccount externalPublicKeyHex(String key) { + return LoginAccount._(type: AccountType.externalSigner, pubkey: key); } - static Map toJson(Account? acc) => { + static Map toJson(LoginAccount? acc) => { "type": acc?.type.name, "pubKey": acc?.pubkey, "privateKey": acc?.privateKey, }; - static Account? fromJson(Map json) { + static LoginAccount? fromJson(Map json) { if (json.length > 2 && json.containsKey("pubKey")) { - return Account._( + return LoginAccount._( type: AccountType.values.firstWhere( (v) => v.toString().endsWith(json["type"] as String), ), @@ -58,13 +58,13 @@ class Account { } } -class LoginData extends ValueNotifier { +class LoginData extends ValueNotifier { final _storage = FlutterSecureStorage(); static const String _storageKey = "accounts"; LoginData() : super(null) { super.addListener(() async { - final data = json.encode(Account.toJson(value)); + final data = json.encode(LoginAccount.toJson(value)); await _storage.write(key: _storageKey, value: data); }); } @@ -78,7 +78,7 @@ class LoginData extends ValueNotifier { final acc = await _storage.read(key: _storageKey); if (acc?.isNotEmpty ?? false) { try { - super.value = Account.fromJson(json.decode(acc!)); + super.value = LoginAccount.fromJson(json.decode(acc!)); } catch (e) { developer.log(e.toString()); } diff --git a/lib/main.dart b/lib/main.dart index b253abd..c5a4f0a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,8 @@ import 'package:ndk_amber/ndk_amber.dart'; import 'package:ndk_objectbox/ndk_objectbox.dart'; import 'package:ndk_rust_verifier/ndk_rust_verifier.dart'; import 'package:zap_stream_flutter/pages/login.dart'; +import 'package:zap_stream_flutter/pages/login_input.dart'; +import 'package:zap_stream_flutter/pages/new_account.dart'; import 'package:zap_stream_flutter/pages/profile.dart'; import 'package:zap_stream_flutter/pages/stream.dart'; import 'package:zap_stream_flutter/theme.dart'; @@ -87,7 +89,43 @@ Future main() async { StatefulShellBranch( routes: [ GoRoute(path: "/", builder: (ctx, state) => HomePage()), - GoRoute(path: "/login", builder: (ctx, state) => LoginPage()), + ShellRoute( + builder: (context, state, child) { + return Container( + margin: EdgeInsets.only(top: 50), + padding: EdgeInsets.symmetric(horizontal: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 20, + children: [ + Center( + child: Image.asset( + "assets/logo.png", + height: 150, + ), + ), + child, + ], + ), + ); + }, + routes: [ + GoRoute( + path: "/login", + builder: (ctx, state) => LoginPage(), + routes: [ + GoRoute( + path: "key", + builder: (ctx, state) => LoginInputPage(), + ), + GoRoute( + path: "new", + builder: (context, state) => NewAccountPage(), + ), + ], + ), + ], + ), GoRoute( path: "/e/:id", builder: (ctx, state) { diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 0e6848a..544a6ab 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -4,56 +4,53 @@ import 'package:go_router/go_router.dart'; import 'package:ndk/shared/nips/nip19/nip19.dart'; import 'package:zap_stream_flutter/login.dart'; import 'package:zap_stream_flutter/main.dart'; +import 'package:zap_stream_flutter/theme.dart'; import 'package:zap_stream_flutter/widgets/button.dart'; -class LoginPage extends StatefulWidget { +class LoginPage extends StatelessWidget { const LoginPage({super.key}); - - @override - State createState() => _LoginPage(); -} - -class _LoginPage extends State { @override Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.only(top: 50), - child: Column( - spacing: 10, - children: [ - Image.asset("assets/logo.png", height: 150), - FutureBuilder( - future: Amberflutter().isAppInstalled(), - builder: (ctx, state) { - if (state.data ?? false) { - return BasicButton.text( - "Login with Amber", - onTap: () async { - final amber = Amberflutter(); - final result = await amber.getPublicKey(); - if (result['signature'] != null) { - final key = Nip19.decode(result['signature']); - loginData.value = Account.externalPublicKeyHex(key); - ctx.go("/"); - } - }, - ); - } else { - return SizedBox.shrink(); - } - }, + return Column( + spacing: 20, + children: [ + FutureBuilder( + future: Amberflutter().isAppInstalled(), + builder: (ctx, state) { + if (state.data ?? false) { + return BasicButton.text( + "Login with Amber", + onTap: () async { + final amber = Amberflutter(); + final result = await amber.getPublicKey(); + if (result['signature'] != null) { + final key = Nip19.decode(result['signature']); + loginData.value = LoginAccount.externalPublicKeyHex(key); + ctx.go("/"); + } + }, + ); + } else { + return SizedBox.shrink(); + } + }, + ), + BasicButton.text( + "Login with Key", + onTap: () => context.push("/login/key"), + ), + Container( + margin: EdgeInsets.symmetric(vertical: 20), + height: 1, + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: LAYER_2)), ), - /*BasicButton.text("Login with Key"), - Container( - margin: EdgeInsets.symmetric(vertical: 20), - height: 1, - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: LAYER_1)), - ), - ), - Text("Create Account"),*/ - ], - ), + ), + BasicButton.text( + "Create Account", + onTap: () => context.push("/login/new"), + ), + ], ); } } diff --git a/lib/pages/login_input.dart b/lib/pages/login_input.dart new file mode 100644 index 0000000..6255831 --- /dev/null +++ b/lib/pages/login_input.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:ndk/shared/nips/nip19/nip19.dart'; +import 'package:zap_stream_flutter/login.dart'; +import 'package:zap_stream_flutter/main.dart'; +import 'package:zap_stream_flutter/theme.dart'; +import 'package:zap_stream_flutter/widgets/button.dart'; + +class LoginInputPage extends StatefulWidget { + const LoginInputPage({super.key}); + + @override + State createState() => _LoginInputPage(); +} + +class _LoginInputPage extends State { + final TextEditingController _controller = TextEditingController(); + String? _error; + + @override + Widget build(BuildContext context) { + return Column( + spacing: 20, + children: [ + TextFormField( + controller: _controller, + decoration: InputDecoration(labelText: "npub/nsec"), + ), + BasicButton.text( + "Login", + onTap: () async { + try { + final keyData = Nip19.decode(_controller.text); + if (keyData.isNotEmpty) { + loginData.value = LoginAccount.nip19(_controller.text); + context.go("/"); + } else { + throw "Invalid key"; + } + } catch (e) { + setState(() { + _error = e.toString(); + }); + } + }, + ), + + if (_error != null) + Text( + _error!, + style: TextStyle(color: WARNING, fontWeight: FontWeight.bold), + ), + ], + ); + } +} diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart new file mode 100644 index 0000000..c9928f5 --- /dev/null +++ b/lib/pages/new_account.dart @@ -0,0 +1,121 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:ndk/ndk.dart'; +import 'package:ndk/shared/nips/nip01/bip340.dart'; +import 'package:ndk/shared/nips/nip01/key_pair.dart'; +import 'package:zap_stream_flutter/login.dart'; +import 'package:zap_stream_flutter/main.dart'; +import 'package:zap_stream_flutter/theme.dart'; +import 'package:zap_stream_flutter/widgets/button.dart'; + +class NewAccountPage extends StatefulWidget { + const NewAccountPage({super.key}); + + @override + State createState() => _NewAccountPage(); +} + +class _NewAccountPage extends State { + final TextEditingController _name = TextEditingController(); + String? _avatar; + String? _error; + final KeyPair _privateKey = Bip340.generatePrivateKey(); + + Future _uploadAvatar() async { + ndk.accounts.loginPrivateKey( + pubkey: _privateKey.publicKey, + privkey: _privateKey.privateKey!, + ); + + final file = await ImagePicker().pickImage(source: ImageSource.gallery); + if (file != null) { + final upload = await ndk.blossom.uploadBlob( + serverUrls: ["https://nostr.download"], + data: await file.readAsBytes(), + ); + setState(() { + _avatar = upload.first.descriptor!.url; + }); + } + } + + Future _login() async { + if (ndk.accounts.isNotLoggedIn) { + ndk.accounts.loginPrivateKey( + pubkey: _privateKey.publicKey, + privkey: _privateKey.privateKey!, + ); + } + + await ndk.metadata.broadcastMetadata( + Metadata( + pubKey: _privateKey.publicKey, + name: _name.text, + picture: _avatar, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Column( + spacing: 20, + children: [ + GestureDetector( + onTap: () { + _uploadAvatar().catchError((e) { + setState(() { + if (e is String) { + _error = e; + } + }); + }); + }, + child: Container( + width: 200, + height: 200, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(200)), + color: Color.fromARGB(100, 50, 50, 50), + ), + child: + _avatar == null + ? Center(child: Text("Upload Avatar")) + : CachedNetworkImage(imageUrl: _avatar!), + ), + ), + TextField( + controller: _name, + decoration: InputDecoration(labelText: "Username"), + ), + BasicButton.text( + "Login", + onTap: () { + _login() + .then((_) { + loginData.value = LoginAccount.privateKeyHex( + _privateKey.privateKey!, + ); + context.go("/"); + }) + .catchError((e) { + setState(() { + if (e is String) { + _error = e; + } + }); + }); + }, + ), + if (_error != null) + Text( + _error!, + style: TextStyle(color: WARNING, fontWeight: FontWeight.bold), + ), + ], + ); + } +} diff --git a/lib/pages/stream.dart b/lib/pages/stream.dart index 5dd0cce..763ac3f 100644 --- a/lib/pages/stream.dart +++ b/lib/pages/stream.dart @@ -1,7 +1,9 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; +import 'package:zap_stream_flutter/imgproxy.dart'; import 'package:zap_stream_flutter/main.dart'; import 'package:zap_stream_flutter/theme.dart'; import 'package:zap_stream_flutter/utils.dart'; @@ -38,17 +40,20 @@ class _StreamPage extends State { _controller = VideoPlayerController.networkUrl( Uri.parse(url), httpHeaders: Map.from({"user-agent": userAgent}), - videoPlayerOptions: VideoPlayerOptions(allowBackgroundPlayback: true), ); () async { await _controller!.initialize(); - - _chewieController = ChewieController( - videoPlayerController: _controller!, - autoPlay: true, - ); setState(() { - // nothing + _chewieController = ChewieController( + videoPlayerController: _controller!, + autoPlay: true, + placeholder: + (widget.stream.info.image?.isNotEmpty ?? false) + ? CachedNetworkImage( + imageUrl: proxyImg(context, widget.stream.info.image!), + ) + : null, + ); }); }(); } @@ -75,7 +80,18 @@ class _StreamPage extends State { child: _chewieController != null ? Chewie(controller: _chewieController!) - : Container(color: LAYER_1), + : Container( + color: LAYER_1, + child: + (widget.stream.info.image?.isNotEmpty ?? false) + ? CachedNetworkImage( + imageUrl: proxyImg( + context, + widget.stream.info.image!, + ), + ) + : null, + ), ), Text( widget.stream.info.title ?? "", diff --git a/lib/theme.dart b/lib/theme.dart index 783dfbd..3f45036 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -15,3 +15,4 @@ Color LAYER_5 = Color.fromARGB(255, 173, 173, 173); Color PRIMARY_1 = Color.fromARGB(255, 248, 56, 217); Color SECONDARY_1 = Color.fromARGB(255, 52, 210, 254); Color ZAP_1 = Color.fromARGB(255, 255, 141, 43); +Color WARNING = Color.fromARGB(255, 255, 86, 63); diff --git a/lib/widgets/chat.dart b/lib/widgets/chat.dart index 286b39d..09fcdf7 100644 --- a/lib/widgets/chat.dart +++ b/lib/widgets/chat.dart @@ -207,6 +207,7 @@ class _WriteMessageWidget extends State { @override Widget build(BuildContext context) { + final canSign = ndk.accounts.canSign; final isLogin = ndk.accounts.isLoggedIn; return Container( @@ -214,7 +215,7 @@ class _WriteMessageWidget extends State { padding: EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration(color: LAYER_2, borderRadius: DEFAULT_BR), child: - isLogin + canSign ? Row( children: [ Expanded( @@ -240,7 +241,15 @@ class _WriteMessageWidget extends State { ) : Container( padding: EdgeInsets.symmetric(vertical: 12), - child: Row(children: [Text("Please login to send messages")]), + child: Row( + children: [ + Text( + isLogin + ? "Can't write messages with npub login" + : "Please login to send messages", + ), + ], + ), ), ); } diff --git a/lib/widgets/stream_grid.dart b/lib/widgets/stream_grid.dart index 961c656..eb68b6a 100644 --- a/lib/widgets/stream_grid.dart +++ b/lib/widgets/stream_grid.dart @@ -23,8 +23,8 @@ class StreamGrid extends StatelessWidget { Widget build(BuildContext context) { final streams = events .map((e) => StreamEvent(e)) - .where((e) => e.info.stream?.isNotEmpty ?? false) - .sortedBy((a) => a.info.starts ?? a.event.createdAt); + .sortedBy((a) => a.info.starts ?? a.event.createdAt) + .reversed; final live = streams.where((s) => s.info.status == StreamStatus.live); final ended = streams.where((s) => s.info.status == StreamStatus.ended); final planned = streams.where((s) => s.info.status == StreamStatus.planned); diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e370dc0..90bf20a 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,11 +6,15 @@ #include "generated_plugin_registrant.h" +#include #include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 67aa687..d9ffb5e 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux flutter_secure_storage_linux objectbox_flutter_libs url_launcher_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index aa4d181..f37b229 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import file_selector_macos import flutter_secure_storage_macos import objectbox_flutter_libs import package_info_plus @@ -15,6 +16,7 @@ import video_player_avfoundation import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 6108d2d..d539fef 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: "direct main" description: @@ -209,6 +217,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" + url: "https://pub.dev" + source: hosted + version: "0.9.4+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" fixnum: dependency: transitive description: @@ -246,6 +286,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + url: "https://pub.dev" + source: hosted + version: "2.0.28" flutter_rust_bridge: dependency: transitive description: @@ -360,6 +408,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb" + url: "https://pub.dev" + source: hosted + version: "0.8.12+23" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" js: dependency: transitive description: @@ -440,6 +552,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" ndk: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2b8f583..456a87c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,6 +28,7 @@ dependencies: qr_flutter: ^4.1.0 url_launcher: ^6.3.1 chewie: ^1.11.3 + image_picker: ^1.1.2 dependency_overrides: ndk: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 3d81177..753b413 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,11 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); ObjectboxFlutterLibsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 1891ca8..0aa0b23 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows flutter_secure_storage_windows objectbox_flutter_libs url_launcher_windows