Skip to content

Commit

Permalink
Add improvements on the Download Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
apiweb committed Aug 2, 2023
1 parent e57e974 commit 754a63a
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 2 deletions.
103 changes: 102 additions & 1 deletion src/web/lib/hakuneko/frontend@classic-dark/jobs.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@
.hide {
display: none;
}
.buttonDisabled {
cursor: default;
pointer-events: none;
color: gray;
}
.remove-button {
cursor: pointer;
text-align: center;
padding: 0.25em;
}
.remove-button i {
color: var(--job-list-button-failed-color);
}

.remove-button:hover i {
color: var(--job-list-button-completed-color);
}

</style>
<div class$="list [[ getListClass(popupVisibility) ]]">
<table cellpadding="0">
Expand All @@ -79,6 +97,9 @@
<td class="cell">[[ item.labels.connector ]]</td>
<td class="cell">[[ item.labels.manga ]]</td>
<td class="cell">[[ item.labels.chapter ]]</td>
<td class="remove-button" on-click="removeFromQueue">
<i class="fas fa-times"></i>
</td>
<td class="progress" style$="background: linear-gradient(90deg, var(--job-list-progress-color) [[ item.progress ]]%, var(--job-list-progress-background-color) 0%);"></td>
</tr>
</template>
Expand All @@ -88,7 +109,18 @@
<div class="expander">
<i class$="fas [[ getButtonClass(popupVisibility) ]] button" title="Toggle download list" on-click="toggleJobList"></i>
</div>
<div class="status">[[ jobList.length ]] Download(s)</div>
<div class="status">
<span>[[ jobList.length ]] Download(s)</span>
<span>
<i class$="fas fa-fw button [[ getPlayPauseClass(queuePaused) ]] [[ isQueueEmpty(jobList.length) ]]"
title$="[[ getPlayPauseTooltip(queuePaused) ]]"
on-click="playPauseQueue">
</i>
</span>
<span>
<i class$="fas fa-times remove-button [[ isQueueEmpty(jobList.length) ]]" title="Clear Job List" on-click="clearJobList"></i>
</span>
</div>
</div>
</template>

Expand All @@ -113,6 +145,10 @@
notify: true, // enable upward data flow,
//readOnly: true, // prevent downward data flow
//observer: 'onSelectedMangaChanged'
},
queuePaused: {
type: Boolean,
value: false,
}
};
}
Expand All @@ -132,6 +168,13 @@
this.ipc.on( 'close', this.onClose.bind( this ) );
}

/**
*
*/
isQueueEmpty(length) {
return length < 1 ? 'buttonDisabled' : '';
}

/**
*
*/
Expand Down Expand Up @@ -178,6 +221,41 @@
}
}

/**
*
*/
getPlayPauseTooltip( status ) {
if ( status ) {
return 'Resume download queue';
} else {
return 'Pause download queue';
}
}

/**
*
*/
getPlayPauseClass( status ) {
if ( status ) {
return 'fa-play';
} else {
return 'fa-pause';
}
}

/**
*
*/
playPauseQueue() {
if(this.queuePaused) {
Engine.DownloadManager.startQueue();
this.queuePaused = false;
} else {
Engine.DownloadManager.pauseQueue();
this.queuePaused = true;
}
}

/**
*
*/
Expand All @@ -197,6 +275,29 @@
}
}

/**
*
*/
removeFromQueue(e) {
const index = e.model.index;
const job = this.jobList[index];
if (job) {
Engine.DownloadManager.removeFromQueue(job);
this.splice('jobList', index, 1);
}
}

/**
*
*/
async clearJobList() {
if(await confirm( 'Do you really want to clear the download queue?' )) {
Engine.DownloadManager.clearQueue();
this.splice('jobList', 0, this.jobList.length);
this.queuePaused = false;
}
}

/**
*
*/
Expand Down
103 changes: 102 additions & 1 deletion src/web/lib/hakuneko/frontend@classic-light/jobs.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@
.hide {
display: none;
}
.buttonDisabled {
cursor: default;
pointer-events: none;
color: gray;
}
.remove-button {
cursor: pointer;
text-align: center;
padding: 0.25em;
}
.remove-button i {
color: var(--job-list-button-failed-color);
}

.remove-button:hover i {
color: var(--job-list-button-completed-color);
}

</style>
<div class$="list [[ getListClass(popupVisibility) ]]">
<table cellpadding="0">
Expand All @@ -79,6 +97,9 @@
<td class="cell">[[ item.labels.connector ]]</td>
<td class="cell">[[ item.labels.manga ]]</td>
<td class="cell">[[ item.labels.chapter ]]</td>
<td class="remove-button" on-click="removeFromQueue">
<i class="fas fa-times"></i>
</td>
<td class="progress" style$="background: linear-gradient(90deg, var(--job-list-progress-color) [[ item.progress ]]%, var(--job-list-progress-background-color) 0%);"></td>
</tr>
</template>
Expand All @@ -88,7 +109,18 @@
<div class="expander">
<i class$="fas [[ getButtonClass(popupVisibility) ]] button" title="Toggle download list" on-click="toggleJobList"></i>
</div>
<div class="status">[[ jobList.length ]] Download(s)</div>
<div class="status">
<span>[[ jobList.length ]] Download(s)</span>
<span>
<i class$="fas fa-fw button [[ getPlayPauseClass(queuePaused) ]] [[ isQueueEmpty(jobList.length) ]]"
title$="[[ getPlayPauseTooltip(queuePaused) ]]"
on-click="playPauseQueue">
</i>
</span>
<span>
<i class$="fas fa-times remove-button [[ isQueueEmpty(jobList.length) ]]" title="Clear Job List" on-click="clearJobList"></i>
</span>
</div>
</div>
</template>

Expand All @@ -113,6 +145,10 @@
notify: true, // enable upward data flow,
//readOnly: true, // prevent downward data flow
//observer: 'onSelectedMangaChanged'
},
queuePaused: {
type: Boolean,
value: false,
}
};
}
Expand All @@ -132,6 +168,13 @@
this.ipc.on( 'close', this.onClose.bind( this ) );
}

/**
*
*/
isQueueEmpty(length) {
return length < 1 ? 'buttonDisabled' : '';
}

/**
*
*/
Expand Down Expand Up @@ -178,6 +221,41 @@
}
}

/**
*
*/
getPlayPauseTooltip( status ) {
if ( status ) {
return 'Resume download queue';
} else {
return 'Pause download queue';
}
}

/**
*
*/
getPlayPauseClass( status ) {
if ( status ) {
return 'fa-play';
} else {
return 'fa-pause';
}
}

/**
*
*/
playPauseQueue() {
if(this.queuePaused) {
Engine.DownloadManager.startQueue();
this.queuePaused = false;
} else {
Engine.DownloadManager.pauseQueue();
this.queuePaused = true;
}
}

/**
*
*/
Expand All @@ -197,6 +275,29 @@
}
}

/**
*
*/
removeFromQueue(e) {
const index = e.model.index;
const job = this.jobList[index];
if (job) {
Engine.DownloadManager.removeFromQueue(job);
this.splice('jobList', index, 1);
}
}

/**
*
*/
async clearJobList() {
if(await confirm( 'Do you really want to clear the download queue?' )) {
Engine.DownloadManager.clearQueue();
this.splice('jobList', 0, this.jobList.length);
this.queuePaused = false;
}
}

/**
*
*/
Expand Down
1 change: 1 addition & 0 deletions src/web/mjs/engine/DownloadJob.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class DownloadJob extends EventTarget {
// TODO: initialize requestOptions.headers = new Headers() if not set
this.chunkSize = 8388608; // 8 MB
this.throttle = chapter.manga.connector.config && chapter.manga.connector.config['throttle'] ? chapter.manga.connector.config['throttle'].value : 0;
this.initialStatus = chapter.status;
this.status = undefined;
this.progress = 0;
this.errors = [];
Expand Down
56 changes: 56 additions & 0 deletions src/web/mjs/engine/DownloadManager.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default class DownloadManager extends EventTarget {
super();
this.queue = [];
this.worker = setInterval( this.processQueue.bind( this ), 250 );
this.queuePaused = false;
}

/**
Expand All @@ -36,12 +37,53 @@ export default class DownloadManager extends EventTarget {
}
}

/**
* Returns true if the download queue is paused.
*/
isQueuePaused() {
return this.queuePaused;
}

/**
* Pause the download queue processing.
*/
pauseQueue() {
this.queuePaused = true;
}

/**
* Start the download queue processing if it was paused.
*/
startQueue() {
this.queuePaused = false;
this.processQueue(); // Start processing the queue again
}

/**
* Remove a job from the download queue.
* @param job
*/
removeFromQueue(job) {
if (!job) return;

const connectorID = job.chapter.manga.connector.id;
const index = this.queue[connectorID].indexOf(job);
if (index !== -1) {
this.queue[connectorID].splice(index, 1);
job.setStatus(job.initialStatus);
}
}

/**
*
*/
processQueue() {
// find a connector in queue that has downloads available and is not locked
for( let connectorID in this.queue ) {
if (this.isQueuePaused()) {
break;
}

// check if queue is not empty, there are no active jobs for this connector and the connector is not locked internally through other requests
if( this.queue[connectorID].length > 0 && this.queue[connectorID].activeCount < 1 && !this.queue[connectorID][0].chapter.manga.connector.isLocked ) {
this.queue[connectorID].activeCount++;
Expand All @@ -52,4 +94,18 @@ export default class DownloadManager extends EventTarget {
}
}
}

/**
* Clear the download queue.
*/
clearQueue() {
for (let connectorID in this.queue) {
const jobs = this.queue[connectorID];
for (let i = jobs.length - 1; i >= 0; i--) {
const job = jobs[i];
job.setStatus(job.initialStatus);
jobs.splice(i, 1);
}
}
}
}

0 comments on commit 754a63a

Please sign in to comment.