upload avatar on desktop
This commit is contained in:
parent
be634e763a
commit
7e742a185a
|
@ -50,7 +50,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
||||||
gameCard = GameCard(element);
|
gameCard = GameCard(element);
|
||||||
} else {
|
} else {
|
||||||
wraps.add(Wrap(
|
wraps.add(Wrap(
|
||||||
children: [GameCard(element), gameCard!],
|
children: [GameCard(element), gameCard],
|
||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
));
|
));
|
||||||
gameCard = null;
|
gameCard = null;
|
||||||
|
@ -58,7 +58,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
||||||
}
|
}
|
||||||
if (gameCard != null) {
|
if (gameCard != null) {
|
||||||
wraps.add(Wrap(
|
wraps.add(Wrap(
|
||||||
children: [gameCard!],
|
children: [gameCard],
|
||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
|
import 'package:image/image.dart' as image;
|
||||||
|
import 'package:crop_image/crop_image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DesktopCropper extends StatefulWidget {
|
||||||
|
final String? title;
|
||||||
|
final double? aspectRatio;
|
||||||
|
final String file;
|
||||||
|
|
||||||
|
const DesktopCropper({
|
||||||
|
Key? key,
|
||||||
|
this.title,
|
||||||
|
this.aspectRatio,
|
||||||
|
required this.file,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _DesktopCropperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopCropperState extends State<DesktopCropper> {
|
||||||
|
late final _controller = CropController(
|
||||||
|
aspectRatio: widget.aspectRatio,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(widget.title ?? "图片裁剪"),
|
||||||
|
actions: [
|
||||||
|
IconButton(onPressed: _finish, icon: const Icon(Icons.done)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: CropImage(
|
||||||
|
controller: _controller,
|
||||||
|
image: Image.file(File(widget.file)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future _finish() async {
|
||||||
|
var cropped = await _controller.croppedBitmap();
|
||||||
|
var data = await cropped.toByteData(format: ui.ImageByteFormat.png);
|
||||||
|
if (data != null) {
|
||||||
|
var u8list = data.buffer.asUint8List();
|
||||||
|
image.Image? baseSizeImage = image.decodePng(u8list);
|
||||||
|
if (baseSizeImage != null) {
|
||||||
|
if (cropped.width > 200) {
|
||||||
|
baseSizeImage =
|
||||||
|
image.copyResize(baseSizeImage, height: 200, width: 200);
|
||||||
|
}
|
||||||
|
var f = image.encodeJpg(baseSizeImage!);
|
||||||
|
Navigator.of(context).pop(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_cropper/image_cropper.dart';
|
import 'package:image_cropper/image_cropper.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
@ -12,6 +13,8 @@ import 'package:pikapika/screens/components/Avatar.dart';
|
||||||
import 'package:pikapika/screens/components/Images.dart';
|
import 'package:pikapika/screens/components/Images.dart';
|
||||||
import 'package:pikapika/screens/components/ItemBuilder.dart';
|
import 'package:pikapika/screens/components/ItemBuilder.dart';
|
||||||
|
|
||||||
|
import 'DesktopCropper.dart';
|
||||||
|
|
||||||
const double _cardHeight = 180;
|
const double _cardHeight = 180;
|
||||||
|
|
||||||
// 用户信息卡
|
// 用户信息卡
|
||||||
|
@ -120,6 +123,10 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (Platform.isAndroid || Platform.isIOS) {
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
await _updateAvatarPhone();
|
await _updateAvatarPhone();
|
||||||
|
} else if (Platform.isMacOS ||
|
||||||
|
Platform.isWindows ||
|
||||||
|
Platform.isLinux) {
|
||||||
|
await _updateAvatarDesktop();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Avatar(profile.avatar, size: 65),
|
child: Avatar(profile.avatar, size: 65),
|
||||||
|
@ -202,6 +209,29 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future _updateAvatarDesktop() async {
|
||||||
|
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||||
|
type: FileType.image,
|
||||||
|
allowMultiple: false,
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
List<int>? buff = await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(builder: (BuildContext context) {
|
||||||
|
return DesktopCropper(
|
||||||
|
file: result.files.first.path!,
|
||||||
|
aspectRatio: 1,
|
||||||
|
title: "裁剪头像",
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (buff != null) {
|
||||||
|
var data = base64Encode(buff);
|
||||||
|
await method.updateAvatar(data);
|
||||||
|
_reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _reload() {
|
void _reload() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_future = _load();
|
_future = _load();
|
||||||
|
|
49
pubspec.lock
49
pubspec.lock
|
@ -8,6 +8,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1+2"
|
version: "1.0.1+2"
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.2"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -57,6 +64,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.15.0"
|
||||||
|
crop_image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: crop_image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.2"
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -64,6 +78,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.2"
|
version: "0.3.2"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -85,6 +106,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.0"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
file_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: file_picker
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
filesystem_picker:
|
filesystem_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -168,6 +203,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
image_cropper:
|
image_cropper:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -446,6 +488,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -45,6 +45,9 @@ dependencies:
|
||||||
modal_bottom_sheet: ^2.0.0
|
modal_bottom_sheet: ^2.0.0
|
||||||
image_cropper: ^1.5.0
|
image_cropper: ^1.5.0
|
||||||
image_picker: ^0.8.4+9
|
image_picker: ^0.8.4+9
|
||||||
|
file_picker: ^4.5.1
|
||||||
|
crop_image: ^1.0.2
|
||||||
|
image: ^3.1.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in New Issue