mirror of
https://github.com/Carve/qbittorrent-webui-cjratliff.com.git
synced 2025-03-01 16:11:06 +01:00
767 lines
23 KiB
JavaScript
767 lines
23 KiB
JavaScript
/*
|
|
* Bittorrent Client using Qt and libtorrent.
|
|
* Copyright (C) 2009 Christophe Dumez <chris@qbittorrent.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* In addition, as a special exception, the copyright holders give permission to
|
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
|
* and distribute the linked executables. You must obey the GNU General Public
|
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
|
* modify file(s), you may extend this exception to your version of the file(s),
|
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
'use strict'
|
|
|
|
if (window.qBittorrent === undefined) {
|
|
window.qBittorrent = {}
|
|
}
|
|
|
|
window.qBittorrent.ContextMenu = (function () {
|
|
const exports = function () {
|
|
return {
|
|
ContextMenu: ContextMenu,
|
|
TorrentsTableContextMenu: TorrentsTableContextMenu,
|
|
CategoriesFilterContextMenu: CategoriesFilterContextMenu,
|
|
TagsFilterContextMenu: TagsFilterContextMenu,
|
|
SearchPluginsTableContextMenu: SearchPluginsTableContextMenu,
|
|
RssFeedContextMenu: RssFeedContextMenu,
|
|
RssArticleContextMenu: RssArticleContextMenu,
|
|
RssDownloaderRuleContextMenu: RssDownloaderRuleContextMenu,
|
|
}
|
|
}
|
|
|
|
let lastShownContextMenu = null
|
|
const ContextMenu = new Class({
|
|
//implements
|
|
Implements: [Options, Events],
|
|
|
|
//options
|
|
options: {
|
|
actions: {},
|
|
menu: 'menu_id',
|
|
stopEvent: true,
|
|
targets: 'body',
|
|
offsets: {
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
onShow: $empty,
|
|
onHide: $empty,
|
|
onClick: $empty,
|
|
fadeSpeed: 200,
|
|
touchTimer: 600,
|
|
},
|
|
|
|
//initialization
|
|
initialize: function (options) {
|
|
//set options
|
|
this.setOptions(options)
|
|
|
|
//option diffs menu
|
|
this.menu = $(this.options.menu)
|
|
this.targets = $$(this.options.targets)
|
|
|
|
//fx
|
|
this.fx = new Fx.Tween(this.menu, {
|
|
property: 'opacity',
|
|
duration: this.options.fadeSpeed,
|
|
onComplete: function () {
|
|
if (this.getStyle('opacity')) {
|
|
this.setStyle('visibility', 'visible')
|
|
} else {
|
|
this.setStyle('visibility', 'hidden')
|
|
}
|
|
}.bind(this.menu),
|
|
})
|
|
|
|
//hide and begin the listener
|
|
this.hide().startListener()
|
|
|
|
//hide the menu
|
|
this.menu.setStyles({
|
|
position: 'absolute',
|
|
top: '-900000px',
|
|
display: 'block',
|
|
})
|
|
},
|
|
|
|
adjustMenuPosition: function (e) {
|
|
this.updateMenuItems()
|
|
|
|
const scrollableMenuMaxHeight =
|
|
document.documentElement.clientHeight * 0.75
|
|
|
|
if (this.menu.hasClass('scrollableMenu'))
|
|
this.menu.setStyle('max-height', scrollableMenuMaxHeight)
|
|
|
|
// draw the menu off-screen to know the menu dimensions
|
|
this.menu.setStyles({
|
|
left: '-999em',
|
|
top: '-999em',
|
|
})
|
|
|
|
// position the menu
|
|
let xPosMenu = e.page.x + this.options.offsets.x
|
|
let yPosMenu = e.page.y + this.options.offsets.y
|
|
if (
|
|
xPosMenu + this.menu.offsetWidth >
|
|
document.documentElement.clientWidth
|
|
)
|
|
xPosMenu -= this.menu.offsetWidth
|
|
if (
|
|
yPosMenu + this.menu.offsetHeight >
|
|
document.documentElement.clientHeight
|
|
)
|
|
yPosMenu =
|
|
document.documentElement.clientHeight - this.menu.offsetHeight
|
|
if (xPosMenu < 0) xPosMenu = 0
|
|
if (yPosMenu < 0) yPosMenu = 0
|
|
this.menu.setStyles({
|
|
left: xPosMenu,
|
|
top: yPosMenu,
|
|
position: 'absolute',
|
|
'z-index': '2000',
|
|
})
|
|
|
|
// position the sub-menu
|
|
const uls = this.menu.getElementsByTagName('ul')
|
|
for (let i = 0; i < uls.length; ++i) {
|
|
const ul = uls[i]
|
|
if (ul.hasClass('scrollableMenu'))
|
|
ul.setStyle('max-height', scrollableMenuMaxHeight)
|
|
const rectParent = ul.parentNode.getBoundingClientRect()
|
|
const xPosOrigin = rectParent.left
|
|
const yPosOrigin = rectParent.bottom
|
|
let xPos = xPosOrigin + rectParent.width - 1
|
|
let yPos = yPosOrigin - rectParent.height - 1
|
|
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
|
xPos -= ul.offsetWidth + rectParent.width - 2
|
|
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
|
yPos = document.documentElement.clientHeight - ul.offsetHeight
|
|
if (xPos < 0) xPos = 0
|
|
if (yPos < 0) yPos = 0
|
|
ul.setStyles({
|
|
'margin-left': xPos - xPosOrigin,
|
|
'margin-top': yPos - yPosOrigin,
|
|
})
|
|
}
|
|
},
|
|
|
|
setupEventListeners: function (elem) {
|
|
elem.addEvent(
|
|
'contextmenu',
|
|
function (e) {
|
|
this.triggerMenu(e, elem)
|
|
}.bind(this)
|
|
)
|
|
elem.addEvent(
|
|
'click',
|
|
function (e) {
|
|
this.hide()
|
|
}.bind(this)
|
|
)
|
|
|
|
elem.addEvent(
|
|
'touchstart',
|
|
function (e) {
|
|
e.preventDefault()
|
|
clearTimeout(this.touchstartTimer)
|
|
this.hide()
|
|
|
|
const touchstartEvent = e
|
|
this.touchstartTimer = setTimeout(
|
|
function () {
|
|
this.triggerMenu(touchstartEvent, elem)
|
|
}.bind(this),
|
|
this.options.touchTimer
|
|
)
|
|
}.bind(this)
|
|
)
|
|
elem.addEvent(
|
|
'touchend',
|
|
function (e) {
|
|
e.preventDefault()
|
|
clearTimeout(this.touchstartTimer)
|
|
}.bind(this)
|
|
)
|
|
},
|
|
|
|
addTarget: function (t) {
|
|
this.targets[this.targets.length] = t
|
|
this.setupEventListeners(t)
|
|
},
|
|
|
|
triggerMenu: function (e, el) {
|
|
if (this.options.disabled) return
|
|
|
|
//prevent default, if told to
|
|
if (this.options.stopEvent) {
|
|
e.stop()
|
|
}
|
|
//record this as the trigger
|
|
this.options.element = $(el)
|
|
this.adjustMenuPosition(e)
|
|
//show the menu
|
|
this.show()
|
|
},
|
|
|
|
//get things started
|
|
startListener: function () {
|
|
/* all elements */
|
|
this.targets.each(
|
|
function (el) {
|
|
this.setupEventListeners(el)
|
|
}.bind(this),
|
|
this
|
|
)
|
|
|
|
/* menu items */
|
|
this.menu.getElements('a').each(function (item) {
|
|
item.addEvent(
|
|
'click',
|
|
function (e) {
|
|
e.preventDefault()
|
|
if (!item.hasClass('disabled')) {
|
|
this.execute(
|
|
item.get('href').split('#')[1],
|
|
$(this.options.element)
|
|
)
|
|
this.fireEvent('click', [item, e])
|
|
}
|
|
}.bind(this)
|
|
)
|
|
}, this)
|
|
|
|
//hide on body click
|
|
$(document.body).addEvent(
|
|
'click',
|
|
function () {
|
|
this.hide()
|
|
}.bind(this)
|
|
)
|
|
},
|
|
|
|
updateMenuItems: function () {},
|
|
|
|
//show menu
|
|
show: function (trigger) {
|
|
if (lastShownContextMenu && lastShownContextMenu != this)
|
|
lastShownContextMenu.hide()
|
|
this.fx.start(1)
|
|
this.fireEvent('show')
|
|
this.shown = true
|
|
lastShownContextMenu = this
|
|
return this
|
|
},
|
|
|
|
//hide the menu
|
|
hide: function (trigger) {
|
|
if (this.shown) {
|
|
this.fx.start(0)
|
|
//this.menu.fade('out');
|
|
this.fireEvent('hide')
|
|
this.shown = false
|
|
}
|
|
return this
|
|
},
|
|
|
|
setItemChecked: function (item, checked) {
|
|
if (this.menu.getElement('a[href$=' + item + ']')) {
|
|
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
|
checked ? '1' : '0'
|
|
}
|
|
return this
|
|
},
|
|
|
|
getItemChecked: function (item) {
|
|
if (this.menu.getElement('a[href$=' + item + ']')) {
|
|
return (
|
|
'0' !=
|
|
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity
|
|
)
|
|
} else {
|
|
return '0'
|
|
}
|
|
},
|
|
|
|
//hide an item
|
|
hideItem: function (item) {
|
|
if (this.menu.getElement('a[href$=' + item + ']')) {
|
|
this.menu
|
|
.getElement('a[href$=' + item + ']')
|
|
.parentNode.addClass('invisible')
|
|
}
|
|
return this
|
|
},
|
|
|
|
//show an item
|
|
showItem: function (item) {
|
|
if (this.menu.getElement('a[href$=' + item + ']')) {
|
|
this.menu
|
|
.getElement('a[href$=' + item + ']')
|
|
.parentNode.removeClass('invisible')
|
|
}
|
|
return this
|
|
},
|
|
|
|
//disable the entire menu
|
|
disable: function () {
|
|
this.options.disabled = true
|
|
return this
|
|
},
|
|
|
|
//enable the entire menu
|
|
enable: function () {
|
|
this.options.disabled = false
|
|
return this
|
|
},
|
|
|
|
//execute an action
|
|
execute: function (action, element) {
|
|
if (this.options.actions[action]) {
|
|
this.options.actions[action](element, this, action)
|
|
}
|
|
return this
|
|
},
|
|
})
|
|
|
|
const TorrentsTableContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
|
|
updateMenuItems: function () {
|
|
let all_are_seq_dl = true
|
|
let there_are_seq_dl = false
|
|
let all_are_f_l_piece_prio = true
|
|
let there_are_f_l_piece_prio = false
|
|
let all_are_downloaded = true
|
|
let all_are_paused = true
|
|
let there_are_paused = false
|
|
let all_are_force_start = true
|
|
let there_are_force_start = false
|
|
let all_are_super_seeding = true
|
|
let all_are_auto_tmm = true
|
|
let there_are_auto_tmm = false
|
|
const tagsSelectionState = Object.clone(tagList)
|
|
|
|
const h = torrentsTable.selectedRowsIds()
|
|
h.each(function (item, index) {
|
|
const data = torrentsTable.rows.get(item).full_data
|
|
|
|
if (data['seq_dl'] !== true) all_are_seq_dl = false
|
|
else there_are_seq_dl = true
|
|
|
|
if (data['f_l_piece_prio'] !== true) all_are_f_l_piece_prio = false
|
|
else there_are_f_l_piece_prio = true
|
|
|
|
if (data['progress'] != 1.0)
|
|
// not downloaded
|
|
all_are_downloaded = false
|
|
else if (data['super_seeding'] !== true) all_are_super_seeding = false
|
|
|
|
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
|
|
all_are_paused = false
|
|
else there_are_paused = true
|
|
|
|
if (data['force_start'] !== true) all_are_force_start = false
|
|
else there_are_force_start = true
|
|
|
|
if (data['auto_tmm'] === true) there_are_auto_tmm = true
|
|
else all_are_auto_tmm = false
|
|
|
|
const torrentTags = data['tags'].split(', ')
|
|
for (const key in tagsSelectionState) {
|
|
const tag = tagsSelectionState[key]
|
|
const tagExists = torrentTags.contains(tag.name)
|
|
if (tag.checked !== undefined && tag.checked != tagExists)
|
|
tag.indeterminate = true
|
|
if (tag.checked === undefined) tag.checked = tagExists
|
|
else tag.checked = tag.checked && tagExists
|
|
}
|
|
})
|
|
|
|
let show_seq_dl = true
|
|
|
|
// hide renameFiles when more than 1 torrent is selected
|
|
if (h.length == 1) {
|
|
const data = torrentsTable.rows.get(h[0]).full_data
|
|
let metadata_downloaded = !(
|
|
data['state'] == 'metaDL' ||
|
|
data['state'] == 'forcedMetaDL' ||
|
|
data['total_size'] == -1
|
|
)
|
|
|
|
// hide renameFiles when metadata hasn't been downloaded yet
|
|
metadata_downloaded
|
|
? this.showItem('renameFiles')
|
|
: this.hideItem('renameFiles')
|
|
} else this.hideItem('renameFiles')
|
|
|
|
if (!all_are_seq_dl && there_are_seq_dl) show_seq_dl = false
|
|
|
|
let show_f_l_piece_prio = true
|
|
|
|
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
|
|
show_f_l_piece_prio = false
|
|
|
|
if (all_are_downloaded) {
|
|
this.hideItem('downloadLimit')
|
|
this.menu
|
|
.getElement('a[href$=uploadLimit]')
|
|
.parentNode.addClass('separator')
|
|
this.hideItem('sequentialDownload')
|
|
this.hideItem('firstLastPiecePrio')
|
|
this.showItem('superSeeding')
|
|
this.setItemChecked('superSeeding', all_are_super_seeding)
|
|
} else {
|
|
if (!show_seq_dl && show_f_l_piece_prio)
|
|
this.menu
|
|
.getElement('a[href$=firstLastPiecePrio]')
|
|
.parentNode.addClass('separator')
|
|
else
|
|
this.menu
|
|
.getElement('a[href$=firstLastPiecePrio]')
|
|
.parentNode.removeClass('separator')
|
|
|
|
if (show_seq_dl) this.showItem('sequentialDownload')
|
|
else this.hideItem('sequentialDownload')
|
|
|
|
if (show_f_l_piece_prio) this.showItem('firstLastPiecePrio')
|
|
else this.hideItem('firstLastPiecePrio')
|
|
|
|
this.setItemChecked('sequentialDownload', all_are_seq_dl)
|
|
this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio)
|
|
|
|
this.showItem('downloadLimit')
|
|
this.menu
|
|
.getElement('a[href$=uploadLimit]')
|
|
.parentNode.removeClass('separator')
|
|
this.hideItem('superSeeding')
|
|
}
|
|
|
|
this.showItem('start')
|
|
this.showItem('pause')
|
|
this.showItem('forceStart')
|
|
if (all_are_paused) this.hideItem('pause')
|
|
else if (all_are_force_start) this.hideItem('forceStart')
|
|
else if (!there_are_paused && !there_are_force_start)
|
|
this.hideItem('start')
|
|
|
|
if (!all_are_auto_tmm && there_are_auto_tmm) {
|
|
this.hideItem('autoTorrentManagement')
|
|
} else {
|
|
this.showItem('autoTorrentManagement')
|
|
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm)
|
|
}
|
|
|
|
const contextTagList = $('contextTagList')
|
|
for (const tagHash in tagList) {
|
|
const checkbox = contextTagList.getElement(
|
|
'a[href=#Tag/' + tagHash + '] input[type=checkbox]'
|
|
)
|
|
const checkboxState = tagsSelectionState[tagHash]
|
|
checkbox.indeterminate = checkboxState.indeterminate
|
|
checkbox.checked = checkboxState.checked
|
|
}
|
|
},
|
|
|
|
updateCategoriesSubMenu: function (category_list) {
|
|
const categoryList = $('contextCategoryList')
|
|
categoryList.empty()
|
|
categoryList.appendChild(
|
|
new Element('li', {
|
|
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/list-add.svg" alt="New..."/>New...</a>',
|
|
})
|
|
)
|
|
categoryList.appendChild(
|
|
new Element('li', {
|
|
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/edit-clear.svg" alt="Reset"/>Reset</a>',
|
|
})
|
|
)
|
|
|
|
const sortedCategories = []
|
|
Object.each(category_list, function (category) {
|
|
sortedCategories.push(category.name)
|
|
})
|
|
sortedCategories.sort()
|
|
|
|
let first = true
|
|
Object.each(sortedCategories, function (categoryName) {
|
|
const categoryHash = genHash(categoryName)
|
|
const el = new Element('li', {
|
|
html:
|
|
'<a href="javascript:torrentSetCategoryFN(\'' +
|
|
categoryHash +
|
|
'\');"><img src="images/view-categories.svg"/> ' +
|
|
window.qBittorrent.Misc.escapeHtml(categoryName) +
|
|
'</a>',
|
|
})
|
|
if (first) {
|
|
el.addClass('separator')
|
|
first = false
|
|
}
|
|
categoryList.appendChild(el)
|
|
})
|
|
},
|
|
|
|
updateTagsSubMenu: function (tagList) {
|
|
const contextTagList = $('contextTagList')
|
|
while (contextTagList.firstChild !== null)
|
|
contextTagList.removeChild(contextTagList.firstChild)
|
|
|
|
contextTagList.appendChild(
|
|
new Element('li', {
|
|
html:
|
|
'<a href="javascript:torrentAddTagsFN();">' +
|
|
'<img src="images/list-add.svg" alt="Add..."/>' +
|
|
' Add...' +
|
|
'</a>',
|
|
})
|
|
)
|
|
contextTagList.appendChild(
|
|
new Element('li', {
|
|
html:
|
|
'<a href="javascript:torrentRemoveAllTagsFN();">' +
|
|
'<img src="images/edit-clear.svg" alt="Remove All"/>' +
|
|
' Remove All' +
|
|
'</a>',
|
|
})
|
|
)
|
|
|
|
const sortedTags = []
|
|
for (const key in tagList) sortedTags.push(tagList[key].name)
|
|
sortedTags.sort()
|
|
|
|
for (let i = 0; i < sortedTags.length; ++i) {
|
|
const tagName = sortedTags[i]
|
|
const tagHash = genHash(tagName)
|
|
const el = new Element('li', {
|
|
html:
|
|
'<a href="#Tag/' +
|
|
tagHash +
|
|
'" onclick="event.preventDefault(); torrentSetTagsFN(\'' +
|
|
tagHash +
|
|
"', !event.currentTarget.getElement('input[type=checkbox]').checked);\">" +
|
|
'<input type="checkbox" onclick="this.checked = !this.checked;"> ' +
|
|
window.qBittorrent.Misc.escapeHtml(tagName) +
|
|
'</a>',
|
|
})
|
|
if (i === 0) el.addClass('separator')
|
|
contextTagList.appendChild(el)
|
|
}
|
|
},
|
|
})
|
|
|
|
const CategoriesFilterContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
updateMenuItems: function () {
|
|
const id = this.options.element.id
|
|
if (id != CATEGORIES_ALL && id != CATEGORIES_UNCATEGORIZED) {
|
|
this.showItem('editCategory')
|
|
this.showItem('deleteCategory')
|
|
if (useSubcategories) {
|
|
this.showItem('createSubcategory')
|
|
} else {
|
|
this.hideItem('createSubcategory')
|
|
}
|
|
} else {
|
|
this.hideItem('editCategory')
|
|
this.hideItem('deleteCategory')
|
|
this.hideItem('createSubcategory')
|
|
}
|
|
},
|
|
})
|
|
|
|
const TagsFilterContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
updateMenuItems: function () {
|
|
const id = this.options.element.id
|
|
if (id !== TAGS_ALL.toString() && id !== TAGS_UNTAGGED.toString())
|
|
this.showItem('deleteTag')
|
|
else this.hideItem('deleteTag')
|
|
},
|
|
})
|
|
|
|
const SearchPluginsTableContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
|
|
updateMenuItems: function () {
|
|
const enabledColumnIndex = function (text) {
|
|
const columns = $('searchPluginsTableFixedHeaderRow').getChildren('th')
|
|
for (let i = 0; i < columns.length; ++i)
|
|
if (columns[i].get('html') === 'Enabled') return i
|
|
}
|
|
|
|
this.showItem('Enabled')
|
|
this.setItemChecked(
|
|
'Enabled',
|
|
this.options.element
|
|
.getChildren('td')
|
|
[enabledColumnIndex()].get('html') === 'Yes'
|
|
)
|
|
|
|
this.showItem('Uninstall')
|
|
},
|
|
})
|
|
|
|
const RssFeedContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
updateMenuItems: function () {
|
|
let selectedRows = window.qBittorrent.Rss.rssFeedTable.selectedRowsIds()
|
|
this.menu
|
|
.getElement('a[href$=newSubscription]')
|
|
.parentNode.addClass('separator')
|
|
switch (selectedRows.length) {
|
|
case 0:
|
|
// remove separator on top of newSubscription entry to avoid double line
|
|
this.menu
|
|
.getElement('a[href$=newSubscription]')
|
|
.parentNode.removeClass('separator')
|
|
// menu when nothing selected
|
|
this.hideItem('update')
|
|
this.hideItem('markRead')
|
|
this.hideItem('rename')
|
|
this.hideItem('delete')
|
|
this.showItem('newSubscription')
|
|
this.showItem('newFolder')
|
|
this.showItem('updateAll')
|
|
this.hideItem('copyFeedURL')
|
|
break
|
|
case 1:
|
|
if (selectedRows[0] === 0) {
|
|
// menu when "unread" feed selected
|
|
this.showItem('update')
|
|
this.showItem('markRead')
|
|
this.hideItem('rename')
|
|
this.hideItem('delete')
|
|
this.showItem('newSubscription')
|
|
this.hideItem('newFolder')
|
|
this.hideItem('updateAll')
|
|
this.hideItem('copyFeedURL')
|
|
} else if (
|
|
window.qBittorrent.Rss.rssFeedTable.rows[selectedRows[0]].full_data
|
|
.dataUid === ''
|
|
) {
|
|
// menu when single folder selected
|
|
this.showItem('update')
|
|
this.showItem('markRead')
|
|
this.showItem('rename')
|
|
this.showItem('delete')
|
|
this.showItem('newSubscription')
|
|
this.showItem('newFolder')
|
|
this.hideItem('updateAll')
|
|
this.hideItem('copyFeedURL')
|
|
} else {
|
|
// menu when single feed selected
|
|
this.showItem('update')
|
|
this.showItem('markRead')
|
|
this.showItem('rename')
|
|
this.showItem('delete')
|
|
this.showItem('newSubscription')
|
|
this.hideItem('newFolder')
|
|
this.hideItem('updateAll')
|
|
this.showItem('copyFeedURL')
|
|
}
|
|
break
|
|
default:
|
|
// menu when multiple items selected
|
|
this.showItem('update')
|
|
this.showItem('markRead')
|
|
this.hideItem('rename')
|
|
this.showItem('delete')
|
|
this.hideItem('newSubscription')
|
|
this.hideItem('newFolder')
|
|
this.hideItem('updateAll')
|
|
this.showItem('copyFeedURL')
|
|
break
|
|
}
|
|
},
|
|
})
|
|
|
|
const RssArticleContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
})
|
|
|
|
const RssDownloaderRuleContextMenu = new Class({
|
|
Extends: ContextMenu,
|
|
adjustMenuPosition: function (e) {
|
|
this.updateMenuItems()
|
|
|
|
// draw the menu off-screen to know the menu dimensions
|
|
this.menu.setStyles({
|
|
left: '-999em',
|
|
top: '-999em',
|
|
})
|
|
// position the menu
|
|
let xPosMenu =
|
|
e.page.x + this.options.offsets.x - $('rssdownloaderpage').offsetLeft
|
|
let yPosMenu =
|
|
e.page.y + this.options.offsets.y - $('rssdownloaderpage').offsetTop
|
|
if (
|
|
xPosMenu + this.menu.offsetWidth >
|
|
document.documentElement.clientWidth
|
|
)
|
|
xPosMenu -= this.menu.offsetWidth
|
|
if (
|
|
yPosMenu + this.menu.offsetHeight >
|
|
document.documentElement.clientHeight
|
|
)
|
|
yPosMenu =
|
|
document.documentElement.clientHeight - this.menu.offsetHeight
|
|
xPosMenu = Math.max(xPosMenu, 0)
|
|
yPosMenu = Math.max(yPosMenu, 0)
|
|
|
|
this.menu.setStyles({
|
|
left: xPosMenu,
|
|
top: yPosMenu,
|
|
position: 'absolute',
|
|
'z-index': '2000',
|
|
})
|
|
},
|
|
updateMenuItems: function () {
|
|
let selectedRows =
|
|
window.qBittorrent.RssDownloader.rssDownloaderRulesTable.selectedRowsIds()
|
|
this.showItem('addRule')
|
|
switch (selectedRows.length) {
|
|
case 0:
|
|
// menu when nothing selected
|
|
this.hideItem('deleteRule')
|
|
this.hideItem('renameRule')
|
|
this.hideItem('clearDownloadedEpisodes')
|
|
break
|
|
case 1:
|
|
// menu when single item selected
|
|
this.showItem('deleteRule')
|
|
this.showItem('renameRule')
|
|
this.showItem('clearDownloadedEpisodes')
|
|
break
|
|
default:
|
|
// menu when multiple items selected
|
|
this.showItem('deleteRule')
|
|
this.hideItem('renameRule')
|
|
this.showItem('clearDownloadedEpisodes')
|
|
break
|
|
}
|
|
},
|
|
})
|
|
|
|
return exports()
|
|
})()
|
|
|
|
Object.freeze(window.qBittorrent.ContextMenu)
|