From 2e24a04607e4023a82f1a535ec50f8a4dd178786 Mon Sep 17 00:00:00 2001 From: Sun Date: Wed, 9 Jun 2021 11:08:03 +0800 Subject: [PATCH] unify select image as avatar --- lib/apps/group_chat/add.dart | 32 +++- lib/pages/account_generate.dart | 143 ++--------------- lib/pages/setting/profile.dart | 146 ++---------------- lib/widgets/select_avatar.dart | 137 ++++++++++++++++ linux/flutter/generated_plugin_registrant.cc | 2 + linux/flutter/generated_plugin_registrant.h | 2 + pubspec.lock | 20 +-- src/apps/group_chat/rpc.rs | 17 +- src/storage.rs | 16 ++ .../flutter/generated_plugin_registrant.cc | 2 + windows/flutter/generated_plugin_registrant.h | 2 + 11 files changed, 230 insertions(+), 289 deletions(-) create mode 100644 lib/widgets/select_avatar.dart diff --git a/lib/apps/group_chat/add.dart b/lib/apps/group_chat/add.dart index c3cc8c5..eb1a7d1 100644 --- a/lib/apps/group_chat/add.dart +++ b/lib/apps/group_chat/add.dart @@ -1,4 +1,5 @@ -import 'dart:async'; +import 'dart:convert' show base64; +import 'dart:typed_data' show Uint8List; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; @@ -13,6 +14,7 @@ import 'package:esse/widgets/user_info.dart'; import 'package:esse/widgets/shadow_button.dart'; import 'package:esse/widgets/shadow_dialog.dart'; import 'package:esse/widgets/qr_scan.dart'; +import 'package:esse/widgets/select_avatar.dart'; import 'package:esse/global.dart'; import 'package:esse/rpc.dart'; import 'package:esse/provider.dart'; @@ -47,6 +49,7 @@ class _GroupAddPageState extends State { FocusNode _createNameFocus = FocusNode(); FocusNode _createBioFocus = FocusNode(); FocusNode _createKeyFocus = FocusNode(); + Uint8List _createAvatarBytes; int _groupAddr = 0; int _groupType = 1; @@ -151,7 +154,8 @@ class _GroupAddPageState extends State { } final name = _createNameController.text.trim(); final bio = _createBioController.text.trim(); - rpc.send('group-chat-create', [_groupType, _myName, addr, name, bio, _groupNeedAgree]); + final avatar = _createAvatarBytes != null ? base64.encode(_createAvatarBytes) : ""; + rpc.send('group-chat-create', [_groupType, _myName, addr, name, bio, _groupNeedAgree, avatar]); setState(() { _createNameController.text = ''; _createBioController.text = ''; @@ -414,20 +418,32 @@ class _GroupAddPageState extends State { margin: const EdgeInsets.symmetric(vertical: 10.0), decoration: BoxDecoration( color: color.surface, + image: _createAvatarBytes != null ? DecorationImage( + image: MemoryImage(_createAvatarBytes), + fit: BoxFit.cover, + ) : null, borderRadius: BorderRadius.circular(15.0)), child: Stack( alignment: Alignment.center, children: [ - Icon(Icons.camera_alt, - size: 47.0, color: Color(0xFFADB0BB)), + if (_createAvatarBytes == null) + Icon(Icons.camera_alt, size: 48.0, color: Color(0xFFADB0BB)), Positioned( bottom: -1.0, right: -1.0, child: InkWell( - child: Icon(Icons.add_circle, - size: 32.0, color: color.primary), - onTap: null, //() => _getImage(context, account.name, color, lang), - ) + child: Container( + decoration: const ShapeDecoration( + color: Colors.white, + shape: CircleBorder(), + ), + child: Icon(Icons.add_circle, + size: 32.0, color: color.primary), + ), + onTap: () => selectAvatar(context, (bytes) => setState(() { + _createAvatarBytes = bytes; + })), + ), ), ], ), diff --git a/lib/pages/account_generate.dart b/lib/pages/account_generate.dart index 71a6d1e..4110cd0 100644 --- a/lib/pages/account_generate.dart +++ b/lib/pages/account_generate.dart @@ -1,20 +1,17 @@ -import 'dart:io' show File; -import 'dart:ui'; -import 'dart:convert'; -import 'dart:typed_data'; +import 'dart:convert' show base64; +import 'dart:typed_data' show Uint8List; -import 'package:crop/crop.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:esse/l10n/localizations.dart'; -import 'package:esse/utils/pick_image.dart'; import 'package:esse/utils/mnemonic.dart'; import 'package:esse/utils/device_info.dart'; import 'package:esse/widgets/button_text.dart'; import 'package:esse/widgets/shadow_dialog.dart'; import 'package:esse/widgets/show_pin.dart'; +import 'package:esse/widgets/select_avatar.dart'; import 'package:esse/pages/home.dart'; import 'package:esse/account.dart'; import 'package:esse/global.dart'; @@ -43,8 +40,6 @@ class _AccountGeneratePageState extends State { TextEditingController _nameController = new TextEditingController(); FocusNode _nameFocus = new FocusNode(); - CropController _imageController = CropController(); - double _imageScale = 1.0; Uint8List _imageBytes; @override @@ -119,97 +114,6 @@ class _AccountGeneratePageState extends State { ); } - void getImage(context, color, lang) async { - final imagePath = await pickImage(); - if (imagePath == null) { - return; - } - final image = File(imagePath); - - showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - barrierColor: Color(0x26ADB0BB), - transitionDuration: const Duration(milliseconds: 150), - transitionBuilder: _buildMaterialDialogTransitions, - pageBuilder: (BuildContext context, Animation animation, - Animation secondaryAnimation) { - return AlertDialog( - content: Container( - height: 180.0, - padding: EdgeInsets.only(top: 20.0), - child: Column(children: [ - Container( - height: 100.0, - width: 100.0, - child: Crop( - controller: _imageController, - shape: BoxShape.rectangle, - helper: Container( - decoration: BoxDecoration( - border: - Border.all(color: color.primary, width: 2), - ), - child: Icon(Icons.filter_center_focus_rounded, - color: color.primary), - ), - child: Image( - image: FileImage(image), fit: BoxFit.cover)), - ), - SizedBox(height: 20.0), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.max, - children: [ - GestureDetector( - child: Icon(Icons.zoom_in_rounded, - size: 30.0, color: color.primary), - onTap: () => setState(() { - _imageScale += 0.5; - _imageController.scale = _imageScale; - }), - ), - GestureDetector( - child: Icon(Icons.zoom_out_rounded, - size: 30.0, color: color.primary), - onTap: () => setState(() { - if (_imageScale > 1.0) { - _imageScale -= 0.5; - _imageController.scale = _imageScale; - } - }), - ), - ]) - ])), - actions: [ - Container( - margin: const EdgeInsets.only(right: 40.0, bottom: 20.0), - child: GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: Text(lang.cancel))), - Container( - margin: const EdgeInsets.only(right: 20.0, bottom: 20.0), - child: GestureDetector( - onTap: () async { - final pixelRatio = - MediaQuery.of(context).devicePixelRatio; - final cropped = await _imageController.crop( - pixelRatio: pixelRatio); - final byteData = await cropped.toByteData( - format: ImageByteFormat.png); - Navigator.of(context).pop(); - setState(() { - _imageBytes = byteData.buffer.asUint8List(); - }); - }, - child: Text(lang.ok, - style: TextStyle(color: color.primary)))), - ]); - }); - } - Widget _mnemonicState(ColorScheme color, AppLocalizations lang) { List mnemonicWordWidgets = []; if (this._mnemoicWords.length > 1) { @@ -373,35 +277,25 @@ class _AccountGeneratePageState extends State { } Widget newAccountAvatar(color, lang) { - final noImage = _imageBytes == null; return Container( width: 100, height: 100, - decoration: noImage - ? BoxDecoration( - color: color.surface, borderRadius: BorderRadius.circular(15.0)) - : BoxDecoration( + decoration: BoxDecoration( color: color.surface, - image: DecorationImage( + image: _imageBytes == null ? DecorationImage( image: MemoryImage(_imageBytes), fit: BoxFit.cover, - ), + ) : null, borderRadius: BorderRadius.circular(15.0)), child: Stack( alignment: Alignment.center, children: [ - if (noImage) + if (_imageBytes == null) Icon(Icons.camera_alt, size: 47.0, color: Color(0xFFADB0BB)), Positioned( bottom: -1.0, right: -1.0, - child: noImage - ? InkWell( - child: Icon(Icons.add_circle, - size: 32.0, color: color.primary), - onTap: () => getImage(context, color, lang), - ) - : InkWell( + child: InkWell( child: Container( decoration: const ShapeDecoration( color: Colors.white, @@ -410,7 +304,9 @@ class _AccountGeneratePageState extends State { child: Icon(Icons.add_circle, size: 32.0, color: color.primary), ), - onTap: () => getImage(context, color, lang), + onTap: () => selectAvatar(context, (bytes) => setState(() { + _imageBytes = bytes; + })), ), ), ], @@ -461,20 +357,3 @@ Widget _footer(String text1, Function callback) { ), ); } - -Widget _buildMaterialDialogTransitions( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - Widget child) { - return BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 4 * animation.value, sigmaY: 4 * animation.value), - child: ScaleTransition( - scale: CurvedAnimation( - parent: animation, - curve: Curves.easeOut, - ), - child: child, - )); -} diff --git a/lib/pages/setting/profile.dart b/lib/pages/setting/profile.dart index 1474472..194b13e 100644 --- a/lib/pages/setting/profile.dart +++ b/lib/pages/setting/profile.dart @@ -1,14 +1,11 @@ -import 'dart:io' show File; -import 'dart:ui'; -import 'package:crop/crop.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:esse/l10n/localizations.dart'; -import 'package:esse/utils/pick_image.dart'; import 'package:esse/utils/better_print.dart'; import 'package:esse/widgets/shadow_dialog.dart'; import 'package:esse/widgets/show_pin.dart'; +import 'package:esse/widgets/select_avatar.dart'; import 'package:esse/global.dart'; import 'package:esse/rpc.dart'; import 'package:esse/provider.dart'; @@ -21,103 +18,11 @@ class ProfileDetail extends StatefulWidget { } class _ProfileDetailState extends State { - CropController _imageController = CropController(); TextEditingController _nameController = TextEditingController(); - double _imageScale = 1.0; bool _changeName = false; bool _mnemoicShow = false; List _mnemoicWords = []; - void _getImage(context, name, color, lang) async { - final imagePath = await pickImage(); - if (imagePath == null) { - return; - } - final image = File(imagePath); - - showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - barrierColor: Color(0x26ADB0BB), - transitionDuration: const Duration(milliseconds: 150), - transitionBuilder: _buildMaterialDialogTransitions, - pageBuilder: (BuildContext context, Animation animation, - Animation secondaryAnimation) { - return AlertDialog( - content: Container( - height: 180.0, - padding: EdgeInsets.only(top: 20.0), - child: Column(children: [ - Container( - height: 100.0, - width: 100.0, - child: Crop( - controller: _imageController, - shape: BoxShape.rectangle, - helper: Container( - decoration: BoxDecoration( - border: - Border.all(color: color.primary, width: 2), - ), - child: Icon(Icons.filter_center_focus_rounded, - color: color.primary), - ), - child: Image( - image: FileImage(image), fit: BoxFit.cover)), - ), - SizedBox(height: 20.0), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.max, - children: [ - GestureDetector( - child: Icon(Icons.zoom_in_rounded, - size: 30.0, color: color.primary), - onTap: () => setState(() { - _imageScale += 0.5; - _imageController.scale = _imageScale; - }), - ), - GestureDetector( - child: Icon(Icons.zoom_out_rounded, - size: 30.0, color: color.primary), - onTap: () => setState(() { - if (_imageScale > 1.0) { - _imageScale -= 0.5; - _imageController.scale = _imageScale; - } - }), - ), - ]) - ])), - actions: [ - Container( - margin: const EdgeInsets.only(right: 40.0, bottom: 20.0), - child: GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: Text(lang.cancel))), - Container( - margin: const EdgeInsets.only(right: 20.0, bottom: 20.0), - child: GestureDetector( - onTap: () async { - final pixelRatio = - MediaQuery.of(context).devicePixelRatio; - final cropped = await _imageController.crop( - pixelRatio: pixelRatio); - final byteData = await cropped.toByteData( - format: ImageByteFormat.png); - Navigator.of(context).pop(); - context.read().accountUpdate( - name, byteData.buffer.asUint8List()); - }, - child: Text(lang.ok, - style: TextStyle(color: color.primary)))), - ]); - }); - } - Widget _infoListTooltip(icon, color, text) { return SizedBox( width: 300.0, @@ -169,25 +74,19 @@ class _ProfileDetailState extends State { Positioned( bottom: -1.0, right: -1.0, - child: noImage - ? InkWell( - child: Icon(Icons.add_circle, - size: 32.0, color: color.primary), - onTap: () => - _getImage(context, account.name, color, lang), - ) - : InkWell( - child: Container( - decoration: const ShapeDecoration( - color: Colors.white, - shape: CircleBorder(), - ), - child: Icon(Icons.add_circle, - size: 32.0, color: color.primary), - ), - onTap: () => - _getImage(context, account.name, color, lang), - ), + child: InkWell( + child: Container( + decoration: const ShapeDecoration( + color: Colors.white, + shape: CircleBorder(), + ), + child: Icon(Icons.add_circle, + size: 32.0, color: color.primary), + ), + onTap: () => selectAvatar(context, (bytes) => + context.read().accountUpdate(account.name, bytes), + ), + ), ), ], ), @@ -381,20 +280,3 @@ class _ProfileDetailState extends State { })); } } - -Widget _buildMaterialDialogTransitions( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - Widget child) { - return BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 4 * animation.value, sigmaY: 4 * animation.value), - child: ScaleTransition( - scale: CurvedAnimation( - parent: animation, - curve: Curves.easeOut, - ), - child: child, - )); -} diff --git a/lib/widgets/select_avatar.dart b/lib/widgets/select_avatar.dart new file mode 100644 index 0000000..bedc95a --- /dev/null +++ b/lib/widgets/select_avatar.dart @@ -0,0 +1,137 @@ +import 'dart:async'; +import 'dart:io' show File; +import 'dart:ui' show ImageByteFormat, ImageFilter; + +import 'package:crop/crop.dart'; +import 'package:flutter/material.dart'; + +import 'package:esse/l10n/localizations.dart'; +import 'package:esse/utils/pick_image.dart'; +import 'package:esse/widgets/shadow_dialog.dart'; + +class _CropAvatar extends StatefulWidget { + final Function callback; + final File image; + + _CropAvatar({Key key, this.callback, this.image}) : super(key: key); + + @override + _CropAvatarState createState() => _CropAvatarState(); +} + +class _CropAvatarState extends State<_CropAvatar> { + CropController _imageController = CropController(aspectRatio: 1.0); + double _imageScale = 1.0; + + @override + Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme; + final lang = AppLocalizations.of(context); + + return AlertDialog( + content: Container( + height: 180.0, + //width: 200.0, + padding: EdgeInsets.only(top: 20.0), + child: Column(children: [ + Container( + height: 120.0, + width: 120.0, + child: Crop( + controller: _imageController, + shape: BoxShape.rectangle, + helper: Container( + decoration: BoxDecoration( + //borderRadius: BorderRadius.circular(15.0), + border: Border.all(color: color.primary, width: 2), + ), + child: Icon(Icons.filter_center_focus_rounded, + color: color.primary), + ), + child: Image( + image: FileImage(widget.image), fit: BoxFit.cover)), + ), + const SizedBox(height: 8.0), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.max, + children: [ + GestureDetector( + child: Icon(Icons.zoom_in_rounded, + size: 30.0, color: color.primary), + onTap: () => setState(() { + _imageScale += 0.5; + _imageController.scale = _imageScale; + }), + ), + GestureDetector( + child: Icon(Icons.zoom_out_rounded, + size: 30.0, color: color.primary), + onTap: () => setState(() { + if (_imageScale > 1.0) { + _imageScale -= 0.5; + _imageController.scale = _imageScale; + } + }), + ), + ]) + ])), + actions: [ + Container( + margin: const EdgeInsets.only(right: 40.0, bottom: 20.0), + child: GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Text(lang.cancel))), + Container( + margin: const EdgeInsets.only(right: 20.0, bottom: 20.0), + child: GestureDetector( + onTap: () async { + final pixelRatio = MediaQuery.of(context).devicePixelRatio; + final cropped = await _imageController.crop(pixelRatio: pixelRatio); + final byteData = await cropped.toByteData(format: ImageByteFormat.png); + Navigator.of(context).pop(); + widget.callback(byteData.buffer.asUint8List()); + }, + child: Text(lang.ok, + style: TextStyle(color: color.primary)))), + ]); + } +} + +Widget _buildMaterialDialogTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + return BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 4 * animation.value, sigmaY: 4 * animation.value), + child: ScaleTransition( + scale: CurvedAnimation( + parent: animation, + curve: Curves.easeOut, + ), + child: child, + )); +} + +void selectAvatar(BuildContext context, Function callback) async { + final imagePath = await pickImage(); + if (imagePath == null) { + return; + } + final image = File(imagePath); + + showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: + MaterialLocalizations.of(context).modalBarrierDismissLabel, + barrierColor: Color(0x26ADB0BB), + transitionDuration: const Duration(milliseconds: 150), + transitionBuilder: _buildMaterialDialogTransitions, + pageBuilder: (BuildContext context, Animation animation, + Animation secondaryAnimation) { + return _CropAvatar(callback: callback, image: image); + }); +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index a00bb93..2f5f543 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" #include diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h index 9bf7478..e0f0a47 100644 --- a/linux/flutter/generated_plugin_registrant.h +++ b/linux/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/pubspec.lock b/pubspec.lock index d7854a7..f59048e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -161,7 +161,7 @@ packages: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.2" file: dependency: transitive description: @@ -309,7 +309,7 @@ packages: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.7.5+3" + version: "0.8.0+1" image_picker_for_web: dependency: transitive description: @@ -454,21 +454,21 @@ packages: name: permission_handler url: "https://pub.dartlang.org" source: hosted - version: "8.0.0+2" + version: "8.0.1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.5.1" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "4.2.0" platform: dependency: transitive description: @@ -510,7 +510,7 @@ packages: name: qr_code_scanner url: "https://pub.dartlang.org" source: hosted - version: "0.4.0" + version: "0.5.1" qr_flutter: dependency: "direct main" description: @@ -648,7 +648,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.4" + version: "6.0.6" url_launcher_linux: dependency: transitive description: @@ -676,7 +676,7 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" url_launcher_windows: dependency: transitive description: @@ -725,7 +725,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.4" xdg_directories: dependency: transitive description: @@ -739,7 +739,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.1.1" + version: "5.1.2" yaml: dependency: transitive description: diff --git a/src/apps/group_chat/rpc.rs b/src/apps/group_chat/rpc.rs index 858bf7f..45d1523 100644 --- a/src/apps/group_chat/rpc.rs +++ b/src/apps/group_chat/rpc.rs @@ -12,7 +12,7 @@ use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent}; use crate::apps::chat::{Friend, MessageType}; use crate::rpc::{session_close, session_delete, RpcState}; use crate::session::{Session, SessionType}; -use crate::storage::{chat_db, group_chat_db, session_db}; +use crate::storage::{chat_db, group_chat_db, session_db, write_avatar}; use super::add_layer; use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request}; @@ -175,23 +175,26 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler) { let name = params[3].as_str()?.to_owned(); let bio = params[4].as_str()?.to_owned(); let need_agree = params[5].as_bool()?; - let avatar = vec![]; + let avatar = params[6].as_str()?; + let avatar_bytes = base64::decode(avatar).unwrap_or(vec![]); - let db = group_chat_db(state.layer.read().await.base(), &gid)?; + let base = state.layer.read().await.base().clone(); + let db = group_chat_db(&base, &gid)?; let mut gc = GroupChat::new(gid, gtype, addr, name, bio, need_agree); - let _gcd = gc.g_id; + let gcd = gc.g_id; // save db let me = state.group.read().await.clone_user(&gid)?; gc.insert(&db)?; Member::new(gc.id, gid, me.addr, me.name, true, gc.datetime).insert(&db)?; - // TODO save avatar + // save avatar + let _ = write_avatar(&base, &gid, &gcd, &avatar_bytes).await; let mut results = HandleResult::new(); - // TODO add to rpcs. + // add to rpcs. results.rpcs.push(json!(gc.to_rpc())); - let info = gc.to_group_info(my_name, avatar); + let info = gc.to_group_info(my_name, avatar_bytes); // TODO create proof. let proof: Proof = Default::default(); diff --git a/src/storage.rs b/src/storage.rs index 43d5d67..667901a 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -207,6 +207,22 @@ pub(crate) fn read_avatar_sync(base: &PathBuf, gid: &GroupId, remote: &GroupId) } } +pub(crate) async fn write_avatar( + base: &PathBuf, + gid: &GroupId, + remote: &GroupId, + bytes: &[u8], +) -> Result<()> { + if bytes.len() < 1 { + return Ok(()); + } + let mut path = base.clone(); + path.push(gid.to_hex()); + path.push(AVATAR_DIR); + path.push(avatar_png(remote)); + fs::write(path, bytes).await +} + pub(crate) fn write_avatar_sync( base: &PathBuf, gid: &GroupId, diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 7f8902c..048a0a8 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" #include diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h index 9846246..dc139d8 100644 --- a/windows/flutter/generated_plugin_registrant.h +++ b/windows/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_