src/app/active-downloads/active-downloads.page.ts
OnInit
OnDestroy
ActiveDownloadsInterface
selector | app-active-downloads |
styleUrls | ./active-downloads.page.scss |
templateUrl | ./active-downloads.page.html |
Properties |
|
Methods |
|
constructor(popoverCtrl: PopoverController, changeDetectionRef: ChangeDetectorRef, headerService: AppHeaderService, commonUtilService: CommonUtilService, telemetryGeneratorService: TelemetryGeneratorService, location: Location, downloadService: DownloadService, eventsBusService: EventsBusService, storageService: StorageService)
|
||||||||||||||||||||||||||||||
Parameters :
|
cancelAllDownloads |
cancelAllDownloads()
|
Returns :
void
|
cancelDownload | ||||||
cancelDownload(downloadRequest: DownloadRequest)
|
||||||
Parameters :
Returns :
void
|
Private checkAvailableSpace |
checkAvailableSpace()
|
Returns :
void
|
Private Async fetchStorageDestination |
fetchStorageDestination()
|
Returns :
any
|
getContentDownloadProgress | ||||||
getContentDownloadProgress(contentId: string)
|
||||||
Parameters :
Returns :
number
|
Private handleHeaderEvents | ||||||
handleHeaderEvents(event: literal type)
|
||||||
Parameters :
Returns :
void
|
Private initAppHeader |
initAppHeader()
|
Returns :
void
|
Private initDownloadProgress |
initDownloadProgress()
|
Returns :
void
|
Private initNetworkDetection |
initNetworkDetection()
|
Returns :
void
|
ionViewDidLoad |
ionViewDidLoad()
|
Returns :
void
|
ionViewWillEnter |
ionViewWillEnter()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
Private Async presentPopupForLessStorageSpace |
presentPopupForLessStorageSpace()
|
Returns :
any
|
Private Async presentPopupForOffline |
presentPopupForOffline()
|
Returns :
any
|
Private Async showCancelPopUp | ||||||
showCancelPopUp(downloadRequest?: DownloadRequest)
|
||||||
Parameters :
Returns :
any
|
Private Optional _appHeaderSubscription |
Type : Subscription
|
Private Optional _downloadProgressSubscription |
Type : Subscription
|
Private _headerConfig |
Type : object
|
Default value : {
showHeader: true,
showBurgerMenu: false,
actionButtons: [] as string[]
}
|
Private Optional _networkSubscription |
Type : Subscription
|
Private _toast |
Type : any
|
activeDownloadRequests$ |
Type : Observable<ContentDownloadRequest[]>
|
defaultImg |
Default value : this.commonUtilService.convertFileSrc('assets/imgs/ic_launcher.png')
|
downloadProgressMap |
Type : literal type
|
networkFlag |
Type : boolean
|
Private storageDestination |
Type : any
|
import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { ActiveDownloadsInterface } from './active-downloads.interface';
import { Observable, Subscription } from 'rxjs';
import { InteractSubtype, Environment, PageId, InteractType } from '../../services/telemetry-constants';
import {
ContentDownloadRequest,
DownloadEventType,
DownloadProgress,
DownloadRequest,
DownloadService,
EventNamespace,
EventsBusService,
StorageService,
StorageDestination
} from 'sunbird-sdk';
import { Location } from '@angular/common';
import { AppHeaderService, CommonUtilService, TelemetryGeneratorService } from '../../services/index';
import { SbNoNetworkPopupComponent } from '../components/popups/sb-no-network-popup/sb-no-network-popup.component';
import { SbPopoverComponent } from '../components/popups/sb-popover/sb-popover.component';
import { featureIdMap } from '@app/feature-id-map';
import { tap, filter, take } from 'rxjs/operators';
@Component({
selector: 'app-active-downloads',
templateUrl: './active-downloads.page.html',
styleUrls: ['./active-downloads.page.scss'],
})
export class ActiveDownloadsPage implements OnInit, OnDestroy, ActiveDownloadsInterface {
downloadProgressMap: { [key: string]: number };
activeDownloadRequests$: Observable<ContentDownloadRequest[]>;
defaultImg = this.commonUtilService.convertFileSrc('assets/imgs/ic_launcher.png');
private _appHeaderSubscription?: Subscription;
private _downloadProgressSubscription?: Subscription;
private _networkSubscription?: Subscription;
private _headerConfig = {
showHeader: true,
showBurgerMenu: false,
actionButtons: [] as string[]
};
private _toast: any;
private storageDestination: any;
networkFlag: boolean;
constructor(
private popoverCtrl: PopoverController,
private changeDetectionRef: ChangeDetectorRef,
private headerService: AppHeaderService,
private commonUtilService: CommonUtilService,
private telemetryGeneratorService: TelemetryGeneratorService,
private location: Location,
@Inject('DOWNLOAD_SERVICE') private downloadService: DownloadService,
@Inject('EVENTS_BUS_SERVICE') private eventsBusService: EventsBusService,
@Inject('STORAGE_SERVICE') private storageService: StorageService
) {
this.downloadProgressMap = {};
// @ts-ignore
this.activeDownloadRequests$ = this.downloadService.getActiveDownloadRequests().pipe(
tap(() => this.changeDetectionRef.detectChanges())
);
}
ngOnInit() {
this.initDownloadProgress();
this.initAppHeader();
this.initNetworkDetection();
this.telemetryGeneratorService.generatePageViewTelemetry(
PageId.ACTIVE_DOWNLOADS,
Environment.DOWNLOADS, '');
}
ngOnDestroy() {
if (this._downloadProgressSubscription) {
this._downloadProgressSubscription.unsubscribe();
}
if (this._appHeaderSubscription) {
this._appHeaderSubscription.unsubscribe();
}
if (this._networkSubscription) {
this._networkSubscription.unsubscribe();
if (this._toast) {
this._toast.dismiss();
this._toast = undefined;
}
}
}
ionViewWillEnter() {
this.fetchStorageDestination();
this.checkAvailableSpace();
}
ionViewDidLoad() {
this.telemetryGeneratorService.generatePageViewTelemetry(
PageId.ACTIVE_DOWNLOADS,
Environment.DOWNLOADS, '');
}
cancelAllDownloads(): void {
this.telemetryGeneratorService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.DOWNLOAD_CANCEL_ALL_CLICKED,
Environment.DOWNLOADS,
PageId.ACTIVE_DOWNLOADS,
undefined,
undefined,
undefined,
featureIdMap.downloadManager.ACTIVE_DOWNLOADS_CANCEL
);
this.showCancelPopUp();
}
cancelDownload(downloadRequest: DownloadRequest): void {
this.telemetryGeneratorService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.DOWNLOAD_CANCEL_CLICKED,
Environment.DOWNLOADS,
PageId.ACTIVE_DOWNLOADS,
undefined,
undefined,
undefined,
featureIdMap.downloadManager.ACTIVE_DOWNLOADS_CANCEL
);
this.showCancelPopUp(downloadRequest);
}
getContentDownloadProgress(contentId: string): number {
return this.downloadProgressMap[contentId] && (this.downloadProgressMap[contentId] > -1) ? this.downloadProgressMap[contentId] : 0;
}
private initDownloadProgress(): void {
this._downloadProgressSubscription = this.eventsBusService.events(EventNamespace.DOWNLOADS).pipe(
filter((event) => event.type === DownloadEventType.PROGRESS),
tap((event) => {
const downloadEvent = event as DownloadProgress;
this.downloadProgressMap[downloadEvent.payload.identifier] = downloadEvent.payload.progress;
this.changeDetectionRef.detectChanges();
})
).subscribe();
}
private initAppHeader() {
this._appHeaderSubscription = this.headerService.headerEventEmitted$.subscribe(eventName => {
this.handleHeaderEvents(eventName);
});
this._headerConfig = this.headerService.getDefaultPageConfig();
this._headerConfig.actionButtons = [];
this._headerConfig.showBurgerMenu = false;
this.headerService.updatePageConfig(this._headerConfig);
}
private handleHeaderEvents(event: { name: string }) {
if(event.name =='back') {
this.location.back();
}
}
private initNetworkDetection() {
this.networkFlag = this.commonUtilService.networkInfo.isNetworkAvailable;
this._networkSubscription = this.commonUtilService.networkAvailability$.subscribe(async (available: boolean) => {
if (this.networkFlag !== available) {
if (this._toast) {
await this._toast.dismiss();
this._toast = undefined;
}
if (!available) {
this.presentPopupForOffline();
}
}
this.networkFlag = available;
});
}
private async showCancelPopUp(downloadRequest?: DownloadRequest) {
this.telemetryGeneratorService.generatePageViewTelemetry(
downloadRequest ? PageId.SINGLE_CANCEL_CONFIRMATION_POPUP : PageId.BULK_CANCEL_CONFIRMATION_POPUP,
Environment.DOWNLOADS);
const popupMessage = downloadRequest ? 'CANCEL_DOWNLOAD_MESSAGE' : 'CANCEL_ALL_DOWNLOAD_MESSAGE';
const confirm = await this.popoverCtrl.create({
component: SbPopoverComponent,
componentProps: {
sbPopoverHeading: this.commonUtilService.translateMessage('CANCEL_DOWNLOAD_TITLE'),
sbPopoverMainTitle: this.commonUtilService.translateMessage(popupMessage),
actionsButtons: [
{
btntext: this.commonUtilService.translateMessage('CANCEL_DOWNLOAD'),
btnClass: 'popover-color'
},
],
icon: null,
// metaInfo: this.content.contentData.name,
},
cssClass: 'sb-popover danger dw-active-downloads-popover',
});
await confirm.present();
const loader = await this.commonUtilService.getLoader();
const response = await confirm.onDidDismiss();
if (response.data) {
let valuesMap;
if (downloadRequest) {
valuesMap = {
count: 1
};
} else {
valuesMap = {
count: (await this.activeDownloadRequests$.pipe(
take(1)).toPromise()).length
};
}
this.telemetryGeneratorService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.DOWNLOAD_CANCEL_CLICKED,
Environment.DOWNLOADS,
PageId.ACTIVE_DOWNLOADS, undefined, valuesMap);
loader.present().then(() => {
return downloadRequest ?
this.downloadService.cancel(downloadRequest).toPromise() :
this.downloadService.cancelAll().toPromise();
}).then(() => {
return loader.dismiss();
});
}
}
private async presentPopupForOffline() {
this._toast = await this.popoverCtrl.create({
component: SbNoNetworkPopupComponent,
componentProps: {
sbPopoverHeading: this.commonUtilService.translateMessage('INTERNET_CONNECTIVITY_NEEDED'),
sbPopoverMessage: this.commonUtilService.translateMessage('OFFLINE_DOWNLOAD_MESSAGE'),
},
cssClass: 'sb-popover no-network',
});
await this._toast.present();
}
private async fetchStorageDestination() {
this.storageDestination = await this.storageService.getStorageDestination().toPromise();
}
private async presentPopupForLessStorageSpace() {
this._toast = await this.popoverCtrl.create({
component: SbNoNetworkPopupComponent,
componentProps: {
sbPopoverHeading: this.commonUtilService.translateMessage('INSUFFICIENT_STORAGE'),
sbPopoverMessage: this.storageDestination === StorageDestination.INTERNAL_STORAGE ?
this.commonUtilService.translateMessage('MOVE_FILES_TO_OTHER_DESTINATION', this.commonUtilService.translateMessage('SD_CARD')) :
this.commonUtilService.translateMessage('MOVE_FILES_TO_OTHER_DESTINATION',
this.commonUtilService.translateMessage('INTERNAL_MEMORY')),
},
cssClass: 'sb-popover no-network',
});
await this._toast.present();
}
private checkAvailableSpace() {
this.storageService.getStorageDestinationVolumeInfo().pipe(
tap((volumeInfo) => {
if (volumeInfo.info.availableSize < 209715200) {
this.presentPopupForLessStorageSpace();
}
})
).subscribe();
}
}
<ion-content overflow-scroll="true">
<div class="sb-view-all-container">
<div class="sb-view-all-items">
<ion-grid class="ion-no-padding" *ngIf="(activeDownloadRequests$ | async)?.length">
<ion-row>
<ion-col class="ad-pt-4" size="9">
<div class="download-page-heading">
<h6>{{'ACTIVE_DOWNLOADS' | translate}}</h6>
</div>
<div class="download-page-info">
{{'DOWNLOADING_CONTENT' | translate}} : 1/{{(activeDownloadRequests$ | async)?.length}}
</div>
</ion-col>
<ion-col class="ion-no-padding" size="3">
<div class="ion-float-right ion-text-center" role="button" (click)="cancelAllDownloads()">
<ion-icon class="download-cancel-icon" name="close"></ion-icon>
<div class="download-page-info">{{'CANCEL_ALL' | translate}}</div>
</div>
</ion-col>
</ion-row>
</ion-grid>
<div class="sb-download-all" *ngIf="!(activeDownloadRequests$ | async)?.length">
<div class="sb-view-all-title">
<span class="page-heading">{{'ACTIVE_DOWNLOADS' | translate}}</span>
</div>
</div>
</div>
<ng-container *ngIf="(activeDownloadRequests$ | async) as activeDownloadRequests">
<div class="img-mt-88" *ngIf="!activeDownloadRequests.length">
<div class="ion-text-center">
<img src="./assets/imgs/no_downloads.png" alt="no_downloads">
</div>
<div class="ion-text-center">
<p>
<strong>{{ 'NO_DOWNLOADS' | translate }}</strong>
</p>
<p>{{ 'NO_DOWNLOADS_INFO' | translate }}</p>
</div>
</div>
<div *ngIf="activeDownloadRequests.length"
class="sb-card-container sb-card-view-all-container ad-pb-88 ad-no-box-shadow">
<div *ngFor="let activeDownload of activeDownloadRequests; let i = index">
<ng-container *ngIf="getContentDownloadProgress(activeDownload.identifier) as downloadProgress; else pending">
<ion-row class="ad-border-bottom-1">
<ion-col class="ion-no-padding" size="10">
<div class="sb-card">
<div start class="img-container">
<img [src]="commonUtilService.convertFileSrc(activeDownload.contentMeta.appIcon) || defaultImg"
alt="icon">
</div>
<div end class="sb-card-details">
<div class="title">{{activeDownload?.contentMeta.name}}</div>
<div class="info grade_ellipsis">
<span class="class">{{activeDownload.contentMeta.subject}}</span>
<span class="separator-dot"></span>
<span class="subject">{{activeDownload.contentMeta.gradeLevel?.join(', ')}}</span>
</div>
<div class="info">
<ng-container *ngIf="!downloadProgress || downloadProgress === -1">
{{ 'WAITING_TO_DOWNLOAD' | translate }}
</ng-container>
<ng-container *ngIf="downloadProgress >= 0 && downloadProgress < 100">
{{((downloadProgress / 100) * activeDownload.contentMeta.size) | fileSize}} /
{{activeDownload.contentMeta.size | fileSize}}
</ng-container>
<ng-container *ngIf="downloadProgress === 100">
{{ 'IMPORTING' | translate }}
</ng-container>
</div>
</div>
</div>
<div class="popover-progress-container ad-ml-8" *ngIf="downloadProgress >= 0 && downloadProgress < 100">
<div [ngStyle]="{'left': downloadProgress + '%'}" class="progress-highlight">
</div>
</div>
</ion-col>
<ion-col size="2">
<button *ngIf="downloadProgress !== 100"
class="action-btn float-end delete mr-8 ad-action-btn ion-no-margin ion-margin-right"
(click)="cancelDownload(activeDownload)">
{{'CANCEL' | translate}}
</button>
</ion-col>
</ion-row>
</ng-container>
<ng-template #pending>
<ion-row class="ad-border-bottom-1">
<ion-col class="ion-no-padding" size="10">
<div class="sb-card">
<div start class="img-container">
<img [src]="commonUtilService.convertFileSrc(activeDownload.contentMeta.appIcon) || defaultImg"
alt="icon">
</div>
<div end class="sb-card-details">
<div class="title">{{activeDownload?.contentMeta.name}}</div>
<div class="info grade_ellipsis">
<span class="class">{{activeDownload.contentMeta.subject}}</span>
<span class="separator-dot"></span>
<span class="subject">{{activeDownload.contentMeta.gradeLevel?.join(', ')}}</span>
</div>
<div class="info">
{{ 'WAITING_TO_DOWNLOAD' | translate }}
</div>
</div>
</div>
</ion-col>
<ion-col size="2">
<button class="action-btn float-end delete mr-8 ad-action-btn ion-no-margin ion-margin-right"
(click)="cancelDownload(activeDownload)">
{{'CANCEL' | translate}}
</button>
</ion-col>
</ion-row>
</ng-template>
</div>
</div>
</ng-container>
</div>
</ion-content>
./active-downloads.page.scss
@import "src/assets/styles/base/_variables.scss";
@import "src/assets/styles/_custom-mixins.scss";
@import "src/assets/styles/_variables.scss";
// :host {
.download-page-heading{
color: map-get($colors, white);
font-size: $font-size-base + 0.125;
}
.download-page-info{
color: map-get($colors, white);
font-size: $font-size-base - 0.125;
}
.download-cancel-icon{
font-size: $font-size-base * 2;
color: map-get($colors, white);
}
.ad-pt-4{
padding-top: $base-block-space * 0.5 !important;
}
.img-mt-88{
margin-top: $base-block-space * 11;
}
.ad-pb-88{
padding-bottom: $base-block-space * 11;
}
.ad-ml-8{
margin-left: $base-block-space;
}
.ad-border-bottom-1{
border-bottom: 1px solid map-get($colors, light_grayish_red);
}
.ad-no-box-shadow{
box-shadow: none;
}
.ad-action-btn{
position: absolute;
bottom: 0;
border-radius: 0px !important;
box-shadow: none !important;
height: ($base-block-space * 3);
border-top-left-radius: 4px !important;
border-top-right-radius: 4px !important;
text-transform: capitalize;
// @include margin(0, 0, 0, ($base-block-space * 1));
@include padding(null, ($base-block-space * 1));
background-color: $danger-color;
color: $white-color;
.button-inner {
font-size: ($font-size-base - 0.125);
line-height: 1.063rem;
font-weight: 100;
font-style: normal;
font-stretch: normal;
text-align: center;
color:$white-color;
}
}
.popover-progress-container{
height: ($base-block-space * 0.5);
background-color: $primary-800;
position: relative;
.progress-highlight{
position:absolute;
background:$primary-200;
left:20%;
right:0;
top:0;
bottom:0
}
}
// }