first commit

This commit is contained in:
编码猿
2024-09-27 01:32:49 +08:00
commit 28ebe05a64
7399 changed files with 1174529 additions and 0 deletions

View File

@@ -0,0 +1 @@
317afd6d-ca10-4a61-878f-aadcb5686fda

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'extra_item_container.dart';
class DefaultExtraWidget extends StatefulWidget {
@override
_DefaultExtraWidgetState createState() => _DefaultExtraWidgetState();
}
class _DefaultExtraWidgetState extends State<DefaultExtraWidget> {
@override
Widget build(BuildContext context) {
return ExtraItemContainer(
items: [
createitem(),
createitem(),
createitem(),
createitem(),
createitem(),
createitem(),
createitem(),
createitem(),
createitem(),
],
);
}
ExtraItem createitem() => DefaultExtraItem(
icon: Icon(Icons.add),
text: "添加",
onPressed: () {
print("添加");
},
);
}

View File

@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
class ExtraItemContainer extends StatefulWidget {
final List<ExtraItem> items;
const ExtraItemContainer({
Key key,
this.items,
}) : super(key: key);
@override
_ExtraItemContainerState createState() => _ExtraItemContainerState();
}
class _ExtraItemContainerState extends State<ExtraItemContainer> {
@override
Widget build(BuildContext context) {
final pages = createPages();
return PageView(
children: pages,
);
}
List<Widget> createPages() {
final items = widget.items;
final hasLastPage = items.length % 8 == 0 ? 0 : 1;
final totalPageCount = items.length ~/ 8 + hasLastPage;
List<Widget> pages = [];
for (var i = 0; i < totalPageCount; i++) {
final page = getPage(i);
pages.add(page);
}
return pages;
}
Widget getPage(int page) {
List<ExtraItem> extras = [];
for (var i = 0; i < widget.items.length; i++) {
if (i < page * 8) continue;
if (i > (page + 1) * 8 - 1) continue;
extras.add(widget.items[i]);
}
List<ExtraItem> itemList1 = [];
List<ExtraItem> itemList2 = [];
for (var i = 0; i < extras.length; i++) {
if (i < 4) {
itemList1.add(extras[i]);
} else {
itemList2.add(extras[i]);
}
}
if (itemList1.length < 4) {
final length = itemList1.length;
for (var i = 0; i < 4 - length; i++) {
itemList1.add(EmptyExtraItem());
}
}
if (itemList2.length < 4) {
final length = itemList2.length;
for (var i = 0; i < 4 - length; i++) {
itemList2.add(EmptyExtraItem());
}
}
return Column(
children: <Widget>[
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
for (final item in itemList1)
Expanded(
child: item.buildItem(),
)
],
),
),
Expanded(
child: Row(
children: <Widget>[
for (final item in itemList2)
Expanded(
child: item.buildItem(),
)
],
),
),
],
);
}
}
abstract class ExtraItem {
ExtraItem();
factory ExtraItem.def({Widget icon, String text, Function onPressed}) {
return DefaultExtraItem(
icon: icon,
text: text,
onPressed: onPressed,
);
}
Widget buildItem();
}
class DefaultExtraItem extends ExtraItem {
final Widget icon;
final String text;
final Function onPressed;
DefaultExtraItem({
this.icon,
this.text,
this.onPressed,
});
Widget buildItem() {
return InkWell(
onTap: onPressed,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
icon,
Container(
height: 10,
),
Text(text),
],
),
),
);
}
}
class EmptyExtraItem extends ExtraItem {
EmptyExtraItem();
@override
Widget buildItem() => Container();
}

View File

@@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
class ImageButton extends StatefulWidget {
final ImageProvider image;
final Function onPressed;
const ImageButton({
Key key,
this.onPressed,
this.image,
}) : super(key: key);
@override
_ImageButtonState createState() => _ImageButtonState();
}
class _ImageButtonState extends State<ImageButton> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onPressed,
child: Container(
width: 44,
height: 44,
alignment: Alignment.center,
child: Image(
image: widget.image,
width: 35,
height: 35,
),
),
);
}
}

View File

@@ -0,0 +1,350 @@
import 'dart:async';
import 'package:emojis/emoji.dart';
import 'package:flutter/material.dart';
import 'package:peach/config/_.dart';
import 'package:peach/event/_.dart';
import 'dart:ui' as ui;
import 'package:peach/utils/Screen.dart';
typedef void OnSend(String text);
ChatType _initType = ChatType.text;
double _softKeyHeight = 324.0;
class InputWidget extends StatefulWidget {
final TextEditingController controller;
final Widget extraWidget;
final Widget emojiWidget;
final Widget voiceWidget;
final OnSend onSend;
final Function onFocusNode;
final String hintText;
const InputWidget({
Key key,
@required this.controller,
this.extraWidget,
this.emojiWidget,
this.voiceWidget,
this.onSend,
this.onFocusNode,
this.hintText = "回复",
}) : super(key: key);
@override
InputWidgetState createState() =>
InputWidgetState(this.onSend, this.onFocusNode);
}
class InputWidgetState extends State<InputWidget>
with WidgetsBindingObserver, TickerProviderStateMixin {
final Function onSend;
final Function onFocusNode;
String hintText = "回复";
ChatType currentType = _initType;
FocusNode focusNode = FocusNode();
StreamController<String> inputContentStreamController =
StreamController.broadcast();
InputWidgetState(this.onSend, this.onFocusNode);
Stream<String> get inputContentStream => inputContentStreamController.stream;
AnimationController _bottomHeightController;
double maxHeight = 90;
List<Emoji> emList = Emoji.all().take(100).toList();
Color butColor = ColorConfig.TextColor;
@override
void initState() {
super.initState();
onFocusNode(focusNode);
WidgetsBinding.instance.addObserver(this);
focusNode.addListener(onFocus);
widget.controller.addListener(_onInputChange);
_bottomHeightController = AnimationController(
vsync: this,
duration: Duration(
milliseconds: 250,
),
);
Config.eventBus.on<ClasshHntTextEvent>().listen((event) {
if (event.text != "") {
hintText = event.text;
}
});
}
// bool checkShowSendButton(String text) {
// if (currentType == ChatType.voice) {
// return false;
// }
// if (text.trim().isNotEmpty) {
// return true;
// }
// return false;
// }
@override
void didChangeMetrics() {
final mediaQueryData = MediaQueryData.fromWindow(ui.window);
final keyHeight = mediaQueryData?.viewInsets?.bottom;
if (keyHeight != 0) {
_softKeyHeight = keyHeight;
// updateState(ChatType.text);
} else {
// setState(() {});
}
}
void onFocus() {
if (focusNode.hasFocus) {
updateState(ChatType.text);
}
}
void _onInputChange() {
inputContentStreamController.add(widget.controller.text);
if (widget.controller.text.length > 0) {
butColor = ColorConfig.ThemeColor;
} else {
butColor = ColorConfig.TextColor;
}
setState(() {});
}
@override
void dispose() {
_bottomHeightController.dispose();
inputContentStreamController.close();
widget.controller.removeListener(_onInputChange);
focusNode.removeListener(onFocus);
focusNode.dispose();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(maxHeight: 390),
child: Container(
height: maxHeight,
// decoration: BoxDecoration(
// border: Border(
// top: BorderSide(color: ColorConfig.LineColor, width: 1),
// ),
// ),
child: Column(
children: <Widget>[
buildInputButton(),
Container(
margin: EdgeInsets.only(bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
buildEmojiButton(),
buildRightButton(),
],
),
),
// Divider(),
_buildBottomContainer(child: _buildBottomItems())
],
),
),
);
}
Widget buildRightButton() {
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
iconSize: 32,
color: butColor,
enableFeedback: true,
padding: EdgeInsets.only(top: 0),
icon: Icon(Icons.send),
onPressed: () {
if (widget.controller.text.length <= 0) return;
this.onSend(widget.controller.text);
widget.controller.text = "";
},
),
);
}
Widget buildEmojiButton() {
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
iconSize: 32,
color: ColorConfig.TextColor,
padding: EdgeInsets.only(top: 0),
icon: currentType != ChatType.emoji
? Icon(Icons.mood)
: Icon(Icons.keyboard),
onPressed: () {
if (currentType != ChatType.emoji) {
updateState(ChatType.emoji);
} else {
updateState(ChatType.text);
}
},
),
);
}
Widget buildInputButton() {
final inputButton = TextField(
focusNode: focusNode,
controller: widget.controller,
cursorHeight: 20,
decoration: InputDecoration(
isDense: true,
hintText: hintText,
fillColor: Colors.white,
border: OutlineInputBorder(borderSide: BorderSide.none),
),
);
return Container(
height: Screen.setHeight(35),
padding: EdgeInsets.only(top: 15),
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: inputButton,
),
);
}
void changeBottomHeight(final double height) {
if (height > 0) {
_bottomHeightController.animateTo(1);
} else {
_bottomHeightController.animateBack(0);
}
}
Future<void> updateState(ChatType type) async {
if (type == ChatType.text || type == ChatType.voice) {
_initType = type;
}
if (type == currentType) {
return;
}
this.currentType = type;
ChangeChatTypeNotification(type).dispatch(context);
if (type != ChatType.text) {
hideSoftKey();
setState(() {
maxHeight = 390;
});
} else {
showSoftKey();
setState(() {
maxHeight = 90;
});
}
if (type == ChatType.emoji || type == ChatType.extra) {
// _currentOtherHeight = _softKeyHeight;
changeBottomHeight(1);
} else {
changeBottomHeight(0);
// _currentOtherHeight = 0;
}
setState(() {});
}
void showSoftKey() {
FocusScope.of(context).requestFocus(focusNode);
}
void hideSoftKey() {
focusNode.unfocus();
}
Widget _buildBottomContainer({Widget child}) {
return SizeTransition(
sizeFactor: _bottomHeightController,
child: Container(
child: child,
height: 300,
),
);
}
Widget _buildBottomItems() {
return Container(
decoration: BoxDecoration(
border: Border(top: BorderSide(width: 1, color: ColorConfig.LineColor)),
),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
removeBottom: true,
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7,
),
children: [
...emList.asMap().keys.map(
(e) {
return GestureDetector(
onTap: () {
widget.controller.text += emList[e].toString();
},
child: Container(
alignment: Alignment.center,
child: Text(
"${emList[e]}",
style: TextStyle(
fontSize: 24,
),
),
),
);
},
).toList(),
],
),
),
);
}
}
enum ChatType {
text,
voice,
emoji,
extra,
}
class ChangeChatTypeNotification extends Notification {
final ChatType type;
ChangeChatTypeNotification(this.type);
}