feat: Added file picker sections and image support
This commit is contained in:
+144
-4
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
@@ -9,6 +10,7 @@ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
|||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
|
import 'package:photo_gallery/photo_gallery.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
@@ -173,6 +175,8 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
bool _actionsShrunk = false;
|
bool _actionsShrunk = false;
|
||||||
bool _sendAsDm = false;
|
bool _sendAsDm = false;
|
||||||
bool _openFilePickerSection = false;
|
bool _openFilePickerSection = false;
|
||||||
|
int _filePickerIndex = 0;
|
||||||
|
Album _selectedAlbum;
|
||||||
|
|
||||||
/// The editing controller passed to the input TextField
|
/// The editing controller passed to the input TextField
|
||||||
TextEditingController textEditingController;
|
TextEditingController textEditingController;
|
||||||
@@ -198,8 +202,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
child: _buildDmCheckbox(),
|
child: _buildDmCheckbox(),
|
||||||
),
|
),
|
||||||
if(_openFilePickerSection)
|
if (_openFilePickerSection) _buildFilePickerSection(),
|
||||||
_buildFilePickerSection(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -538,9 +541,146 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
Widget _buildFilePickerSection() {
|
Widget _buildFilePickerSection() {
|
||||||
return Container(
|
return Container(
|
||||||
height: 200.0,
|
height: 200.0,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
StreamIcons.picture,
|
||||||
|
color: _filePickerIndex == 0
|
||||||
|
? StreamChatTheme.of(context).accentColor
|
||||||
|
: Colors.black.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_filePickerIndex = 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
StreamIcons.folder,
|
||||||
|
color: _filePickerIndex == 1
|
||||||
|
? StreamChatTheme.of(context).accentColor
|
||||||
|
: Colors.black.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_filePickerIndex = 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
StreamIcons.camera,
|
||||||
|
color: _filePickerIndex == 2
|
||||||
|
? StreamChatTheme.of(context).accentColor
|
||||||
|
: Colors.black.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_filePickerIndex = 2;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: _buildPickerSection(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildPickerSection() {
|
||||||
|
switch (_filePickerIndex) {
|
||||||
|
case 0:
|
||||||
|
if (_selectedAlbum != null) {
|
||||||
|
return FutureBuilder<MediaPage>(
|
||||||
|
future: _selectedAlbum.listMedia(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return GridView.builder(
|
||||||
|
itemCount: snapshot.data.total,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 3),
|
||||||
|
itemBuilder: (context, position) {
|
||||||
|
return FutureBuilder<File>(
|
||||||
|
future: snapshot.data.items[position].getFile(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
child: AspectRatio(
|
||||||
|
child: Image.file(snapshot.data),
|
||||||
|
aspectRatio: 1.0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return FutureBuilder<List<Album>>(
|
||||||
|
future: PhotoGallery.listAlbums(mediumType: MediumType.image),
|
||||||
|
builder: (context, albumData) {
|
||||||
|
if (!albumData.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return GridView.builder(
|
||||||
|
itemCount: albumData.data.length,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 3),
|
||||||
|
itemBuilder: (context, position) {
|
||||||
|
return FutureBuilder<List<int>>(
|
||||||
|
future: albumData.data[position].getThumbnail(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InkWell(
|
||||||
|
child: AspectRatio(
|
||||||
|
child: Image.memory(snapshot.data),
|
||||||
|
aspectRatio: 1.0,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_selectedAlbum = albumData.data[position];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OverlayEntry _buildMentionsOverlayEntry() {
|
OverlayEntry _buildMentionsOverlayEntry() {
|
||||||
final splits = textEditingController.text
|
final splits = textEditingController.text
|
||||||
.substring(0, textEditingController.value.selection.start)
|
.substring(0, textEditingController.value.selection.start)
|
||||||
@@ -814,7 +954,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if(_openFilePickerSection) {
|
if (_openFilePickerSection) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_openFilePickerSection = false;
|
_openFilePickerSection = false;
|
||||||
});
|
});
|
||||||
@@ -832,7 +972,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
_focusNode.unfocus();
|
_focusNode.unfocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!kIsWeb) {
|
if (!kIsWeb) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_openFilePickerSection = true;
|
_openFilePickerSection = true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ dependencies:
|
|||||||
carousel_slider: ^2.2.1
|
carousel_slider: ^2.2.1
|
||||||
clipboard: ^0.1.2+8
|
clipboard: ^0.1.2+8
|
||||||
widgets_visibility_provider: ^2.0.2
|
widgets_visibility_provider: ^2.0.2
|
||||||
|
photo_gallery: ^0.3.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
assets:
|
assets:
|
||||||
|
|||||||
Reference in New Issue
Block a user