1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00
pigallery2/frontend/app/gallery/thumbnailLoader.service.ts

204 lines
5.3 KiB
TypeScript
Raw Normal View History

2018-03-31 03:30:30 +08:00
import {Injectable} from '@angular/core';
import {GalleryCacheService} from './cache.gallery.service';
2018-11-05 02:28:32 +08:00
import {Media} from './Media';
import {MediaIcon} from './MediaIcon';
2018-03-31 03:30:30 +08:00
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Config} from '../../../common/config/public/Config';
2018-11-05 02:28:32 +08:00
import {MediaDTO} from '../../../common/entities/MediaDTO';
2016-06-17 06:05:31 +08:00
2017-07-26 05:40:07 +08:00
export enum ThumbnailLoadingPriority {
extraHigh = 4, high = 3, medium = 2, low = 1
}
2016-06-17 06:05:31 +08:00
@Injectable()
export class ThumbnailLoaderService {
que: Array<ThumbnailTask> = [];
runningRequests = 0;
2016-06-17 06:05:31 +08:00
2017-06-28 05:00:28 +08:00
constructor(private galleryCacheService: GalleryCacheService) {
}
2016-06-17 06:05:31 +08:00
run = () => {
if (this.que.length === 0 || this.runningRequests >= Config.Client.Thumbnail.concurrentThumbnailGenerations) {
return;
}
const task = this.getNextTask();
if (task === null) {
return;
}
this.runningRequests++;
task.taskEntities.forEach(te => te.listener.onStartedLoading());
task.inProgress = true;
const curImg = new Image();
curImg.onload = () => {
task.onLoaded();
2018-11-05 02:28:32 +08:00
this.galleryCacheService.mediaUpdated(task.media);
task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onLoad());
this.taskReady(task);
this.runningRequests--;
this.run();
};
curImg.onerror = (error) => {
task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onError(error));
this.taskReady(task);
this.runningRequests--;
this.run();
};
curImg.src = task.path;
};
2016-06-24 04:25:16 +08:00
removeTask(taskEntry: ThumbnailTaskEntity) {
const index = taskEntry.parentTask.taskEntities.indexOf(taskEntry);
if (index === -1) {
2018-03-31 03:30:30 +08:00
throw new Error('ThumbnailTaskEntity not exist on Task');
2017-06-28 05:00:28 +08:00
}
taskEntry.parentTask.taskEntities.splice(index, 1);
if (taskEntry.parentTask.taskEntities.length === 0
&& taskEntry.parentTask.inProgress === false) {
const i = this.que.indexOf(taskEntry.parentTask);
if (i === -1) {
2018-03-31 03:30:30 +08:00
throw new Error('ThumbnailTask not exist');
}
2017-06-28 05:00:28 +08:00
this.que.splice(i, 1);
}
}
2018-11-05 02:28:32 +08:00
loadIcon(photo: MediaIcon, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
2017-06-28 05:00:28 +08:00
let thTask: ThumbnailTask = null;
// is image already qued?
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].path === photo.getIconPath()) {
2017-06-28 05:00:28 +08:00
thTask = this.que[i];
break;
}
}
2017-06-28 05:00:28 +08:00
if (thTask == null) {
thTask = {
2018-11-05 02:28:32 +08:00
media: photo.media,
inProgress: false,
2017-06-28 05:00:28 +08:00
taskEntities: [],
onLoaded: () => {
photo.iconLoaded();
},
path: photo.getIconPath()
2017-06-28 05:00:28 +08:00
};
this.que.push(thTask);
}
const thumbnailTaskEntity = {priority: priority, listener: listener, parentTask: thTask};
2017-06-28 05:00:28 +08:00
thTask.taskEntities.push(thumbnailTaskEntity);
if (thTask.inProgress === true) {
2017-06-28 05:00:28 +08:00
listener.onStartedLoading();
}
2017-06-28 05:00:28 +08:00
2017-06-11 04:56:23 +08:00
setTimeout(this.run, 0);
return thumbnailTaskEntity;
}
2018-11-05 02:28:32 +08:00
loadImage(media: Media, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
2017-06-28 05:00:28 +08:00
let thTask: ThumbnailTask = null;
// is image already qued?
for (let i = 0; i < this.que.length; i++) {
2018-11-05 02:28:32 +08:00
if (this.que[i].path === media.getThumbnailPath()) {
2017-06-28 05:00:28 +08:00
thTask = this.que[i];
break;
}
}
2017-06-28 05:00:28 +08:00
if (thTask == null) {
thTask = {
2018-11-05 02:28:32 +08:00
media: media.media,
inProgress: false,
2017-06-28 05:00:28 +08:00
taskEntities: [],
onLoaded: () => {
2018-11-05 02:28:32 +08:00
media.thumbnailLoaded();
},
2018-11-05 02:28:32 +08:00
path: media.getThumbnailPath()
2017-06-28 05:00:28 +08:00
};
this.que.push(thTask);
}
2017-06-28 05:00:28 +08:00
const thumbnailTaskEntity = {priority: priority, listener: listener, parentTask: thTask};
2017-06-28 05:00:28 +08:00
// add to poolTask
2017-06-28 05:00:28 +08:00
thTask.taskEntities.push(thumbnailTaskEntity);
if (thTask.inProgress === true) {
2017-06-28 05:00:28 +08:00
listener.onStartedLoading();
}
2017-06-11 04:56:23 +08:00
setTimeout(this.run, 0);
return thumbnailTaskEntity;
}
private getNextTask(): ThumbnailTask {
if (this.que.length === 0) {
return null;
}
2017-07-26 05:40:07 +08:00
let highestPriority: ThumbnailTask = null;
let currentPriority: ThumbnailLoadingPriority = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < this.que.length; i++) {
for (let j = 0; j < this.que[i].taskEntities.length; j++) {
if (this.que[i].inProgress === false) {
2017-07-26 05:40:07 +08:00
if (highestPriority == null || currentPriority < this.que[i].taskEntities[j].priority) {
highestPriority = this.que[i];
currentPriority = this.que[i].taskEntities[j].priority;
if (currentPriority === ThumbnailLoadingPriority.extraHigh) {
2017-07-26 05:40:07 +08:00
return highestPriority;
}
}
}
}
}
2016-06-17 06:05:31 +08:00
2017-07-26 05:40:07 +08:00
return highestPriority;
}
private taskReady(task: ThumbnailTask) {
const i = this.que.indexOf(task);
if (i === -1) {
if (task.taskEntities.length !== 0) {
2018-03-31 03:30:30 +08:00
console.error('ThumbnailLoader: can\'t find poolTask to remove');
}
return;
}
this.que.splice(i, 1);
}
}
2016-06-17 06:05:31 +08:00
export interface ThumbnailLoadingListener {
onStartedLoading: () => void;
onLoad: () => void;
onError: (error: any) => void;
}
export interface ThumbnailTaskEntity {
priority: ThumbnailLoadingPriority;
listener: ThumbnailLoadingListener;
2017-06-28 05:00:28 +08:00
parentTask: ThumbnailTask;
2016-06-17 06:05:31 +08:00
}
interface ThumbnailTask {
2018-11-05 02:28:32 +08:00
media: MediaDTO;
inProgress: boolean;
taskEntities: Array<ThumbnailTaskEntity>;
path: string;
onLoaded: Function;
2016-06-17 06:05:31 +08:00
}