✨ Crop image for profile picture, background
This commit is contained in:
parent
f266968644
commit
937e249b87
@ -1,4 +1,6 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- croppy (0.0.1):
|
||||||
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- DKImagePickerController/Core (4.3.9):
|
- DKImagePickerController/Core (4.3.9):
|
||||||
@ -171,6 +173,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
@ -215,6 +218,8 @@ SPEC REPOS:
|
|||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
croppy:
|
||||||
|
:path: ".symlinks/plugins/croppy/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
file_picker:
|
file_picker:
|
||||||
@ -259,6 +264,7 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
||||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:croppy/croppy.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -100,6 +101,7 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
...context.localizationDelegates,
|
...context.localizationDelegates,
|
||||||
|
CroppyLocalizations.delegate,
|
||||||
], // this contains the cupertino one
|
], // this contains the cupertino one
|
||||||
locale: context.locale,
|
locale: context.locale,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
|
@ -29,6 +29,7 @@ class AppRouter extends RootStackRouter {
|
|||||||
page: EditPublisherRoute.page,
|
page: EditPublisherRoute.page,
|
||||||
path: '/account/me/publishers/:id/edit',
|
path: '/account/me/publishers/:id/edit',
|
||||||
),
|
),
|
||||||
|
AutoRoute(page: AccountProfileRoute.page, path: '/account/:name'),
|
||||||
AutoRoute(page: PostComposeRoute.page, path: '/posts/compose'),
|
AutoRoute(page: PostComposeRoute.page, path: '/posts/compose'),
|
||||||
AutoRoute(page: PostDetailRoute.page, path: '/posts/:id'),
|
AutoRoute(page: PostDetailRoute.page, path: '/posts/:id'),
|
||||||
AutoRoute(page: PostEditRoute.page, path: '/posts/:id/edit'),
|
AutoRoute(page: PostEditRoute.page, path: '/posts/:id/edit'),
|
||||||
|
@ -31,7 +31,8 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Card(
|
GestureDetector(
|
||||||
|
child: Card(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -79,6 +80,12 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
).padding(horizontal: 8),
|
).padding(horizontal: 8),
|
||||||
|
onTap: () {
|
||||||
|
context.router.push(
|
||||||
|
AccountProfileRoute(name: user.value!.name),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
ListTile(
|
ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:croppy/croppy.dart' hide cropImage;
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -176,10 +177,23 @@ class EditPublisherScreen extends HookConsumerWidget {
|
|||||||
final background = useState<SnCloudFile?>(null);
|
final background = useState<SnCloudFile?>(null);
|
||||||
|
|
||||||
void setPicture(String position) async {
|
void setPicture(String position) async {
|
||||||
final result = await ref
|
var result = await ref
|
||||||
.read(imagePickerProvider)
|
.read(imagePickerProvider)
|
||||||
.pickImage(source: ImageSource.gallery);
|
.pickImage(source: ImageSource.gallery);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
result = await cropImage(
|
||||||
|
context,
|
||||||
|
image: result,
|
||||||
|
allowedAspectRatios: [
|
||||||
|
if (position == 'background')
|
||||||
|
CropAspectRatio(height: 7, width: 16)
|
||||||
|
else
|
||||||
|
CropAspectRatio(height: 1, width: 1),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:croppy/croppy.dart' hide cropImage;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@ -25,10 +26,23 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
final submitting = useState(false);
|
final submitting = useState(false);
|
||||||
|
|
||||||
void updateProfilePicture(String position) async {
|
void updateProfilePicture(String position) async {
|
||||||
final result = await ref
|
var result = await ref
|
||||||
.read(imagePickerProvider)
|
.read(imagePickerProvider)
|
||||||
.pickImage(source: ImageSource.gallery);
|
.pickImage(source: ImageSource.gallery);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
result = await cropImage(
|
||||||
|
context,
|
||||||
|
image: result,
|
||||||
|
allowedAspectRatios: [
|
||||||
|
if (position == 'background')
|
||||||
|
CropAspectRatio(height: 7, width: 16)
|
||||||
|
else
|
||||||
|
CropAspectRatio(height: 1, width: 1),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:croppy/croppy.dart' hide cropImage;
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -244,10 +245,23 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
}, [chat]);
|
}, [chat]);
|
||||||
|
|
||||||
void setPicture(String position) async {
|
void setPicture(String position) async {
|
||||||
final result = await ref
|
var result = await ref
|
||||||
.read(imagePickerProvider)
|
.read(imagePickerProvider)
|
||||||
.pickImage(source: ImageSource.gallery);
|
.pickImage(source: ImageSource.gallery);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
result = await cropImage(
|
||||||
|
context,
|
||||||
|
image: result,
|
||||||
|
allowedAspectRatios: [
|
||||||
|
if (position == 'background')
|
||||||
|
CropAspectRatio(height: 7, width: 16)
|
||||||
|
else
|
||||||
|
CropAspectRatio(height: 1, width: 1),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:croppy/croppy.dart' show CropAspectRatio;
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -158,10 +159,23 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
}, [realm]);
|
}, [realm]);
|
||||||
|
|
||||||
void setPicture(String position) async {
|
void setPicture(String position) async {
|
||||||
final result = await ref
|
var result = await ref
|
||||||
.read(imagePickerProvider)
|
.read(imagePickerProvider)
|
||||||
.pickImage(source: ImageSource.gallery);
|
.pickImage(source: ImageSource.gallery);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
result = await cropImage(
|
||||||
|
context,
|
||||||
|
image: result,
|
||||||
|
allowedAspectRatios: [
|
||||||
|
if (position == 'background')
|
||||||
|
CropAspectRatio(height: 7, width: 16)
|
||||||
|
else
|
||||||
|
CropAspectRatio(height: 1, width: 1),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
if (result == null) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
|
@ -1,11 +1,43 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:io';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:croppy/croppy.dart';
|
||||||
import 'package:cross_file/cross_file.dart';
|
import 'package:cross_file/cross_file.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:tus_client_dart/tus_client_dart.dart';
|
import 'package:tus_client_dart/tus_client_dart.dart';
|
||||||
|
|
||||||
|
Future<XFile?> cropImage(
|
||||||
|
BuildContext context, {
|
||||||
|
required XFile image,
|
||||||
|
List<CropAspectRatio?>? allowedAspectRatios,
|
||||||
|
}) async {
|
||||||
|
final result = await showMaterialImageCropper(
|
||||||
|
context,
|
||||||
|
imageProvider:
|
||||||
|
kIsWeb ? NetworkImage(image.path) : FileImage(File(image.path)),
|
||||||
|
showLoadingIndicatorOnSubmit: true,
|
||||||
|
allowedAspectRatios: allowedAspectRatios,
|
||||||
|
);
|
||||||
|
if (result == null) return null; // Cancelled operation
|
||||||
|
final croppedFile = result.uiImage;
|
||||||
|
final croppedBytes = await croppedFile.toByteData(
|
||||||
|
format: ImageByteFormat.png,
|
||||||
|
);
|
||||||
|
if (croppedBytes == null) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
croppedFile.dispose();
|
||||||
|
return XFile.fromData(
|
||||||
|
croppedBytes.buffer.asUint8List(),
|
||||||
|
path: image.path,
|
||||||
|
mimeType: image.mimeType,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Completer<SnCloudFile?> putMediaToCloud({
|
Completer<SnCloudFile?> putMediaToCloud({
|
||||||
required dynamic fileData, // Can be XFile or List<int> (Uint8List)
|
required dynamic fileData, // Can be XFile or List<int> (Uint8List)
|
||||||
required String atk,
|
required String atk,
|
||||||
|
@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
croppy
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
24
pubspec.lock
24
pubspec.lock
@ -217,6 +217,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
cassowary:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cassowary
|
||||||
|
sha256: f304452beaf93b9349daaeeda23f853578c9dd8674c06c6100fda0319c46b967
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.3"
|
||||||
chalkdart:
|
chalkdart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -297,6 +305,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
|
croppy:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: croppy
|
||||||
|
sha256: "2a69059d9ec007b79d6a494854094b2e3c0a4f7ed609cf55a4805c9de9ec171d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.6"
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -449,6 +465,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
|
equatable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.7"
|
||||||
expandable:
|
expandable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -90,6 +90,7 @@ dependencies:
|
|||||||
collection: ^1.19.1
|
collection: ^1.19.1
|
||||||
flutter_expandable_fab: ^2.5.0
|
flutter_expandable_fab: ^2.5.0
|
||||||
markdown_editor_plus: ^0.2.15
|
markdown_editor_plus: ^0.2.15
|
||||||
|
croppy: ^1.3.6
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -19,6 +19,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
croppy
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user