您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
269 行
9.3 KiB
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
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|