opt: reply panel

request focus onResume
keep emoji panel onPause
This commit is contained in:
bggRGjQaUbCoE
2024-10-07 17:03:05 +08:00
parent afa7405fda
commit 5d0e4ed441
3 changed files with 70 additions and 31 deletions

View File

@@ -7,7 +7,6 @@ import 'package:chat_bottom_container/chat_bottom_container.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:PiliPalaX/common/widgets/no_splash_factory.dart';
import 'package:PiliPalaX/http/video.dart'; import 'package:PiliPalaX/http/video.dart';
import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/models/video/reply/emote.dart'; import 'package:PiliPalaX/models/video/reply/emote.dart';
@@ -45,7 +44,7 @@ class ReplyPage extends StatefulWidget {
} }
class _ReplyPageState extends State<ReplyPage> class _ReplyPageState extends State<ReplyPage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin, WidgetsBindingObserver {
late final _focusNode = FocusNode(); late final _focusNode = FocusNode();
late final _controller = ChatBottomPanelContainerController<PanelType>(); late final _controller = ChatBottomPanelContainerController<PanelType>();
late final TextEditingController _replyContentController = late final TextEditingController _replyContentController =
@@ -65,6 +64,7 @@ class _ReplyPageState extends State<ReplyPage>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this);
if (widget.savedReply != null && widget.savedReply!.isNotEmpty) { if (widget.savedReply != null && widget.savedReply!.isNotEmpty) {
_enablePublish = true; _enablePublish = true;
@@ -87,37 +87,69 @@ class _ReplyPageState extends State<ReplyPage>
_enableSend.close(); _enableSend.close();
_focusNode.dispose(); _focusNode.dispose();
_replyContentController.dispose(); _replyContentController.dispose();
WidgetsBinding.instance.removeObserver(this);
super.dispose(); super.dispose();
} }
void _requestFocus() async {
await Future.delayed(const Duration(microseconds: 200));
_focusNode.requestFocus();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
if (mounted && _selectKeyboard) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
if (_focusNode.hasFocus) {
_focusNode.unfocus();
_requestFocus();
} else {
_requestFocus();
}
});
}
} else if (state == AppLifecycleState.paused) {
_controller.keepChatPanel();
if (_focusNode.hasFocus) {
_focusNode.unfocus();
}
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MediaQuery.removePadding( return MediaQuery.removePadding(
removeTop: true, removeTop: true,
context: context, context: context,
child: GestureDetector(
onTap: Get.back,
child: LayoutBuilder(
builder: (_, constraints) {
bool isH = constraints.maxWidth > constraints.maxHeight;
late double padding = constraints.maxWidth * 0.12;
return Padding(
padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0),
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
body: Column( body: GestureDetector(
mainAxisAlignment: MainAxisAlignment.center, onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Expanded(
child: InkWell(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
splashFactory: NoSplashFactory(),
onTap: () {
FocusScope.of(context).unfocus();
Get.back();
},
),
),
_buildInputView(), _buildInputView(),
_buildImagePreview(), _buildImagePreview(),
_buildPanelContainer(), _buildPanelContainer(),
], ],
), ),
)); ),
),
);
},
),
),
);
} }
Widget _buildPanelContainer() { Widget _buildPanelContainer() {
@@ -160,7 +192,7 @@ class _ReplyPageState extends State<ReplyPage>
} }
Widget _buildEmojiPickerPanel() { Widget _buildEmojiPickerPanel() {
double height = 200; double height = 170;
final keyboardHeight = _controller.keyboardHeight; final keyboardHeight = _controller.keyboardHeight;
if (keyboardHeight != 0) { if (keyboardHeight != 0) {
height = max(height, keyboardHeight); height = max(height, keyboardHeight);
@@ -213,6 +245,7 @@ class _ReplyPageState extends State<ReplyPage>
Widget _buildInputView() { Widget _buildInputView() {
return Container( return Container(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12), topLeft: Radius.circular(12),

View File

@@ -258,10 +258,11 @@ packages:
chat_bottom_container: chat_bottom_container:
dependency: "direct main" dependency: "direct main"
description: description:
name: chat_bottom_container path: "packages/chat_bottom_container"
sha256: fc2e690892699604524bf4a4c7ba9b3281ae060c90154b55b38116ce7812c3d8 ref: main
url: "https://pub.dev" resolved-ref: "5bd612a5ee2f0025460ec50090044209b3d43cb2"
source: hosted url: "https://github.com/pye52/flutter_chat_packages.git"
source: git
version: "0.2.0" version: "0.2.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive

View File

@@ -158,7 +158,12 @@ dependencies:
marquee: ^2.2.3 marquee: ^2.2.3
#富文本 #富文本
extended_text: ^14.0.1 extended_text: ^14.0.1
chat_bottom_container: ^0.2.0 # chat_bottom_container: ^0.2.0
chat_bottom_container:
git:
url: https://github.com/pye52/flutter_chat_packages.git
ref: main
path: packages/chat_bottom_container
image_picker: ^1.1.2 image_picker: ^1.1.2