Improve design of attachment buttons

This commit is contained in:
Nutcake 2023-05-21 18:43:01 +02:00
parent 2987603b7a
commit 358e8490bc
2 changed files with 129 additions and 141 deletions

View file

@ -21,6 +21,7 @@ class _MessageAttachmentListState extends State<MessageAttachmentList> {
final List<(FileType, File)> _loadedFiles = []; final List<(FileType, File)> _loadedFiles = [];
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
bool _showShadow = true; bool _showShadow = true;
bool _popupIsOpen = false;
@override @override
void initState() { void initState() {
@ -121,146 +122,131 @@ class _MessageAttachmentListState extends State<MessageAttachmentList> {
), ),
), ),
), ),
PopupMenuButton<DocumentType>( AnimatedSwitcher(
offset: const Offset(0, -64), duration: const Duration(milliseconds: 200),
constraints: const BoxConstraints.tightFor(width: 48 * 3, height: 64), switchInCurve: Curves.decelerate,
shadowColor: Colors.transparent, transitionBuilder: (child, animation) => FadeTransition(
position: PopupMenuPosition.over, opacity: animation,
color: Colors.transparent, child: SizeTransition(
enableFeedback: true, sizeFactor: animation,
padding: EdgeInsets.zero, axis: Axis.horizontal,
surfaceTintColor: Colors.transparent, //position: Tween<Offset>(begin: const Offset(1, 0), end: const Offset(0, 0)).animate(animation),
iconSize: 24, child: child,
itemBuilder: (context) =>
[
PopupMenuItem(
padding: EdgeInsets.zero,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true);
if (result != null) {
setState(() {
_loadedFiles.addAll(
result.files.map((e) => e.path != null ? (FileType.image, File(e.path!)) : null)
.whereNotNull());
});
}
if (context.mounted) {
Navigator.of(context).pop();
}
},
icon: const Icon(Icons.image,),
),
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final picture = await Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const MessageCameraView())) as File?;
if (picture != null) {
_loadedFiles.add((FileType.image, picture));
await widget.onChange(_loadedFiles);
}
if (context.mounted) {
Navigator.of(context).pop();
}
},
icon: const Icon(Icons.camera,),
),
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true);
if (result != null) {
setState(() {
_loadedFiles.addAll(
result.files.map((e) => e.path != null ? (FileType.any, File(e.path!)) : null)
.whereNotNull());
});
}
if (context.mounted) {
Navigator.of(context).pop();
}
},
icon: const Icon(Icons.file_present_rounded,),
),
],
),
),
],
icon: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(64),
border: Border.all(
color: Theme
.of(context)
.colorScheme
.primary,
),
),
child: Icon(
Icons.add,
color: Theme.of(context).colorScheme.onSurface,
), ),
), ),
child: _popupIsOpen ? Row(
key: const ValueKey("popup-buttons"),
children: [
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true);
if (result != null) {
setState(() {
_loadedFiles.addAll(
result.files.map((e) => e.path != null ? (FileType.image, File(e.path!)) : null)
.whereNotNull());
});
}
},
icon: const Icon(Icons.image,),
),
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final picture = await Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const MessageCameraView())) as File?;
if (picture != null) {
_loadedFiles.add((FileType.image, picture));
await widget.onChange(_loadedFiles);
}
},
icon: const Icon(Icons.camera,),
),
IconButton(
iconSize: 24,
style: IconButton.styleFrom(
backgroundColor: Theme
.of(context)
.colorScheme
.surface,
foregroundColor: Theme
.of(context)
.colorScheme
.onSurface,
side: BorderSide(
width: 1,
color: Theme
.of(context)
.colorScheme
.secondary,
)
),
padding: EdgeInsets.zero,
onPressed: () async {
final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true);
if (result != null) {
setState(() {
_loadedFiles.addAll(
result.files.map((e) => e.path != null ? (FileType.any, File(e.path!)) : null)
.whereNotNull());
});
}
},
icon: const Icon(Icons.file_present_rounded,),
),
],
) : const SizedBox.shrink(),
), ),
Container(
color: Theme.of(context).colorScheme.surface,
child: IconButton(onPressed: () {
setState(() {
_popupIsOpen = !_popupIsOpen;
});
}, icon: AnimatedRotation(
duration: const Duration(milliseconds: 200),
turns: _popupIsOpen ? 3/8 : 0,
child: const Icon(Icons.add),
)),
)
], ],
); );
} }

View file

@ -270,7 +270,7 @@ class _MessageInputBarState extends State<MessageInputBar> {
}); });
} }
}, },
icon: const Icon(Icons.camera_alt), icon: const Icon(Icons.camera),
label: const Text("Camera"), label: const Text("Camera"),
), ),
TextButton.icon( TextButton.icon(
@ -393,11 +393,13 @@ class _MessageInputBarState extends State<MessageInputBar> {
hintText: _isRecording ? "" : "Message ${widget.recipient hintText: _isRecording ? "" : "Message ${widget.recipient
.username}...", .username}...",
hintMaxLines: 1, hintMaxLines: 1,
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
fillColor: Colors.black38,
filled: true,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(24) borderSide: BorderSide.none,
), borderRadius: BorderRadius.circular(24),
)
), ),
), ),
AnimatedSwitcher( AnimatedSwitcher(