Skip to content

Instantly share code, notes, and snippets.

@danielsmykowski1
Created November 2, 2019 12:32
Show Gist options
  • Save danielsmykowski1/cafc047b7f51f720c0ba06ec2f88a628 to your computer and use it in GitHub Desktop.
Save danielsmykowski1/cafc047b7f51f720c0ba06ec2f88a628 to your computer and use it in GitHub Desktop.
AngularDart message input component for chatting PWA
:host {
background-color: #eae0da;
width: 100%;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
input[type="file"] {
display: none;
}
.mic-icon {
padding-left: 8px;
padding-right: 8px;
opacity: 0;
transition: opacity 250ms ease-in-out;
}
.mic-icon.show {
opacity: 1;
}
material-fab.green {
background-color: #0f9d58;
color: #fff;
}
material-icon.attach_file {
transform: rotate(-45deg);
}
.input-group {
background-color: #fff;
border-radius: 20px;
margin: 5px;
}
.input-group material-fab {
margin: 0;
}
/* message input box style */
material-input.input-message {
width: 50px;
}
material-input.input-message ::ng-deep .bottom-section {
display: none;
}
material-input.input-message ::ng-deep .baseline .underline {
display: none;
}
material-input.input-message ::ng-deep .baseline .top-section {
margin-bottom: 0;
}
import 'package:angular/angular.dart';
import 'dart:html';
import 'dart:async';
import 'package:angular_components/angular_components.dart';
@Component(
selector: 'message-input',
templateUrl: 'message_input_component.html',
styleUrls: ['message_input_component.css'],
directives: [
coreDirectives,
materialInputDirectives,
MaterialInputComponent,
MaterialButtonComponent,
MaterialIconComponent,
MaterialFabComponent,
MaterialMultilineInputComponent,
],
providers: [materialProviders]
)
class MessageInputComponent {
final _messageChange = StreamController<String>();
@Output()
Stream<String> get messageChange => _messageChange.stream;
String _message = "";
String get message => _message;
@Input()
set message(String val) {
_message = val;
_messageChange.add(val);
}
bool _inputDisabled;
get inputDisabled => _inputDisabled;
@Input()
set inputDisabled(bool val) => _inputDisabled = val;
bool _showSendButton = false;
get showSendButton => _showSendButton;
@Input()
set showSendButton(bool val) => _showSendButton = val;
bool _micAllowed = false;
bool get micAllowed => _micAllowed;
@Input()
set micAllowed(bool val) => _micAllowed = val;
bool _isRecording = false;
bool get isRecording => _isRecording;
@Input()
set isRecording(bool val) => _isRecording = val;
bool _showingMic = false;
bool get showingMic => _showingMic;
@Input()
set showingMic(bool val) => _showingMic = val;
bool _cameraAsNormalButton = false;
bool get cameraAsNormalButton => _cameraAsNormalButton;
@Input()
set cameraAsNormalButton(bool val) => _cameraAsNormalButton = val;
final _messageTrigger = StreamController<String>.broadcast(sync: true);
@Output()
get messageTrigger => _messageTrigger.stream;
final _contentChangedController = StreamController<Event>.broadcast(sync: true);
@Output()
get contentChanged => _contentChangedController.stream;
final _imageChangedController = StreamController<FileList>.broadcast(sync: true);
@Output()
get imageChanged => _imageChangedController.stream;
final _attachedController = StreamController<FileList>.broadcast(sync: true);
@Output()
get attached => _attachedController.stream;
final _micClickedController = StreamController<Event>.broadcast(sync: true);
@Output()
get micClicked => _micClickedController.stream;
final _cancelClickedController = StreamController<Event>.broadcast(sync: true);
@Output()
get cancelClicked => _cancelClickedController.stream;
final _cameraClickedController = StreamController<Event>.broadcast(sync: true);
@Output()
get cameraClicked => _cameraClickedController.stream;
void handleEnter(KeyboardEvent event) {
event.preventDefault();
sendTextMessage();
}
void sendTextMessage() {
String messageText = message.trim();
if (messageText.isNotEmpty || showSendButton) {
_messageTrigger.add(messageText);
}
}
void handleKeyPress() {
_contentChangedController.add(Event('contentChanged'));
}
void handleImageChange(FileList list) {
_imageChangedController.add(list);
}
void handleAttachment(FileList list) {
_attachedController.add(list);
}
void handleMicClicked() {
_micClickedController.add(Event('mic button clicked'));
}
void handleCancelClicked() {
_cancelClickedController.add(Event('cancel clicked'));
}
void handleCameraClicked() {
_cameraClickedController.add(Event('camera clicked'));
}
}
<div class="input-group layout horizontal center flex">
<material-fab mini [disabled]="inputDisabled" *ngIf="!isRecording">
<material-icon icon="sentiment_satisfied_alt"></material-icon>
</material-fab>
<material-icon
icon="mic"
class="mic-icon"
*ngIf="isRecording"
[ngClass]="showingMic ? 'show' : ''"
></material-icon>
<material-input
class="flex input-message"
label="Type a message"
multiline
[(ngModel)]="message"
(keydown.enter)="handleEnter($event)"
(inputKeyPress)="handleKeyPress"
(change)="handleKeyPress"
[disabled]="inputDisabled || isRecording"
></material-input>
<material-fab
mini
(trigger)="attachment.click()"
[disabled]="inputDisabled"
*ngIf="!isRecording"
>
<material-icon icon="attach_file" class="attach_file"></material-icon>
</material-fab>
<material-fab mini
(trigger)="cameraAsNormalButton ? handleCameraClicked() : mediaCapture.click()"
[disabled]="inputDisabled"
*ngIf="!isRecording"
>
<material-icon icon="camera_alt"></material-icon>
</material-fab>
<material-button mini
(trigger)="handleCancelClicked"
*ngIf="isRecording"
>
Cancel
</material-button>
</div>
<input
#attachment
type="file"
accept="image/*"
(change)="handleAttachment(attachment.files)"
>
<input
#mediaCapture
type="file"
(change)="handleImageChange(mediaCapture.files)"
>
<material-fab
mini
class="green"
*ngIf="message == '' && !showSendButton"
[disabled]="inputDisabled"
(trigger)="handleMicClicked"
>
<material-icon icon="mic"></material-icon>
</material-fab>
<material-fab
mini
class="green"
*ngIf="message != '' || showSendButton"
(trigger)="sendTextMessage()"
[disabled]="inputDisabled"
>
<material-icon icon="send"></material-icon>
</material-fab>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment