mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-09-11 19:17:43 +03:00
feat: request permission again if the user denied the photo permission (#5251)
* fix: clear the email field after sending email * fix: ask permission before picking image * feat: improve photo permission UI design * chore: update translations * fix: android photo permission * chore: update translations * fix: awareness meta data decode error
This commit is contained in:
parent
d52042fa4f
commit
266a2a53ab
@ -47,6 +47,12 @@
|
|||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<!-- Permission to read files from external storage (outside application container).
|
||||||
|
As of Android 12 this permission no longer has any effect. Instead use the
|
||||||
|
READ_MEDIA_IMAGES, READ_MEDIA_VIDEO or READM_MEDIA_AUDIO permissions. -->
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||||
|
<!-- Permissions to read media files. -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
||||||
|
@ -37,6 +37,16 @@ end
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
|
||||||
|
'$(inherited)',
|
||||||
|
|
||||||
|
# dart: PermissionGroup.photos
|
||||||
|
'PERMISSION_PHOTOS=1',
|
||||||
|
]
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
installer.aggregate_targets.each do |target|
|
installer.aggregate_targets.each do |target|
|
||||||
|
@ -63,6 +63,8 @@ PODS:
|
|||||||
- path_provider_foundation (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- permission_handler_apple (9.3.0):
|
||||||
|
- Flutter
|
||||||
- ReachabilitySwift (5.0.0)
|
- ReachabilitySwift (5.0.0)
|
||||||
- SDWebImage (5.14.2):
|
- SDWebImage (5.14.2):
|
||||||
- SDWebImage/Core (= 5.14.2)
|
- SDWebImage/Core (= 5.14.2)
|
||||||
@ -98,6 +100,7 @@ DEPENDENCIES:
|
|||||||
- keyboard_height_plugin (from `.symlinks/plugins/keyboard_height_plugin/ios`)
|
- keyboard_height_plugin (from `.symlinks/plugins/keyboard_height_plugin/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
||||||
@ -144,6 +147,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
|
permission_handler_apple:
|
||||||
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
share_plus:
|
share_plus:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
@ -173,6 +178,7 @@ SPEC CHECKSUMS:
|
|||||||
keyboard_height_plugin: 43fa8bba20fd5c4fdeed5076466b8b9d43cc6b86
|
keyboard_height_plugin: 43fa8bba20fd5c4fdeed5076466b8b9d43cc6b86
|
||||||
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
|
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
|
||||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||||
|
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||||
SDWebImage: b9a731e1d6307f44ca703b3976d18c24ca561e84
|
SDWebImage: b9a731e1d6307f44ca703b3976d18c24ca561e84
|
||||||
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
|
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
|
||||||
@ -183,6 +189,6 @@ SPEC CHECKSUMS:
|
|||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||||
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||||
|
|
||||||
PODFILE CHECKSUM: d94f9be27d1db182e9bc77d10f065555d518f127
|
PODFILE CHECKSUM: d0d9b4ff572d8695c38eb3f9b490f55cdfc57eca
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.11.3
|
||||||
|
@ -127,6 +127,7 @@
|
|||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
08FAA63113168DEC7FB74204 /* [CP] Embed Pods Frameworks */,
|
08FAA63113168DEC7FB74204 /* [CP] Embed Pods Frameworks */,
|
||||||
|
A548E58D5F4006A34D7DAA88 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -233,6 +234,23 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
A548E58D5F4006A34D7DAA88 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
E790B8FE5609053209ED85CB /* [CP] Check Pods Manifest.lock */ = {
|
E790B8FE5609053209ED85CB /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -1,53 +1,86 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
///show the dialog to confirm one single action
|
enum ConfirmDialogActionAlignment {
|
||||||
///[onActionButtonPressed] and [onCancelButtonPressed] end with close the dialog
|
// The action buttons are aligned vertically
|
||||||
|
// ---------------------
|
||||||
|
// | Action Button |
|
||||||
|
// | Cancel Button |
|
||||||
|
vertical,
|
||||||
|
// The action buttons are aligned horizontally
|
||||||
|
// ---------------------
|
||||||
|
// | Action Button | Cancel Button |
|
||||||
|
horizontal,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// show the dialog to confirm one single action
|
||||||
|
/// [onActionButtonPressed] and [onCancelButtonPressed] end with close the dialog
|
||||||
Future<T?> showFlowyMobileConfirmDialog<T>(
|
Future<T?> showFlowyMobileConfirmDialog<T>(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
Widget? title,
|
Widget? title,
|
||||||
Widget? content,
|
Widget? content,
|
||||||
|
ConfirmDialogActionAlignment actionAlignment =
|
||||||
|
ConfirmDialogActionAlignment.horizontal,
|
||||||
required String actionButtonTitle,
|
required String actionButtonTitle,
|
||||||
|
required VoidCallback? onActionButtonPressed,
|
||||||
Color? actionButtonColor,
|
Color? actionButtonColor,
|
||||||
String? cancelButtonTitle,
|
String? cancelButtonTitle,
|
||||||
required void Function()? onActionButtonPressed,
|
Color? cancelButtonColor,
|
||||||
void Function()? onCancelButtonPressed,
|
VoidCallback? onCancelButtonPressed,
|
||||||
}) async {
|
}) async {
|
||||||
return showDialog(
|
return showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (dialogContext) {
|
builder: (dialogContext) {
|
||||||
final foregroundColor = Theme.of(context).colorScheme.onSurface;
|
final foregroundColor = Theme.of(context).colorScheme.onSurface;
|
||||||
|
final actionButton = TextButton(
|
||||||
|
child: FlowyText(
|
||||||
|
actionButtonTitle,
|
||||||
|
color: actionButtonColor ?? foregroundColor,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
onActionButtonPressed?.call();
|
||||||
|
// we cannot use dialogContext.pop() here because this is no GoRouter in dialogContext. Use Navigator instead to close the dialog.
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final cancelButton = TextButton(
|
||||||
|
child: FlowyText(
|
||||||
|
cancelButtonTitle ?? LocaleKeys.button_cancel.tr(),
|
||||||
|
color: cancelButtonColor ?? foregroundColor,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
onCancelButtonPressed?.call();
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final actions = switch (actionAlignment) {
|
||||||
|
ConfirmDialogActionAlignment.horizontal => [
|
||||||
|
actionButton,
|
||||||
|
cancelButton,
|
||||||
|
],
|
||||||
|
ConfirmDialogActionAlignment.vertical => [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
actionButton,
|
||||||
|
const Divider(height: 1, color: Colors.grey),
|
||||||
|
cancelButton,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
return AlertDialog.adaptive(
|
return AlertDialog.adaptive(
|
||||||
title: title,
|
title: title,
|
||||||
content: content,
|
content: content,
|
||||||
actions: [
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
TextButton(
|
horizontal: 24.0,
|
||||||
child: Text(
|
vertical: 4.0,
|
||||||
actionButtonTitle,
|
),
|
||||||
style: TextStyle(
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
color: actionButtonColor ?? foregroundColor,
|
actions: actions,
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
onActionButtonPressed?.call();
|
|
||||||
// we cannot use dialogContext.pop() here because this is no GoRouter in dialogContext. Use Navigator instead to close the dialog.
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
cancelButtonTitle ?? LocaleKeys.button_cancel.tr(),
|
|
||||||
style: TextStyle(
|
|
||||||
color: foregroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
onCancelButtonPressed?.call();
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -182,14 +182,21 @@ class DocumentCollabAdapter {
|
|||||||
);
|
);
|
||||||
for (final state in values) {
|
for (final state in values) {
|
||||||
// the following code is only for version 1
|
// the following code is only for version 1
|
||||||
if (state.version != 1) {
|
if (state.version != 1 || state.metadata.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final uid = state.user.uid.toString();
|
final uid = state.user.uid.toString();
|
||||||
final did = state.user.deviceId;
|
final did = state.user.deviceId;
|
||||||
final metadata = DocumentAwarenessMetadata.fromJson(
|
debugPrint('metadata: ${state.metadata}');
|
||||||
jsonDecode(state.metadata),
|
DocumentAwarenessMetadata metadata;
|
||||||
);
|
try {
|
||||||
|
metadata = DocumentAwarenessMetadata.fromJson(
|
||||||
|
jsonDecode(state.metadata),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
Log.error('Failed to parse metadata: $e, ${state.metadata}');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final selectionColor = metadata.selectionColor.tryToColor();
|
final selectionColor = metadata.selectionColor.tryToColor();
|
||||||
final cursorColor = metadata.cursorColor.tryToColor();
|
final cursorColor = metadata.cursorColor.tryToColor();
|
||||||
if ((uid == userId && did == deviceId) ||
|
if ((uid == userId && did == deviceId) ||
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
|
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_confirm_dialog.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_cover_bottom_sheet.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_cover_bottom_sheet.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
||||||
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
||||||
|
import 'package:appflowy/startup/tasks/device_info_task.dart';
|
||||||
import 'package:appflowy/user/application/user_service.dart';
|
import 'package:appflowy/user/application/user_service.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
|
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class PageStyleCoverImage extends StatelessWidget {
|
class PageStyleCoverImage extends StatelessWidget {
|
||||||
PageStyleCoverImage({
|
PageStyleCoverImage({
|
||||||
@ -114,9 +121,22 @@ class PageStyleCoverImage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _pickImage(BuildContext context) async {
|
Future<void> _pickImage(BuildContext context) async {
|
||||||
final result = await _imagePicker.pickImage(
|
final photoPermission = await _checkPhotoPermission(context);
|
||||||
source: ImageSource.gallery,
|
if (!photoPermission) {
|
||||||
);
|
Log.error('Has no permission to access the photo library');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFile? result;
|
||||||
|
try {
|
||||||
|
result = await _imagePicker.pickImage(
|
||||||
|
source: ImageSource.gallery,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
Log.error('Error while picking image: $e');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final path = result?.path;
|
final path = result?.path;
|
||||||
if (path != null && context.mounted) {
|
if (path != null && context.mounted) {
|
||||||
final String? result;
|
final String? result;
|
||||||
@ -204,6 +224,54 @@ class PageStyleCoverImage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> _checkPhotoPermission(BuildContext context) async {
|
||||||
|
// check the permission first
|
||||||
|
final status = await Permission.photos.status;
|
||||||
|
// if the permission is permanently denied, we should open the app settings
|
||||||
|
if (status.isPermanentlyDenied && context.mounted) {
|
||||||
|
unawaited(
|
||||||
|
showFlowyMobileConfirmDialog(
|
||||||
|
context,
|
||||||
|
title: FlowyText.semibold(
|
||||||
|
LocaleKeys.pageStyle_photoPermissionTitle.tr(),
|
||||||
|
maxLines: 3,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
content: FlowyText(
|
||||||
|
LocaleKeys.pageStyle_photoPermissionDescription.tr(),
|
||||||
|
maxLines: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
fontSize: 12.0,
|
||||||
|
),
|
||||||
|
actionAlignment: ConfirmDialogActionAlignment.vertical,
|
||||||
|
actionButtonTitle: LocaleKeys.pageStyle_openSettings.tr(),
|
||||||
|
actionButtonColor: Colors.blue,
|
||||||
|
cancelButtonTitle: LocaleKeys.pageStyle_doNotAllow.tr(),
|
||||||
|
cancelButtonColor: Colors.blue,
|
||||||
|
onActionButtonPressed: () {
|
||||||
|
openAppSettings();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (status.isDenied) {
|
||||||
|
// https://github.com/Baseflow/flutter-permission-handler/issues/1262#issuecomment-2006340937
|
||||||
|
Permission permission = Permission.photos;
|
||||||
|
if (defaultTargetPlatform == TargetPlatform.android &&
|
||||||
|
ApplicationInfo.androidSDKVersion <= 32) {
|
||||||
|
permission = Permission.storage;
|
||||||
|
}
|
||||||
|
// if the permission is denied, we should request the permission
|
||||||
|
final newStatus = await permission.request();
|
||||||
|
if (newStatus.isDenied) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UnsplashCover extends StatelessWidget {
|
class _UnsplashCover extends StatelessWidget {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||||
@ -18,6 +16,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:string_validator/string_validator.dart';
|
import 'package:string_validator/string_validator.dart';
|
||||||
|
|
||||||
@ -215,6 +214,8 @@ class _InviteMemberState extends State<_InviteMember> {
|
|||||||
context
|
context
|
||||||
.read<WorkspaceMemberBloc>()
|
.read<WorkspaceMemberBloc>()
|
||||||
.add(WorkspaceMemberEvent.inviteWorkspaceMember(email));
|
.add(WorkspaceMemberEvent.inviteWorkspaceMember(email));
|
||||||
|
// clear the email field after inviting
|
||||||
|
_emailController.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1329,6 +1329,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.3"
|
version: "4.2.3"
|
||||||
|
permission_handler:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: permission_handler
|
||||||
|
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "11.3.1"
|
||||||
|
permission_handler_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_android
|
||||||
|
sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "12.0.6"
|
||||||
|
permission_handler_apple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_apple
|
||||||
|
sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "9.4.4"
|
||||||
|
permission_handler_html:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_html
|
||||||
|
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.1"
|
||||||
|
permission_handler_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_platform_interface
|
||||||
|
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
|
permission_handler_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: permission_handler_windows
|
||||||
|
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -134,6 +134,7 @@ dependencies:
|
|||||||
avatar_stack: ^1.2.0
|
avatar_stack: ^1.2.0
|
||||||
numerus: ^2.1.2
|
numerus: ^2.1.2
|
||||||
flutter_animate: ^4.5.0
|
flutter_animate: ^4.5.0
|
||||||
|
permission_handler: ^11.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^3.0.1
|
||||||
|
@ -1534,7 +1534,11 @@
|
|||||||
"photo": "Photo",
|
"photo": "Photo",
|
||||||
"unsplash": "Unsplash",
|
"unsplash": "Unsplash",
|
||||||
"pageCover": "Page cover",
|
"pageCover": "Page cover",
|
||||||
"none": "None"
|
"none": "None",
|
||||||
|
"photoPermissionDescription": "Allow access to the photo library for uploading images.",
|
||||||
|
"openSettings": "Open Settings",
|
||||||
|
"photoPermissionTitle": "AppFlowy Would Like to Access Your Photo Library",
|
||||||
|
"doNotAllow": "Don't Allow"
|
||||||
},
|
},
|
||||||
"commandPalette": {
|
"commandPalette": {
|
||||||
"placeholder": "Type to search for views...",
|
"placeholder": "Type to search for views...",
|
||||||
|
Loading…
Reference in New Issue
Block a user