@ -39,6 +39,7 @@ let syncRequestInProgress = false;
let clipboardEvent ;
let clipboardEvent ;
/* Categories filter */
const CATEGORIES _ALL = 1 ;
const CATEGORIES _ALL = 1 ;
const CATEGORIES _UNCATEGORIZED = 2 ;
const CATEGORIES _UNCATEGORIZED = 2 ;
@ -47,6 +48,7 @@ let category_list = {};
let selected _category = CATEGORIES _ALL ;
let selected _category = CATEGORIES _ALL ;
let setCategoryFilter = function ( ) { } ;
let setCategoryFilter = function ( ) { } ;
/* Tags filter */
const TAGS _ALL = 1 ;
const TAGS _ALL = 1 ;
const TAGS _UNTAGGED = 2 ;
const TAGS _UNTAGGED = 2 ;
@ -55,6 +57,16 @@ let tagList = {};
let selectedTag = TAGS _ALL ;
let selectedTag = TAGS _ALL ;
let setTagFilter = function ( ) { } ;
let setTagFilter = function ( ) { } ;
/* Trackers filter */
const TRACKERS _ALL = 1 ;
const TRACKERS _TRACKERLESS = 2 ;
const trackerList = new Map ( ) ;
let selectedTracker = TRACKERS _ALL ;
let setTrackerFilter = function ( ) { } ;
/* All filters */
let selected _filter = LocalPreferences . get ( 'selected_filter' , 'all' ) ;
let selected _filter = LocalPreferences . get ( 'selected_filter' , 'all' ) ;
let setFilter = function ( ) { } ;
let setFilter = function ( ) { } ;
let toggleFilterDisplay = function ( ) { } ;
let toggleFilterDisplay = function ( ) { } ;
@ -69,6 +81,11 @@ const loadSelectedTag = function() {
} ;
} ;
loadSelectedTag ( ) ;
loadSelectedTag ( ) ;
const loadSelectedTracker = function ( ) {
selectedTracker = LocalPreferences . get ( 'selected_tracker' , TRACKERS _ALL ) ;
} ;
loadSelectedTracker ( ) ;
function genHash ( string ) {
function genHash ( string ) {
let hash = 0 ;
let hash = 0 ;
for ( let i = 0 ; i < string . length ; ++ i ) {
for ( let i = 0 ; i < string . length ; ++ i ) {
@ -174,6 +191,14 @@ window.addEvent('load', function() {
updateMainData ( ) ;
updateMainData ( ) ;
} ;
} ;
setTrackerFilter = function ( hash ) {
selectedTracker = hash . toString ( ) ;
LocalPreferences . set ( 'selected_tracker' , selectedTracker ) ;
highlightSelectedTracker ( ) ;
if ( torrentsTable . tableBody !== undefined )
updateMainData ( ) ;
} ;
setFilter = function ( f ) {
setFilter = function ( f ) {
// Visually Select the right filter
// Visually Select the right filter
$ ( "all_filter" ) . removeClass ( "selectedFilter" ) ;
$ ( "all_filter" ) . removeClass ( "selectedFilter" ) ;
@ -335,7 +360,7 @@ window.addEvent('load', function() {
} ;
} ;
const updateFilter = function ( filter , filterTitle ) {
const updateFilter = function ( filter , filterTitle ) {
$ ( filter + '_filter' ) . firstChild . childNodes [ 1 ] . nodeValue = filterTitle . replace ( '%1' , torrentsTable . getFilteredTorrentsNumber ( filter , CATEGORIES _ALL , TAGS _ALL ) ) ;
$ ( filter + '_filter' ) . firstChild . childNodes [ 1 ] . nodeValue = filterTitle . replace ( '%1' , torrentsTable . getFilteredTorrentsNumber ( filter , CATEGORIES _ALL , TAGS _ALL , TRACKERS _ALL ) ) ;
} ;
} ;
const updateFiltersList = function ( ) {
const updateFiltersList = function ( ) {
@ -462,6 +487,51 @@ window.addEvent('load', function() {
children [ i ] . className = ( children [ i ] . id === selectedTag ) ? "selectedFilter" : "" ;
children [ i ] . className = ( children [ i ] . id === selectedTag ) ? "selectedFilter" : "" ;
} ;
} ;
const updateTrackerList = function ( ) {
const trackerFilterList = $ ( 'trackerFilterList' ) ;
if ( trackerFilterList === null )
return ;
while ( trackerFilterList . firstChild !== null )
trackerFilterList . removeChild ( trackerFilterList . firstChild ) ;
const createLink = function ( hash , text , count ) {
const html = '<a href="#" onclick="setTrackerFilter(' + hash + ');return false;">'
+ '<img src="images/qbt-theme/network-server.svg"/>'
+ window . qBittorrent . Misc . escapeHtml ( text . replace ( "%1" , count ) ) + '</a>' ;
const el = new Element ( 'li' , {
id : hash ,
html : html
} ) ;
window . qBittorrent . Filters . trackersFilterContextMenu . addTarget ( el ) ;
return el ;
} ;
const torrentsCount = torrentsTable . getRowIds ( ) . length ;
trackerFilterList . appendChild ( createLink ( TRACKERS _ALL , 'QBT_TR(All (%1))QBT_TR[CONTEXT=TrackerFiltersList]' , torrentsCount ) ) ;
let trackerlessTorrentsCount = 0 ;
for ( const key in torrentsTable . rows ) {
if ( torrentsTable . rows . hasOwnProperty ( key ) && ( torrentsTable . rows [ key ] [ 'full_data' ] . trackers _count === 0 ) )
trackerlessTorrentsCount += 1 ;
}
trackerFilterList . appendChild ( createLink ( TRACKERS _TRACKERLESS , 'QBT_TR(Trackerless (%1))QBT_TR[CONTEXT=TrackerFiltersList]' , trackerlessTorrentsCount ) ) ;
for ( const [ hash , tracker ] of trackerList )
trackerFilterList . appendChild ( createLink ( hash , tracker . url + ' (%1)' , tracker . torrents . length ) ) ;
highlightSelectedTracker ( ) ;
} ;
const highlightSelectedTracker = function ( ) {
const trackerFilterList = $ ( 'trackerFilterList' ) ;
if ( ! trackerFilterList )
return ;
const children = trackerFilterList . childNodes ;
for ( const child of children )
child . className = ( child . id === selectedTracker ) ? "selectedFilter" : "" ;
} ;
let syncMainDataTimer ;
let syncMainDataTimer ;
const syncMainData = function ( ) {
const syncMainData = function ( ) {
const url = new URI ( 'api/v2/sync/maindata' ) ;
const url = new URI ( 'api/v2/sync/maindata' ) ;
@ -484,6 +554,7 @@ window.addEvent('load', function() {
let torrentsTableSelectedRows ;
let torrentsTableSelectedRows ;
let update _categories = false ;
let update _categories = false ;
let updateTags = false ;
let updateTags = false ;
let updateTrackers = false ;
const full _update = ( response [ 'full_update' ] === true ) ;
const full _update = ( response [ 'full_update' ] === true ) ;
if ( full _update ) {
if ( full _update ) {
torrentsTableSelectedRows = torrentsTable . selectedRowsIds ( ) ;
torrentsTableSelectedRows = torrentsTable . selectedRowsIds ( ) ;
@ -538,6 +609,25 @@ window.addEvent('load', function() {
}
}
updateTags = true ;
updateTags = true ;
}
}
if ( response [ 'trackers' ] ) {
for ( const tracker in response [ 'trackers' ] ) {
const torrents = response [ 'trackers' ] [ tracker ] ;
const hash = genHash ( tracker ) ;
trackerList . set ( hash , {
url : tracker ,
torrents : torrents
} ) ;
}
updateTrackers = true ;
}
if ( response [ 'trackers_removed' ] ) {
for ( let i = 0 ; i < response [ 'trackers_removed' ] . length ; ++ i ) {
const tracker = response [ 'trackers_removed' ] [ i ] ;
const hash = genHash ( tracker ) ;
trackerList . delete ( hash ) ;
}
updateTrackers = true ;
}
if ( response [ 'torrents' ] ) {
if ( response [ 'torrents' ] ) {
let updateTorrentList = false ;
let updateTorrentList = false ;
for ( const key in response [ 'torrents' ] ) {
for ( const key in response [ 'torrents' ] ) {
@ -582,6 +672,8 @@ window.addEvent('load', function() {
updateTagList ( ) ;
updateTagList ( ) ;
window . qBittorrent . TransferList . contextMenu . updateTagsSubMenu ( tagList ) ;
window . qBittorrent . TransferList . contextMenu . updateTagsSubMenu ( tagList ) ;
}
}
if ( updateTrackers )
updateTrackerList ( ) ;
if ( full _update )
if ( full _update )
// re-select previously selected rows
// re-select previously selected rows
@ -656,10 +748,10 @@ window.addEvent('load', function() {
break ;
break ;
default : {
default : {
$ ( 'connectionStatus' ) . src = 'images/skin/disconnected.svg' ;
$ ( 'connectionStatus' ) . src = 'images/skin/disconnected.svg' ;
$ ( 'connectionStatus' ) . alt = 'QBT_TR(Connection status: Disconnected)QBT_TR[CONTEXT=MainWindow]' ;
$ ( 'connectionStatus' ) . alt = 'QBT_TR(Connection status: Disconnected)QBT_TR[CONTEXT=MainWindow]' ;
}
}
break ;
break ;
}
}
if ( queueing _enabled != serverState . queueing ) {
if ( queueing _enabled != serverState . queueing ) {
queueing _enabled = serverState . queueing ;
queueing _enabled = serverState . queueing ;
@ -695,7 +787,7 @@ window.addEvent('load', function() {
if ( enabled ) {
if ( enabled ) {
$ ( 'alternativeSpeedLimits' ) . src = 'images/slow.svg' ;
$ ( 'alternativeSpeedLimits' ) . src = 'images/slow.svg' ;
$ ( 'alternativeSpeedLimits' ) . alt = 'QBT_TR(Alternative speed limits: On)QBT_TR[CONTEXT=MainWindow]' ;
$ ( 'alternativeSpeedLimits' ) . alt = 'QBT_TR(Alternative speed limits: On)QBT_TR[CONTEXT=MainWindow]' ;
}
}
else {
else {
$ ( 'alternativeSpeedLimits' ) . src = 'images/slow_off.svg' ;
$ ( 'alternativeSpeedLimits' ) . src = 'images/slow_off.svg' ;
$ ( 'alternativeSpeedLimits' ) . alt = 'QBT_TR(Alternative speed limits: Off)QBT_TR[CONTEXT=MainWindow]' ;
$ ( 'alternativeSpeedLimits' ) . alt = 'QBT_TR(Alternative speed limits: Off)QBT_TR[CONTEXT=MainWindow]' ;