/**
 *  Copyright 2020 Google LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */ import { Component , Input , HostBinding , ElementRef , ViewChild , AfterViewChecked , AfterViewInit , OnDestroy } from '@angular/core' ; import { BotResponseService , BotName } from '../bot-response.service' ; interface IMessage { text : string ; isPlayer : boolean ; isWaiting ? : boolean ; } let arePassiveListenersSupported = false ; try { window . addEventListener ( 'test' , null , Object . defineProperty ( { } , 'passive' , { get ( ) { arePassiveListenersSupported = true ; } } ) ) ; } catch ( err ) { } @ Component ( { selector : 'app-interview-pane' , templateUrl : './interview-pane.component.html' , styleUrls : [ './interview-pane.component.scss' ] } ) export class InterviewPaneComponent implements AfterViewChecked , AfterViewInit , OnDestroy { @ ViewChild ( 'messageContainer' ) private scrollContainer : ElementRef ; @ HostBinding ( 'attr.data-bot-name' ) @ Input ( ) botName : BotName ; question = '' ; messages : IMessage [ ] = [ ] ; private shouldScroll = false ; constructor ( private botResponseService ) { this . handleScroll = this . handleScroll . bind ( this ) ; } ngAfterViewChecked ( ) { if ( this . shouldScroll ) { setTimeout ( ( ) => { this . scrollContainer . nativeElement . scrollTop = this . scrollContainer . nativeElement . scrollHeight ; this . toggleScrollClasses ( ) ; } , 0 ) ; this . shouldScroll = false ; } } ngAfterViewInit ( ) { this . scrollContainer . nativeElement . addEventListener ( 'scroll' , this . handleScroll , arePassiveListenersSupported ? { passive : true , } : false ) ; } ngOnDestroy ( ) { if ( this . scrollContainer ) { this . scrollContainer . nativeElement . removeEventListener ( 'scroll' , this . handleScroll ) ; } } handleScroll ( ) { this . toggleScrollClasses ( ) ; } handleQuestionSubmit ( event ) { event . preventDefault ( ) ; this . messages . push ( { text : this . question , isPlayer : true , } ) ; const question = this . question ; this . question = '' ; this . messages . push ( { text : '' , isPlayer : false , isWaiting : true , } ) ; this . scrollToBottom ( ) ; setTimeout ( async ( ) => { let response = await this . botResponseService . getResponse ( question , this . botName ) ; if ( ! response ) { response = 'I\'m sorry, I didn\'t understand that. Can you ask that another way?' ; } const pendingMessage = this . messages . find ( ( { isWaiting , isPlayer } ) => ! isPlayer && isWaiting ) ; if ( pendingMessage ) { pendingMessage . text = response ; pendingMessage . isWaiting = false ; } else { this . messages . push ( { text : response , isPlayer : false , } ) ; this . scrollToBottom ( ) ; } } , 0 ) ; } handleQuestionInput ( event ) { this . question = event . target . value ; } private scrollToBottom ( ) { this . shouldScroll = true ; } private toggleScrollClasses ( ) { this . scrollContainer . nativeElement . classList . toggle ( 'at-top' , this . scrollContainer . nativeElement . scrollTop === 0 ) ; this . scrollContainer . nativeElement . classList . toggle ( 'at-bottom' , this . scrollContainer . nativeElement . scrollTop + this . scrollContainer . nativeElement . clientHeight >= this . scrollContainer . nativeElement . scrollHeight ) ; } }