import {Plugins, AppState} from '@capacitor/core'; import {AfterViewChecked, AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {ChatMessage} from '../chat.message'; import {Host} from '../host'; import {ApiService} from '../api.service'; import {WebsocketListener} from '../websocket.listener'; import {WebsocketService} from '../websocket.service'; import {LocalNotifications} from '@ionic-native/local-notifications/ngx'; import {BackgroundMode} from '@ionic-native/background-mode/ngx'; import {ForegroundService} from '@ionic-native/foreground-service/ngx'; const {App} = Plugins; @Component({ selector: 'app-chat', templateUrl: './chat.component.html', styleUrls: ['./chat.component.scss'], }) export class ChatComponent implements OnInit, AfterViewInit, AfterViewChecked, WebsocketListener { messages: ChatMessage[] = []; userToken: string; userId: number; url: string; @ViewChild('chatPostArea') chatPostArea: ElementRef; chatText: string; private oldScrollHeight = 0; private messageOffset = 0; private messageLimit = 10; private hasBeenReloaded = false; private hasFocus = true; public constructor( private apiService: ApiService, private websocketService: WebsocketService, private localNotifications: LocalNotifications, private backgroundMode: BackgroundMode, private foregroundService: ForegroundService ) { this.userToken = this.apiService.getFromStorage('token'); this.userId = Number(this.apiService.getFromStorage('userId')); this.url = Host.URL; this.websocketService.setListener(this); this.websocketService.initializeSocket(this.apiService.getFromStorage('chatToken')); this.backgroundMode.disableBatteryOptimizations(); this.backgroundMode.disableWebViewOptimizations(); } ngAfterViewInit(): void { this.chatPostArea.nativeElement.scroll(0, this.chatPostArea.nativeElement.scrollHeight); } ngAfterViewChecked(): void { if (this.oldScrollHeight !== this.chatPostArea.nativeElement.scrollHeight) { const scrollTop = this.chatPostArea.nativeElement.scrollTop; const clientHeight = this.chatPostArea.nativeElement.clientHeight; if (this.hasBeenReloaded) { this.chatPostArea.nativeElement.scroll(0, this.chatPostArea.nativeElement.scrollHeight - this.oldScrollHeight); this.hasBeenReloaded = false; } else if (scrollTop + clientHeight > this.oldScrollHeight - 10) { this.chatPostArea.nativeElement.scroll(0, this.oldScrollHeight); } this.oldScrollHeight = this.chatPostArea.nativeElement.scrollHeight; } } ngOnInit(): void { if (this.userToken === null) { return; } this.localNotifications.requestPermission(); this.foregroundService.start('METAsocket', 'The chat for WowApp', 'ic_stat_notification_icon_enabled'); this.apiService.getChatHistory(this.userToken, this.messageOffset, this.messageLimit).subscribe( (response) => { this.messages = response; this.messageOffset += this.messageLimit; } ); App.addListener('appStateChange', (state: AppState) => { this.hasFocus = state.isActive; }); setInterval( () => { this.websocketService.sendKeepAliveMessage(); }, 1000 * 60 // every minute ); } onScroll(): void { if (this.chatPostArea.nativeElement.scrollTop === 0) { this.apiService.getChatHistory(this.userToken, this.messageOffset, this.messageLimit).subscribe( (response) => { this.messages = response.concat(this.messages); this.messageOffset += this.messageLimit; this.hasBeenReloaded = true; } ); } } onTextInput(event: Event): void { if (!(event instanceof KeyboardEvent)) { return; } switch (event.key) { case 'Enter': event.preventDefault(); if (this.chatText.trim() === '') { return; } this.websocketService.sendChatMessage(this.chatText); this.chatText = ''; return; default: return; } } onChatMessage(message: ChatMessage): void { this.messages.push(message); this.messageOffset++; if (message.userId === this.userId) { return; } this.triggerNotification(message); } triggerNotification(message: ChatMessage): void { this.localNotifications.schedule( { title: message.username, text: message.message, id: 1, priority: 2, lockscreen: true, autoClear: true, icon: Host.URL + '/user/' + message.userId + '/avatar?token=' + this.userToken, smallIcon: 'ic_stat_notification_icon_enabled', led: {color: '#ff00ff', on: 500, off: 500}, trigger: { at: new Date(new Date().getTime() + 1000) }, sound: 'file://assets/audio/murloc.wav', vibrate: true } ); } }