ask permissions

This commit is contained in:
Salvatore Giordano
2020-11-13 16:26:24 +01:00
parent e3a260902b
commit 8dd718b148
7 changed files with 303 additions and 223 deletions
+11 -5
View File
@@ -108,6 +108,8 @@ PODS:
- GoogleUtilities/Logger
- image_picker (0.0.1):
- Flutter
- media_gallery (0.0.1):
- Flutter
- nanopb (1.30906.0):
- nanopb/decode (= 1.30906.0)
- nanopb/encode (= 1.30906.0)
@@ -115,7 +117,7 @@ PODS:
- nanopb/encode (1.30906.0)
- path_provider (0.0.1):
- Flutter
- photo_gallery (0.0.1):
- "permission_handler (5.0.1+1)":
- Flutter
- PromisesObjC (1.2.11)
- Protobuf (3.13.0)
@@ -167,8 +169,9 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- image_picker (from `.symlinks/plugins/image_picker/ios`)
- media_gallery (from `.symlinks/plugins/media_gallery/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- photo_gallery (from `.symlinks/plugins/photo_gallery/ios`)
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
@@ -220,10 +223,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
image_picker:
:path: ".symlinks/plugins/image_picker/ios"
media_gallery:
:path: ".symlinks/plugins/media_gallery/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
photo_gallery:
:path: ".symlinks/plugins/photo_gallery/ios"
permission_handler:
:path: ".symlinks/plugins/permission_handler/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
sqflite:
@@ -259,9 +264,10 @@ SPEC CHECKSUMS:
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09
media_gallery: 834a04455a476b975c280aa1f24ed2853dfe36de
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
photo_gallery: 9f95e57747cd22c10676ece3660d1ffe6c603ee5
permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6
PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748
SDWebImage: b69257f4ab14e9b6a2ef53e910fdf914d8f757c1
+2 -2
View File
@@ -327,9 +327,9 @@
"${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework",
"${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework",
"${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework",
"${BUILT_PRODUCTS_DIR}/media_gallery/media_gallery.framework",
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
"${BUILT_PRODUCTS_DIR}/photo_gallery/photo_gallery.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework",
@@ -358,9 +358,9 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_gallery.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_gallery.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework",
+135 -133
View File
@@ -59,165 +59,167 @@ class ChooseUserPage extends StatelessWidget {
(_, value) => value..extraData['image'] = getRandomPicUrl(value));
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
top: 34,
bottom: 20,
),
child: Center(
child: SvgPicture.asset(
'assets/logo.svg',
height: 40,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
top: 34,
bottom: 20,
),
child: Center(
child: SvgPicture.asset(
'assets/logo.svg',
height: 40,
),
),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 13.0),
child: Text(
'Welcome to Stream Chat',
Padding(
padding: const EdgeInsets.only(bottom: 13.0),
child: Text(
'Welcome to Stream Chat',
style: TextStyle(
fontSize: 22,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Text(
'Select a user to try the Flutter SDK:',
style: TextStyle(
fontSize: 22,
fontSize: 14.5,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Text(
'Select a user to try the Flutter SDK:',
style: TextStyle(
fontSize: 14.5,
color: Colors.black,
),
),
Expanded(
child: ListView.separated(
separatorBuilder: (context, i) {
return Container(
width: double.infinity,
color: Colors.black12,
height: 1,
);
},
itemCount: users.length + 1,
itemBuilder: (context, i) {
return [
...users.entries.map((entry) {
final token = entry.key;
final user = entry.value;
return ListTile(
onTap: () async {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
),
height: 100,
width: 100,
child: Center(
child: CircularProgressIndicator(),
Expanded(
child: ListView.separated(
separatorBuilder: (context, i) {
return Container(
width: double.infinity,
color: Colors.black12,
height: 1,
);
},
itemCount: users.length + 1,
itemBuilder: (context, i) {
return [
...users.entries.map((entry) {
final token = entry.key;
final user = entry.value;
return ListTile(
onTap: () async {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
),
height: 100,
width: 100,
child: Center(
child: CircularProgressIndicator(),
),
),
),
);
final secureStorage = FlutterSecureStorage();
final client = StreamChat.of(context).client;
await client.setUser(
user,
token,
);
secureStorage.write(
key: kStreamApiKey,
value: kDefaultStreamApiKey,
);
secureStorage.write(
key: kStreamUserId,
value: user.id,
);
secureStorage.write(
key: kStreamToken,
value: token,
);
if (!kIsWeb) {
initNotifications(client);
}
Navigator.pop(context);
await Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) {
return StreamChat(
client: client,
child: ChannelListPage(),
);
},
),
);
},
leading: UserAvatar(
user: user,
constraints: BoxConstraints.tight(
Size.fromRadius(20),
),
);
final secureStorage = FlutterSecureStorage();
final client = StreamChat.of(context).client;
await client.setUser(
user,
token,
);
secureStorage.write(
key: kStreamApiKey,
value: kDefaultStreamApiKey,
);
secureStorage.write(
key: kStreamUserId,
value: user.id,
);
secureStorage.write(
key: kStreamToken,
value: token,
);
if (!kIsWeb) {
initNotifications(client);
}
Navigator.pop(context);
await Navigator.pushReplacement(
),
title: Text(
user.name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text('Stream test account'),
trailing: SvgPicture.asset(
'assets/icon_arrow_right.svg',
height: 24,
width: 24,
),
);
}),
ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return StreamChat(
client: client,
child: ChannelListPage(),
);
},
builder: (context) => AdvancedOptionsPage(),
),
);
},
leading: UserAvatar(
user: user,
constraints: BoxConstraints.tight(
Size.fromRadius(20),
leading: CircleAvatar(
child: Icon(
StreamIcons.settings,
color: Colors.black,
),
backgroundColor:
StreamChatTheme.of(context).secondaryColor,
),
title: Text(
user.name,
'Advanced Options',
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text('Stream test account'),
subtitle: Text('Custom settings'),
trailing: SvgPicture.asset(
'assets/icon_arrow_right.svg',
height: 24,
width: 24,
clipBehavior: Clip.none,
),
);
}),
ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AdvancedOptionsPage(),
),
);
},
leading: CircleAvatar(
child: Icon(
StreamIcons.settings,
color: Colors.black,
),
backgroundColor:
StreamChatTheme.of(context).secondaryColor,
),
title: Text(
'Advanced Options',
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text('Custom settings'),
trailing: SvgPicture.asset(
'assets/icon_arrow_right.svg',
height: 24,
width: 24,
clipBehavior: Clip.none,
),
),
][i];
},
][i];
},
),
),
),
StreamVersion(),
],
StreamVersion(),
],
),
),
);
}
+66 -64
View File
@@ -64,83 +64,85 @@ class ChannelListPage extends StatelessWidget {
final user = StreamChat.of(context).user;
return Scaffold(
drawer: Drawer(
child: Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).viewPadding.top + 8,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 20.0,
left: 8,
),
child: Row(
children: [
UserAvatar(
user: user,
showOnlineStatus: false,
constraints: BoxConstraints.tight(Size.fromRadius(20)),
),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
user.name,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
child: SafeArea(
child: Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).viewPadding.top + 8,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
bottom: 20.0,
left: 8,
),
child: Row(
children: [
UserAvatar(
user: user,
showOnlineStatus: false,
constraints: BoxConstraints.tight(Size.fromRadius(20)),
),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
user.name,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
ListTile(
leading: Icon(StreamIcons.edit),
title: Text(
'New direct message',
style: TextStyle(
fontSize: 14.5,
),
],
),
),
ListTile(
leading: Icon(StreamIcons.edit),
title: Text(
'New direct message',
style: TextStyle(
fontSize: 14.5,
),
),
),
ListTile(
leading: Icon(StreamIcons.group),
title: Text(
'New group',
style: TextStyle(
fontSize: 14.5,
ListTile(
leading: Icon(StreamIcons.group),
title: Text(
'New group',
style: TextStyle(
fontSize: 14.5,
),
),
),
),
Expanded(
child: Container(
alignment: Alignment.bottomCenter,
child: ListTile(
onTap: () async {
await StreamChat.of(context).client.disconnect();
Expanded(
child: Container(
alignment: Alignment.bottomCenter,
child: ListTile(
onTap: () async {
await StreamChat.of(context).client.disconnect();
final secureStorage = FlutterSecureStorage();
await secureStorage.deleteAll();
Navigator.pop(context);
await Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => ChooseUserPage(),
final secureStorage = FlutterSecureStorage();
await secureStorage.deleteAll();
Navigator.pop(context);
await Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => ChooseUserPage(),
),
);
},
leading: Icon(StreamIcons.user),
title: Text(
'Sign out',
style: TextStyle(
fontSize: 14.5,
),
);
},
leading: Icon(StreamIcons.user),
title: Text(
'Sign out',
style: TextStyle(
fontSize: 14.5,
),
),
),
),
),
],
],
),
),
),
),
+1 -1
View File
@@ -1,6 +1,6 @@
name: example
description: A new Flutter project.
version: 1.0.58+60
version: 1.0.59+61
environment:
sdk: ">=2.2.2 <3.0.0"
+84 -18
View File
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:emojis/emoji.dart';
@@ -659,7 +660,7 @@ class MessageInputState extends State<MessageInput> {
setState(() {
_animateContainer = false;
_filePickerSize = (_filePickerSize - update.delta.dy).clamp(
100,
240.0,
MediaQuery.of(context).size.height / 1.7,
);
});
@@ -709,17 +710,80 @@ class MessageInputState extends State<MessageInput> {
Widget _buildPickerSection() {
switch (_filePickerIndex) {
case 0:
return MediaListView(
selectedIds: _attachments.map((e) => e.id).toList(),
onSelect: (media) {
if (!_attachments.any((element) => element.id == media.id)) {
_addAttachment(media);
} else {
_attachments.removeWhere((element) => element.id == media.id);
setState(() {});
}
},
);
return FutureBuilder<PermissionStatus>(
future: Platform.isAndroid
? Permission.storage.status
: Permission.photos.status,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.data.isGranted) {
return MediaListView(
selectedIds: _attachments.map((e) => e.id).toList(),
onSelect: (media) {
if (!_attachments
.any((element) => element.id == media.id)) {
_addAttachment(media);
} else {
_attachments
.removeWhere((element) => element.id == media.id);
setState(() {});
}
},
);
}
return InkWell(
onTap: () async {
var status = await (Platform.isAndroid
? Permission.storage.status
: Permission.photos.status);
print('status: ${status}');
if (status.isPermanentlyDenied || status.isDenied) {
if (await openAppSettings()) {
setState(() {});
}
} else {
status = await (Platform.isAndroid
? Permission.storage
: Permission.photos)
.request();
if (status.isGranted) {
setState(() {});
}
}
},
child: Container(
color: Color(0xFFF2F2F2),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SvgPicture.asset(
'svgs/icon_picture_empty_state.svg',
package: 'stream_chat_flutter',
height: 140,
color: StreamChatTheme.of(context).accentColor,
),
Center(
child: Text(
'Allow access to your gallery',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: StreamChatTheme.of(context).accentColor,
),
),
),
],
),
),
);
});
break;
case 1:
break;
@@ -1235,12 +1299,14 @@ class MessageInputState extends State<MessageInput> {
_filePickerSize = 250.0;
});
} else {
final status = await Permission.storage.request();
if (status.isDenied || status.isPermanentlyDenied) {
final res = await openAppSettings();
if (!res) {
return;
}
final status = await (Platform.isAndroid
? Permission.storage.status
: Permission.photos.status);
if (status.isUndetermined) {
await (Platform.isAndroid
? Permission.storage
: Permission.photos)
.request();
}
showAttachmentModal();
}
+4
View File
@@ -0,0 +1,4 @@
<svg width="136" height="136" viewBox="0 0 136 136" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3333 45.3333C11.3333 35.9445 18.9444 28.3333 28.3333 28.3333H107.667C117.055 28.3333 124.667 35.9445 124.667 45.3333V90.6667C124.667 100.055 117.055 107.667 107.667 107.667H28.3333C18.9444 107.667 11.3333 100.055 11.3333 90.6667V45.3333ZM28.3333 39.6666C25.2036 39.6666 22.6666 42.2037 22.6666 45.3333V90.6666C22.6666 93.7963 25.2036 96.3333 28.3333 96.3333H107.667C110.796 96.3333 113.333 93.7963 113.333 90.6666V45.3333C113.333 42.2037 110.796 39.6666 107.667 39.6666H28.3333Z" fill="#D6D6D6"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.61 51.0003C92.3115 50.9833 93.9306 51.7318 95.0199 53.039L123.353 87.039C125.357 89.4432 125.032 93.0164 122.628 95.0199C120.223 97.0234 116.65 96.6986 114.647 94.2944L90.7563 65.6258L72.4249 88.5399C70.5129 90.9299 67.0486 91.3698 64.6 89.5333L45.8651 75.4821L26.6736 94.6736C24.4606 96.8866 20.8727 96.8866 18.6597 94.6736C16.4468 92.4606 16.4468 88.8727 18.6597 86.6597L41.3264 63.9931C43.3204 61.999 46.4773 61.7747 48.7333 63.4667L67.0061 77.1713L86.2417 53.1267C87.3047 51.798 88.9085 51.0173 90.61 51.0003Z" fill="#D6D6D6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB