import { Injectable } from "@angular/core"; import { NavController, ToastController, LoadingController, AlertController, Platform } from "@ionic/angular"; import { Router } from "@angular/router"; import { TranslatorService } from "../translator/translator.service"; import { AlertControllerService } from "../../ui/alert/alert-controller.service"; import { Response } from "../models/response"; import { Location, DatePipe } from "@angular/common"; import { ThemeableBrowser } from "@ionic-native/themeable-browser/ngx"; import { BrowserConfig } from "./models/browser-config"; import { LaunchNavigator, LaunchNavigatorOptions } from "@ionic-native/launch-navigator/ngx"; import { Device } from "@ionic-native/device/ngx"; import { ProgressLoadingService } from "../../ui/progressLoading/progress-loading.service"; import { Observable, throwError } from "rxjs"; import { SharedDataService } from "../shared-data-service/shared-data.service"; import { Badge } from "@ionic-native/badge/ngx"; import { LifeCycleService } from "../life-cycle/life-cycle.service"; import { Diagnostic } from '@ionic-native/diagnostic/ngx'; import { CallNumber } from '@ionic-native/call-number/ngx'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; @Injectable({ providedIn: "root" }) export class CommonService { public static months_en_long = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; public static months_en = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; public static months_ar = [ "يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر" ]; private progressLoaders: any[] = []; private loadingProgress: any; constructor( public nav: NavController, public router: Router, public location: Location, public ts: TranslatorService, public loadingController: LoadingController, public progressLoadingService: ProgressLoadingService, public toastController: ToastController, public alertController: AlertControllerService, public alertControllerIonic: AlertController, public themeableBrowser: ThemeableBrowser, public launchNavigation: LaunchNavigator, public platform: Platform, public device: Device, public sharedService: SharedDataService, public badge: Badge, public lifeCycle: LifeCycleService, public diagnostic: Diagnostic, public callNumber: CallNumber, public iab: InAppBrowser ) { } public back() { // this.nav.pop(); this.nav.back({ animated: true, animationDirection: "back" }); } public round(value: number, decimal: number): string { const valueStr = value.toString(); const dotIndex = valueStr.indexOf("."); if (dotIndex >= 0) { return valueStr.toString().substr(0, dotIndex + decimal); } else { return value.toString(); } } getSecondsAsDigitalClock(inputSeconds: number) { var sec_num = parseInt(inputSeconds.toString(), 10); // don't forget the second param var hours = Math.floor(sec_num / 3600); var minutes = Math.floor((sec_num - (hours * 3600)) / 60); var seconds = sec_num - (hours * 3600) - (minutes * 60); var hoursString = ''; var minutesString = ''; var secondsString = ''; hoursString = (hours < 10) ? "0" + hours : hours.toString(); minutesString = (minutes < 10) ? "0" + minutes : minutes.toString(); secondsString = (seconds < 10) ? "0" + seconds : seconds.toString(); return minutesString + ':' + secondsString; } public toastPK(page: string, key: string) { this.toast(this.ts.trPK(page, key)); } async toast(message: string) { const toast = await this.toastController.create({ message: message, showCloseButton: true, position: "middle", duration: 2000, closeButtonText: this.ts.trPK("general", "close") }); toast.present(); } private loaderIsActive = false; async startLoadingOld() { this.stopLoading(); const loader = await this.loadingController.create({ spinner: "bubbles", duration: 30000, message: this.ts.trPK("error", "wait"), translucent: true }); this.progressLoaders.push(loader); return await loader.present(); } public startLoading() { /*this.stopLoading(small); this.progressLoadingService.presentLoading( this.ts.trPK("general", "loading") , small ); */ this.stopLoading(); this.progressLoadingService.presentLoading(this.ts.trPK("general", "loading")); } public mobileNumber(number: string) { return number.substr(1, number.length - 1); } public testFunction() { } public stopLoading() { this.progressLoadingService.dismiss(); } public presentAlert(message: string, onAccept?: any) { this.alertDialog( () => { if (onAccept) { onAccept(); } }, this.ts.trPK("general", "ok"), this.ts.trPK("general", "alert"), message ); } public presentConfirmDialog(message: string, onAccept: any, onCancel?: any) { this.confirmAlertDialog( onAccept, this.ts.trPK("general", "ok"), onCancel, this.ts.trPK("general", "cancel"), this.ts.trPK("general", "confirm"), message ); } public presentAcceptDialog(message: string, onAccept: any) { this.alertDialog( onAccept, this.ts.trPK("general", "ok"), this.ts.trPK("general", "confirm"), message ); } public confirmBackDialog(message: string) { this.alertDialog( () => { this.back(); }, this.ts.trPK("general", "ok"), this.ts.trPK("general", "info"), message ); } public confirmNotAllowedDialog() { this.openHome(); this.alertDialog( () => { }, this.ts.trPK("general", "ok"), this.ts.trPK("general", "info"), this.ts.trPK("general", "not-allowed") ); } public showErrorMessageDialog( onClick: any, okLabel: string, message: string ) { this.alertDialog( onClick, okLabel, this.ts.trPK("general", "alert"), message ); } public userNeedToReLogin() { this.presentConfirmDialog(this.ts.trPK("general", "relogin"), () => { this.openLogin(); }); } public showConnectionErrorDialog(onClick: any, okLabel: string) { this.alertDialog( onClick, okLabel, this.ts.trPK("general", "alert"), this.ts.trPK("error", "conn") ); } public showConnectionTimeout(onClick: any, okLabel: string) { this.alertDialog( onClick, okLabel, this.ts.trPK("general", "alert"), this.ts.trPK("error", "timeout") ); } async JustAlertDialog(acceptLabel: string, message: string) { this.clearAllAlerts(); const alert = await this.alertControllerIonic.create({ header: this.ts.trPK("general", "info"), message: message, buttons: [ { text: acceptLabel, handler: () => { this.alertControllerIonic.dismiss(); } } ] }); // this.alerts.push(alert); await alert.present(); } async confirmAlertDialog( onAccept: any, acceptLabel: string, onCancel: any, cancelLabel: string, title: string, message: string ) { this.clearAllAlerts(); const alert = await this.alertControllerIonic.create({ header: this.ts.trPK("general", "confirm"), message: message, buttons: [ { text: cancelLabel, role: "cancel", cssClass: 'cancel-button', handler: () => { if (onCancel) { onCancel(); } this.alertControllerIonic.dismiss(); } }, { text: acceptLabel, handler: () => { if (onAccept) { onAccept(); } this.alertControllerIonic.dismiss(); } } ] }); // this.alerts.push(alert); await alert.present(); } async confirmAlertDialogPrimarySecondary( onPrimary: any, primaryLabel: string, onSecondary: any, secondaryLabel: string, title: string, message: string ) { this.clearAllAlerts(); const alert = await this.alertControllerIonic.create({ header: this.ts.trPK("general", "confirm"), message: message, buttons: [ { text: primaryLabel, handler: () => { onPrimary(); this.alertControllerIonic.dismiss(); } }, { text: secondaryLabel, handler: () => { onSecondary(); this.alertControllerIonic.dismiss(); } } ] }); await alert.present(); } async alertDialog( onAccept: any, acceptLabel: string, title: string, message: string ) { this.clearAllAlerts(); const alert = await this.alertControllerIonic.create({ header: title, message: message, buttons: [ { text: acceptLabel, handler: () => { if (onAccept) { onAccept(); } this.alertControllerIonic.dismiss(); } } ] }); // this.alerts.push(alert); await alert.present(); } async loginAlertDialog(acceptLabel: string, title: string, message: string) { this.clearAllAlerts(); const alert = await this.alertControllerIonic.create({ header: title, message: message, backdropDismiss: false, buttons: [ { text: acceptLabel, handler: () => { // this.openUserLogin(); this.alertControllerIonic.dismiss(); } } ] }); // this.alerts.push(alert); await alert.present(); } public clearAllAlerts() { // custom solutions because of async issue const alerts = document.getElementsByTagName("ion-alert"); for (let i = 0; i < alerts.length; i++) { const alert = alerts[i]; alert.parentNode.removeChild(alert); } } public getDeviceInfo(): string { if (this.platform.is("mobile")) { const os = this.platform.is("ios") ? "Iphone" : "android"; return ( os + " - " + this.device.platform + " - " + this.device.version + " , " + this.device.manufacturer ); } else { return navigator.userAgent; } } public getDeviceType(): string { if (this.platform.is("mobile")) { return "Mobile " + (this.platform.is("ios") ? "Iphone" : "android"); } else { return "Desktop"; } } public validResponse(result: Response): boolean { if (result.MessageStatus === 1) { return true; } else if (result.MessageStatus === 2) { return this.hasData(result["SameClinicApptList"]); } return false; } public openBrowser(url: string, onExit?, onFaild?, onSuccess?, successURLS?: string[]) { console.log(url); if (this.isCordova()) { this.openBrowserInApp(url, onExit, onFaild, onSuccess, successURLS); } else { this.openBrowserHtml(url, onExit, onFaild, onSuccess); } } private openBrowserHtml(url, onExit?, onFaild?, onSuccess?) { const browser = window.open(url, '_blank', 'location=no'); browser.addEventListener('loadstart', () => { }); browser.addEventListener('loaderror', () => { if (onFaild) { onFaild(); } }); browser.addEventListener('loadstop', () => { if (onSuccess) { onSuccess(); } }); } private openBrowserInApp(url: string, onExit?, onFaild?, onSuccess?, successURLS?: string[]) { this.platform.ready().then(() => { const browser = this.iab.create(url, '_blank', 'closebuttoncolor=#60686b,hidenavigationbuttons=yes,hideurlbar=yes,zoom=no'); // browser.executeScript(...); // browser.insertCSS(...); browser.on('loaderror').subscribe(event => { if (onFaild) { onFaild(); } browser.close(); }); /* browser.on('loadstop').subscribe(event => { // browser.insertCSS({ code: 'body{color: white;}' }); if (onSuccess) { onSuccess(); } }); */ browser.on('exit').subscribe(event => { if (onExit) { onExit(); } }); browser.on('loadstart').subscribe(event => { if ( successURLS ) { successURLS.forEach((successURL, index) => { if (event.url && (event.url.indexOf(successURL) >= 0)) { // alert('load start found success url'); browser.close(); if (onSuccess) { onSuccess(); } } }); } }); }); } public imageFromBase64(base64: string) { return "data:image/jpeg;base64," + base64; } public openLocation(lat: number, lng: number) { this.platform.ready().then(() => { this.launchNavigation.navigate([lat, lng]).then( () => { }, err => { // this.failedToOpenMap(); window.open('https://maps.google.com/?q=' + lat + ',' + lng); } ); }); } private failedToOpenMap() { this.presentAlert(this.ts.trPK("error", "map")); } public localizeTime(date: Date) { if (!(date.getHours() == 0 && date.getMinutes() == 0)) { let h = date.getHours() % 12 || 12; let hStr = h < 10 ? "0" + h : h; // leading 0 at the left for 1 digit hours const m = date.getMinutes(); let mStr = m < 10 ? "0" + m : m; return hStr + ":" + mStr + (date.getHours() < 12 ? " AM" : " PM"); } return ""; } public localizeDate(date: Date, time = false) { const lng = TranslatorService.getCurrentLanguageName(); let dateStr; if (lng === TranslatorService.AR) { dateStr = CommonService.months_ar[date.getMonth()] + ' ' + date.getDate() + ' ' + date.getFullYear(); } else { dateStr = CommonService.months_en[date.getMonth()] + ' ' + date.getDate() + ',' + date.getFullYear(); } return time ? dateStr + ' ' + this.localizeTime(date) : dateStr; } public localizeMonth(monthIndex) { const lng = TranslatorService.getCurrentLanguageName(); if (lng === TranslatorService.AR) { return CommonService.months_ar[monthIndex]; } else { return CommonService.months_en[monthIndex]; } } public evaluteDate(dateStr: string, time = false): string { if (dateStr) { const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10); if (utc) { const date = new Date(utc); if (date instanceof Date && !isNaN(date.getTime())) { // return this.datePipe.transform( appoDate, 'dd-MM-yyyy'); return this.localizeDate(date, time); } } } return dateStr; } public evaluateDateShort(dateStr: string): string { const date = this.evaluteDateAsObject(dateStr); if (date) { return date.getMonth() + 1 + "/" + date.getFullYear().toString().substr(2); } else { return '--'; } } public convertISODateToJsonDate(isoDate: string): string { return "/Date(" + Date.parse(isoDate) + ")/"; } public convertDateToJsonDate(date: Date): string { return "/Date(" + date.getTime() + ")/"; } /* date iso format and time is 24 format hh:mm:ss */ public convertIsoDateToObject(isoDate: string, isoTime: string): Date { const date = new Date(isoDate); const parts = isoTime.split(':'); if (this.hasData(parts)) { // remove if numbers start with 0 let hrsStr = parts[0]; let msStr = parts[1]; hrsStr = hrsStr[0] == '0' ? hrsStr.substr(1) : hrsStr; msStr = msStr[0] == '0' ? msStr.substr(1) : msStr; date.setHours(Number(hrsStr)); date.setMinutes(Number(msStr)); } return date; } public evaluateDateWithTimeZoneOffset(dateStr: string): Date { if (dateStr) { const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10); let date = new Date(utc); let timezoneOffset: number = date.getTimezoneOffset() * 60000; date.setTime(date.getTime() + timezoneOffset); return date; } return null } public evaluteDateAsObject(dateStr: string): Date { if (dateStr) { const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10); return new Date(utc); } return null; } public getDateISO(date: Date): string { return ( date.getFullYear().toString() + "-" + this.trailerZero(date.getMonth() + 1) + "-" + this.trailerZero(date.getDate()) ); } public getTodayISO(): string { return this.getDateISO(new Date()); } public getTimeISO(date: Date): string { return ( this.trailerZero(date.getHours()) + ":" + this.trailerZero(date.getMinutes()) + ":00" ); } public getDateTimeISO(date: Date): string { return this.getDateISO(date) + " " + this.getTimeISO(date); } public getDateTimeISOFromString(dateStr: string): string { const date = this.evaluteDateAsObject(dateStr); return this.getDateTimeISO(date) + " " + this.getTimeISO(date); } public getCurrentTimeISO(): string { return this.getTimeISO(new Date()); } private trailerZero(value: number): string { const str = value.toString(); return str.length > 1 ? str : "0" + str; } public hasData(array: any[]): boolean { return array != null && array.length > 0; } public extractNumber(message: string): string { if (message != null && message.length > 0) { let startIndex = null; let endIndex = message.length - 1; for (let i = 0; i < message.length; i++) { const code = message.charCodeAt(i); if (this.inNumberRange(code)) { if (!startIndex) { startIndex = i; } } else { if (startIndex) { endIndex = i; break; } } } return startIndex ? message.substring(startIndex, endIndex) : ""; } return null; } public inNumberRange(targetCode: number): boolean { const minDigit = "0".charCodeAt(0); const maxDigit = "9".charCodeAt(0); return targetCode >= minDigit && targetCode <= maxDigit; } public enterPage() { } private smsAlertDialog = null; public presentSMSPasswordDialog( onAccept: any, smsCode?: string, title?: string ) { this.dismissSMSDialog().subscribe(removed => { this.createSMSPAsswordDialog(onAccept, smsCode, title); }); } async createSMSPAsswordDialog( onAccept: any, smsCode?: string, title?: string ) { this.smsAlertDialog = await this.alertControllerIonic.create({ header: title || this.ts.trPK("general", "enter-sms-code"), inputs: [ { name: "sms", type: "number", value: smsCode, placeholder: this.ts.trPK("general", "enter-sms") } ], buttons: [ { text: this.ts.trPK("general", "cancel"), role: "cancel", cssClass: 'cancel-button', handler: () => { } }, { text: this.ts.trPK("general", "ok"), handler: data => { onAccept(data.sms); } } ] }); await this.smsAlertDialog.present(); } public getStartOfDay(date: Date): Date { date.setHours(0, 0, 0, 0); return date; } public dismissSMSDialog(): Observable { return Observable.create(observer => { this.alertControllerIonic.getTop().then( () => { this.alertControllerIonic.dismiss().then( () => { observer.next(true); observer.complete(); }, () => { observer.next(false); observer.complete(); } ); }, () => { observer.next(false); observer.complete(); } ); }); } public getStartOfToday(): number { const date = new Date(); date.setHours(0, 0, 0, 0); return date.getTime(); } public getGraphSeries( xLabels: string[], data: number[], title: string, color: string, fill = false ): any { return { labels: xLabels, datasets: [ { label: title, data: data, fill: fill, borderColor: color, backgroundColor: color } ] }; } public getGraphDataSet(title: string, data: number[], color: string, fill = false) { return { label: title, data: data, fill: fill, borderColor: color, backgroundColor: color }; } public getGraphMultiSeries(xLabels: string[], datasets: any[]): any { return { labels: xLabels, datasets: datasets }; } public get2SeriesMultiGraphData(dataList: any[], value1Key, title1, value2Key, title2, labels: string[]) { const series1: number[] = []; const series2: number[] = []; for (const data of dataList) { series1.push(data[value1Key]); series2.push(data[value2Key]); } const dataSets = [ this.getGraphDataSet(this.ts.trInline(title1), series1, '#d12026'), this.getGraphDataSet(this.ts.trInline(title2), series2, '#60686b') ]; return this.getGraphMultiSeries(labels, dataSets); } async setBadge(count: number) { this.platform.ready().then(() => { if (count > 0) { this.badge.set(count); } else { this.badge.clear(); } }); } public isHtml5VideoSupported(): boolean { const v = document.createElement("video"); if (v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) { return true; } if (v.canPlayType('video/ogg; codecs="theora, vorbis"')) { return true; } if (v.canPlayType('video/webm; codecs="vp8, vorbis"')) { return true; } return false; } public isCordova(): boolean { return this.platform.is("cordova"); } public pageRevisited(pageName: string): Observable { return this.lifeCycle.pageRevisited(pageName); } /* open calls */ public openHome() { this.nav.navigateForward(["/home"]); } public openForgotPassword() { this.nav.navigateForward(["/authentication/forgot"]); } public openProfile() { this.nav.navigateForward(["/profile/home"]); } public openAccuralPage() { this.nav.navigateForward(["/accrual-balances/home"]); } public openMyTeamPage(){ this.nav.navigateForward(["/my-team/home"]); } public openMyTeamDetails(){ this.nav.navigateForward(["/my-team/details"]); } public reload(url: string, from: string) { console.log("force reload called from:" + from); // window.location.reload(); location.href = url; } public navigateRoot(url: string) { this.nav.navigateRoot([url]); } public navigateByURL(url: string) { this.router.navigateByUrl(url); // this.router.navigateByUrl([url); } public navigateForward(url: string) { this.nav.navigateForward([url]); } public navigateBack(url: string) { this.nav.navigateBack([url]); } private alternateNavigate(paths: string[], key: string, root = false) { let url: string; if (localStorage.getItem(key) === "yes") { localStorage.setItem(key, "no"); url = paths[0]; } else { localStorage.setItem(key, "yes"); url = paths[1]; } if (root) { this.nav.navigateRoot([url]); } else { this.nav.navigateForward([url]); } } public openLogin() { this.nav.navigateRoot(["/authentication/login"]); } public openUserForgot() { this.nav.navigateForward(["/authentication/checkuser"]); } public openSMSPage() { this.nav.navigateForward(["/authentication/smspage"]); } public navigateTo(url: string) { this.nav.navigateForward([url]); } public keysInObject(obj): any[] { const keys: any = []; if (obj != null) { for (const key in obj) { keys.push(key); } } return keys.length > 0 ? keys : null; } public keysCountInObject(obj): number { let count = 0; if (obj != null) { for (const key in obj) { count++; } } return count; } public checkBlueTooth(feedback: any) { this.platform.ready().then(() => { this.diagnostic.getBluetoothState() .then((state) => { if (state == this.diagnostic.bluetoothState.POWERED_ON) { feedback(); } else { this.presentAlert(this.ts.trPK('bluetooth', 'start')); } }).catch(e => { this.presentAlert(this.ts.trPK('bluetooth', 'start')) }); }); } public callPhoneNumber(phoneNumber: string) { this.platform.ready().then(() => { if (this.isCordova()) { this.callNumber.callNumber(phoneNumber, true) .then(res => { }).catch(err => { }); } else { window.open('tel:' + phoneNumber); // this.presentAlert(this.ts.trPK('error', 'call')); } }); } }