您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

269 行
9.3 KiB

using System.Collections.Generic;
using ChatComponents;
using uiwidgets;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.service;
using Unity.UIWidgets.services;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using System;
using UnityEngine;
using Canvas = UnityEngine.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Material = Unity.UIWidgets.material.Material;
namespace UIWidgetsSample
{
public class NewLineIntent : Intent
{
public NewLineIntent(LocalKey key ) : base(key)
{
}
}
public class SendMessageIntent : Intent
{
public SendMessageIntent(LocalKey key ) : base(key)
{
}
}
/// A class that represents bottom bar widget with a text field, attachment and
/// send buttons inside. Hides send button when text field is empty.
public class Input : StatefulWidget
{
/// Whether attachment is uploading. Will replace attachment button with a
/// [CircularProgressIndicator]. Since we don't have libraries for
/// managing media in dependencies we have no way of knowing if
/// something is uploading so you need to set this manually.
public readonly bool? isAttachmentUploading;
/// See [AttachmentButton.onPressed]
public readonly OnAttachmentPressed onAttachmentPressed;
/// Will be called on [SendButton] tap. Has [types.PartialText] which can
/// be transformed to [types.TextMessage] and added to the messages list.
public readonly OnSendPressed onSendPressed;
/// Will be called whenever the text inside [TextField] changes
public readonly OnTextChanged onTextChanged;
/// Creates [Input] widget
public Input(
OnSendPressed onSendPressed,
Key key = null,
bool? isAttachmentUploading = null,
OnAttachmentPressed onAttachmentPressed = null,
OnTextChanged onTextChanged = null
) : base(key)
{
this.onAttachmentPressed = onAttachmentPressed;
this.isAttachmentUploading = isAttachmentUploading;
this.onSendPressed = onSendPressed;
this.onTextChanged = onTextChanged;
}
public override State createState()
{
return new _InputState();
}
}
/// [Input] widget state
internal class _InputState : State<Input>
{
public readonly FocusNode _inputFocusNode = new FocusNode();
public readonly TextEditingController _textController = new TextEditingController();
private bool _sendButtonVisible;
public override void initState()
{
base.initState();
_textController.addListener(_handleTextControllerChange);
}
public override void dispose()
{
_inputFocusNode.dispose();
_textController.dispose();
base.dispose();
}
private void _handleSendPressed()
{
var _partialText = new PartialText(_textController.text.TrimEnd());
widget.onSendPressed(_partialText);
_textController.clear();
}
private void _handleTextControllerChange()
{
setState(() =>
{
_sendButtonVisible = _textController.text != "";
});
}
private Widget _leftWidget()
{
if (widget.isAttachmentUploading == true)
return new SizedBox(
height: 14,
width: 24,
child: new CircularProgressIndicator(
backgroundColor: Colors.transparent,
strokeWidth: 2,
valueColor: new AlwaysStoppedAnimation<Color>(
InheritedChatTheme.of(context).theme.inputTextColor
)
)
);
else
{
return new AttachmentButton(onPressed: ()=>
{
widget.onAttachmentPressed();
});
}
}
public CallbackAction sendPress(){
return new CallbackAction(
intentKey: DoNothingAction.key,
onInvoke: (FocusNode node, Intent intent) => _handleSendPressed()
);
}
public CallbackAction sendSelectionPress()
{
return new CallbackAction(
intentKey: DoNothingAction.key,
onInvoke: (FocusNode node, Intent intent) =>
{
var _newValue = $"{_textController.text}\r\n";
_textController.value = new TextEditingValue(
_newValue,
TextSelection.fromPosition(
new TextPosition(_newValue.Length)
)
);
}
);
}
public override Widget build(BuildContext context)
{
var _query = MediaQuery.of(context);
var results = new List<Widget>();
//if (widget.onAttachmentPressed != null)
// results.Add(_leftWidget());
results.Add( new SizedBox(
height: 14,
width: 24
));
var hintStyle = InheritedChatTheme.of(context)?
.theme
.inputTextStyle
.copyWith(
color: InheritedChatTheme.of(context)?
.theme
.inputTextColor
.withOpacity(0.5f)
);
var hintText = InheritedL10n.of(context)?.l10n?.inputPlaceholder;
var decoration = InputDecoration.collapsed(
hintStyle: hintStyle,
hintText: hintText
);
var style = InheritedChatTheme.of(context)
.theme
.inputTextStyle
.copyWith(
color: InheritedChatTheme.of(context)
.theme
.inputTextColor
);
var item = new Expanded(
child: new TextField(
controller: _textController,
decoration: decoration ,
focusNode: _inputFocusNode,
keyboardType: TextInputType.multiline,
maxLines: 5,
minLines: 1,
onChanged: (_str) =>
{
widget.onTextChanged(_str);
},
style: style,
textCapitalization: TextCapitalization.sentences
)
);
results.Add(item);
results.Add(new Visibility(
visible: _sendButtonVisible,
child: new SendButton(
onPressed: _handleSendPressed
)
));
var shortCutsKey = new Dictionary<LogicalKeySet, Intent>
{
{new LogicalKeySet(LogicalKeyboardKey.enter), new SendMessageIntent(DoNothingAction.key)},
{
new LogicalKeySet(LogicalKeyboardKey.enter, LogicalKeyboardKey.alt),
new NewLineIntent(DoNothingAction.key)
},
{
new LogicalKeySet(LogicalKeyboardKey.enter, LogicalKeyboardKey.shift),
new NewLineIntent(DoNothingAction.key)
}
};
var actionKeys = new Dictionary<LocalKey, ActionFactory>
{
{new ObjectKey(typeof(SendMessageIntent)), sendPress},
{new ObjectKey(typeof(NewLineIntent)), sendSelectionPress}
};
var test = _query;
return new GestureDetector(
onTap: () =>
{
_inputFocusNode.requestFocus();
},
child: new Shortcuts(
shortcuts: shortCutsKey ,
child: new Actions(
actions: actionKeys,
child: new Focus(
autofocus: true,
child: new Material(
borderRadius: InheritedChatTheme.of(context).theme.inputBorderRadius,
color: InheritedChatTheme.of(context).theme.inputBackgroundColor,
child: new Container(
padding: EdgeInsets.fromLTRB(
left:_query.padding.left,
top:10,
right:_query.padding.right,
bottom:10 + _query.viewInsets.bottom + _query.padding.bottom
),
child: new Row(
children: results
)
)
)
)
)
)
);
}
}
}