Browse Source

unify select image as avatar

pull/18/head
Sun 5 years ago
parent
commit
2e24a04607
  1. 32
      lib/apps/group_chat/add.dart
  2. 143
      lib/pages/account_generate.dart
  3. 146
      lib/pages/setting/profile.dart
  4. 137
      lib/widgets/select_avatar.dart
  5. 2
      linux/flutter/generated_plugin_registrant.cc
  6. 2
      linux/flutter/generated_plugin_registrant.h
  7. 20
      pubspec.lock
  8. 17
      src/apps/group_chat/rpc.rs
  9. 16
      src/storage.rs
  10. 2
      windows/flutter/generated_plugin_registrant.cc
  11. 2
      windows/flutter/generated_plugin_registrant.h

32
lib/apps/group_chat/add.dart

@ -1,4 +1,5 @@ @@ -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'; @@ -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<GroupAddPage> { @@ -47,6 +49,7 @@ class _GroupAddPageState extends State<GroupAddPage> {
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<GroupAddPage> { @@ -151,7 +154,8 @@ class _GroupAddPageState extends State<GroupAddPage> {
}
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<GroupAddPage> { @@ -414,20 +418,32 @@ class _GroupAddPageState extends State<GroupAddPage> {
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: <Widget>[
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;
})),
),
),
],
),

143
lib/pages/account_generate.dart

@ -1,20 +1,17 @@ @@ -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<AccountGeneratePage> { @@ -43,8 +40,6 @@ class _AccountGeneratePageState extends State<AccountGeneratePage> {
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<AccountGeneratePage> { @@ -119,97 +114,6 @@ class _AccountGeneratePageState extends State<AccountGeneratePage> {
);
}
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<double> animation,
Animation<double> 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<Widget> mnemonicWordWidgets = [];
if (this._mnemoicWords.length > 1) {
@ -373,35 +277,25 @@ class _AccountGeneratePageState extends State<AccountGeneratePage> { @@ -373,35 +277,25 @@ class _AccountGeneratePageState extends State<AccountGeneratePage> {
}
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: <Widget>[
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<AccountGeneratePage> { @@ -410,7 +304,9 @@ class _AccountGeneratePageState extends State<AccountGeneratePage> {
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) { @@ -461,20 +357,3 @@ Widget _footer(String text1, Function callback) {
),
);
}
Widget _buildMaterialDialogTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> 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,
));
}

146
lib/pages/setting/profile.dart

@ -1,14 +1,11 @@ @@ -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 { @@ -21,103 +18,11 @@ class ProfileDetail extends StatefulWidget {
}
class _ProfileDetailState extends State<ProfileDetail> {
CropController _imageController = CropController();
TextEditingController _nameController = TextEditingController();
double _imageScale = 1.0;
bool _changeName = false;
bool _mnemoicShow = false;
List<String> _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<double> animation,
Animation<double> 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<AccountProvider>().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<ProfileDetail> { @@ -169,25 +74,19 @@ class _ProfileDetailState extends State<ProfileDetail> {
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<AccountProvider>().accountUpdate(account.name, bytes),
),
),
),
],
),
@ -381,20 +280,3 @@ class _ProfileDetailState extends State<ProfileDetail> { @@ -381,20 +280,3 @@ class _ProfileDetailState extends State<ProfileDetail> {
}));
}
}
Widget _buildMaterialDialogTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> 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,
));
}

137
lib/widgets/select_avatar.dart

@ -0,0 +1,137 @@ @@ -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<double> animation,
Animation<double> 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<double> animation,
Animation<double> secondaryAnimation) {
return _CropAvatar(callback: callback, image: image);
});
}

2
linux/flutter/generated_plugin_registrant.cc

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <esse_core/esse_core_plugin.h>

2
linux/flutter/generated_plugin_registrant.h

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_

20
pubspec.lock

@ -161,7 +161,7 @@ packages: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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:

17
src/apps/group_chat/rpc.rs

@ -12,7 +12,7 @@ use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent}; @@ -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<RpcState>) { @@ -175,23 +175,26 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
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();

16
src/storage.rs

@ -207,6 +207,22 @@ pub(crate) fn read_avatar_sync(base: &PathBuf, gid: &GroupId, remote: &GroupId) @@ -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,

2
windows/flutter/generated_plugin_registrant.cc

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <esse_core/esse_core_plugin.h>

2
windows/flutter/generated_plugin_registrant.h

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_

Loading…
Cancel
Save