|
|
|
@@ -626,7 +626,7 @@ input[type=range]::-moz-range-thumb{width:12px;height:12px;border:0;border-radiu
|
|
|
|
<div class="tgroup item">
|
|
|
|
<div class="tgroup item">
|
|
|
|
<button id="tbPlay" title="Play the selected item" aria-label="Play the selected item" data-icon="play" disabled></button>
|
|
|
|
<button id="tbPlay" title="Play the selected item" aria-label="Play the selected item" data-icon="play" disabled></button>
|
|
|
|
<button id="tbRead" title="Mark the selected item read or unread" aria-label="Mark read or unread" data-icon="check" disabled></button>
|
|
|
|
<button id="tbRead" title="Mark the selected item read or unread" aria-label="Mark read or unread" data-icon="check" disabled></button>
|
|
|
|
<button id="tbFlag" title="Keep the selected item, so it is never deleted" aria-label="Keep" data-icon="flag" disabled></button>
|
|
|
|
<button id="tbFlag" title="Pin the selected item, so it is never deleted" aria-label="Pin" data-icon="pin" disabled></button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<span class="grow"></span>
|
|
|
|
<span class="grow"></span>
|
|
|
|
<input type="search" id="epSearch" placeholder="Search items…">
|
|
|
|
<input type="search" id="epSearch" placeholder="Search items…">
|
|
|
|
@@ -705,8 +705,11 @@ const ICON={
|
|
|
|
play:fa('0 0 448 512','<path fill="currentColor" d="M91.2 36.9c-12.4-6.8-27.4-6.5-39.6 .7S32 57.9 32 72l0 368c0 14.1 7.5 27.2 19.6 34.4s27.2 7.5 39.6 .7l336-184c12.8-7 20.8-20.5 20.8-35.1s-8-28.1-20.8-35.1l-336-184z"/>'), // solid/play
|
|
|
|
play:fa('0 0 448 512','<path fill="currentColor" d="M91.2 36.9c-12.4-6.8-27.4-6.5-39.6 .7S32 57.9 32 72l0 368c0 14.1 7.5 27.2 19.6 34.4s27.2 7.5 39.6 .7l336-184c12.8-7 20.8-20.5 20.8-35.1s-8-28.1-20.8-35.1l-336-184z"/>'), // solid/play
|
|
|
|
check:fa('0 0 448 512','<path fill="currentColor" d="M434.8 70.1c14.3 10.4 17.5 30.4 7.1 44.7l-256 352c-5.5 7.6-14 12.3-23.4 13.1s-18.5-2.7-25.1-9.3l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l101.5 101.5 234-321.7c10.4-14.3 30.4-17.5 44.7-7.1z"/>'), // solid/check
|
|
|
|
check:fa('0 0 448 512','<path fill="currentColor" d="M434.8 70.1c14.3 10.4 17.5 30.4 7.1 44.7l-256 352c-5.5 7.6-14 12.3-23.4 13.1s-18.5-2.7-25.1-9.3l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l101.5 101.5 234-321.7c10.4-14.3 30.4-17.5 44.7-7.1z"/>'), // solid/check
|
|
|
|
checks:fa('0 0 384 512','<path fill="currentColor" d="M249.9 66.8c10.4-14.3 7.2-34.3-7.1-44.7s-34.3-7.2-44.7 7.1l-106 145.7-37.5-37.5c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l64 64c6.6 6.6 15.8 10 25.1 9.3s17.9-5.5 23.4-13.1l128-176zm128 136c10.4-14.3 7.2-34.3-7.1-44.7s-34.3-7.2-44.7 7.1l-170 233.7-69.5-69.5c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l96 96c6.6 6.6 15.8 10 25.1 9.3s17.9-5.5 23.4-13.1l192-264z"/>'), // solid/check-double
|
|
|
|
checks:fa('0 0 384 512','<path fill="currentColor" d="M249.9 66.8c10.4-14.3 7.2-34.3-7.1-44.7s-34.3-7.2-44.7 7.1l-106 145.7-37.5-37.5c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l64 64c6.6 6.6 15.8 10 25.1 9.3s17.9-5.5 23.4-13.1l128-176zm128 136c10.4-14.3 7.2-34.3-7.1-44.7s-34.3-7.2-44.7 7.1l-170 233.7-69.5-69.5c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l96 96c6.6 6.6 15.8 10 25.1 9.3s17.9-5.5 23.4-13.1l192-264z"/>'), // solid/check-double
|
|
|
|
flag:fa('0 0 448 512','<path fill="currentColor" d="M48 24C48 10.7 37.3 0 24 0S0 10.7 0 24L0 488c0 13.3 10.7 24 24 24s24-10.7 24-24l0-100 80.3-20.1c41.1-10.3 84.6-5.5 122.5 13.4 44.2 22.1 95.5 24.8 141.7 7.4l34.7-13c12.5-4.7 20.8-16.6 20.8-30l0-279.7c0-23-24.2-38-44.8-27.7l-9.6 4.8c-46.3 23.2-100.8 23.2-147.1 0-35.1-17.6-75.4-22-113.5-12.5L48 52 48 24zm0 77.5l96.6-24.2c27-6.7 55.5-3.6 80.4 8.8 54.9 27.4 118.7 29.7 175 6.8l0 241.8-24.4 9.1c-33.7 12.6-71.2 10.7-103.4-5.4-48.2-24.1-103.3-30.1-155.6-17.1l-68.6 17.2 0-237z"/>'), // regular/flag
|
|
|
|
// Pinned is the solid thumbtack; not pinned, the same shape outlined, as the flag had its regular
|
|
|
|
flagOn:fa('0 0 448 512','<path fill="currentColor" d="M64 32C64 14.3 49.7 0 32 0S0 14.3 0 32L0 480c0 17.7 14.3 32 32 32s32-14.3 32-32l0-121.6 62.7-18.8c41.9-12.6 87.1-8.7 126.2 10.9 42.7 21.4 92.5 24 137.2 7.2l37.1-13.9c12.5-4.7 20.8-16.6 20.8-30l0-247.7c0-23-24.2-38-44.8-27.7l-11.8 5.9c-44.9 22.5-97.8 22.5-142.8 0-36.4-18.2-78.3-21.8-117.2-10.1L64 54.4 64 32z"/>'), // solid/flag
|
|
|
|
// and solid pair (Font Awesome's free set has no regular thumbtack). Both share a viewBox padded
|
|
|
|
|
|
|
|
// for the outline's stroke, so the two draw the same size.
|
|
|
|
|
|
|
|
pin:fa('-18 -18 420 548','<path fill="none" stroke="currentColor" stroke-width="36" stroke-linejoin="round" d="M32 32C32 14.3 46.3 0 64 0L320 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-29.5 0 11.4 148.2c36.7 19.9 65.7 53.2 79.5 94.7l1 3c3.3 9.8 1.6 20.5-4.4 28.8s-15.7 13.3-26 13.3L32 352c-10.3 0-19.9-4.9-26-13.3s-7.7-19.1-4.4-28.8l1-3c13.8-41.5 42.8-74.8 79.5-94.7L93.5 64 64 64C46.3 64 32 49.7 32 32zM160 384l64 0 0 96c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-96z"/>'), // solid/thumbtack, outlined
|
|
|
|
|
|
|
|
pinOn:fa('-18 -18 420 548','<path fill="currentColor" d="M32 32C32 14.3 46.3 0 64 0L320 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-29.5 0 11.4 148.2c36.7 19.9 65.7 53.2 79.5 94.7l1 3c3.3 9.8 1.6 20.5-4.4 28.8s-15.7 13.3-26 13.3L32 352c-10.3 0-19.9-4.9-26-13.3s-7.7-19.1-4.4-28.8l1-3c13.8-41.5 42.8-74.8 79.5-94.7L93.5 64 64 64C46.3 64 32 49.7 32 32zM160 384l64 0 0 96c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-96z"/>'), // solid/thumbtack
|
|
|
|
scan:fa('0 0 512 512','<path fill="currentColor" d="M65.9 228.5c13.3-93 93.4-164.5 190.1-164.5 53 0 101 21.5 135.8 56.2 .2 .2 .4 .4 .6 .6l7.6 7.2-47.9 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l128 0c17.7 0 32-14.3 32-32l0-128c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 53.4-11.3-10.7C390.5 28.6 326.5 0 256 0 127 0 20.3 95.4 2.6 219.5 .1 237 12.2 253.2 29.7 255.7s33.7-9.7 36.2-27.1zm443.5 64c2.5-17.5-9.7-33.7-27.1-36.2s-33.7 9.7-36.2 27.1c-13.3 93-93.4 164.5-190.1 164.5-53 0-101-21.5-135.8-56.2-.2-.2-.4-.4-.6-.6l-7.6-7.2 47.9 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L32 320c-8.5 0-16.7 3.4-22.7 9.5S-.1 343.7 0 352.3l1 127c.1 17.7 14.6 31.9 32.3 31.7S65.2 496.4 65 478.7l-.4-51.5 10.7 10.1c46.3 46.1 110.2 74.7 180.7 74.7 129 0 235.7-95.4 253.4-219.5z"/>'), // solid/arrows-rotate
|
|
|
|
scan:fa('0 0 512 512','<path fill="currentColor" d="M65.9 228.5c13.3-93 93.4-164.5 190.1-164.5 53 0 101 21.5 135.8 56.2 .2 .2 .4 .4 .6 .6l7.6 7.2-47.9 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l128 0c17.7 0 32-14.3 32-32l0-128c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 53.4-11.3-10.7C390.5 28.6 326.5 0 256 0 127 0 20.3 95.4 2.6 219.5 .1 237 12.2 253.2 29.7 255.7s33.7-9.7 36.2-27.1zm443.5 64c2.5-17.5-9.7-33.7-27.1-36.2s-33.7 9.7-36.2 27.1c-13.3 93-93.4 164.5-190.1 164.5-53 0-101-21.5-135.8-56.2-.2-.2-.4-.4-.6-.6l-7.6-7.2 47.9 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L32 320c-8.5 0-16.7 3.4-22.7 9.5S-.1 343.7 0 352.3l1 127c.1 17.7 14.6 31.9 32.3 31.7S65.2 496.4 65 478.7l-.4-51.5 10.7 10.1c46.3 46.1 110.2 74.7 180.7 74.7 129 0 235.7-95.4 253.4-219.5z"/>'), // solid/arrows-rotate
|
|
|
|
download:fa('0 0 448 512','<path fill="currentColor" d="M256 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 210.7-41.4-41.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 242.7 256 32zM64 320c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-46.9 0-56.6 56.6c-31.2 31.2-81.9 31.2-113.1 0L110.9 320 64 320zm304 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/>'), // solid/download
|
|
|
|
download:fa('0 0 448 512','<path fill="currentColor" d="M256 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 210.7-41.4-41.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 242.7 256 32zM64 320c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-46.9 0-56.6 56.6c-31.2 31.2-81.9 31.2-113.1 0L110.9 320 64 320zm304 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/>'), // solid/download
|
|
|
|
save:fa('0 0 448 512','<path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm32 96c0-17.7 14.3-32 32-32l160 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-160 0c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/>'), // solid/floppy-disk
|
|
|
|
save:fa('0 0 448 512','<path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm32 96c0-17.7 14.3-32 32-32l160 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-160 0c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/>'), // solid/floppy-disk
|
|
|
|
@@ -1011,7 +1014,7 @@ function renderFeed(){
|
|
|
|
</div>`) + `
|
|
|
|
</div>`) + `
|
|
|
|
<div class="toolbar">
|
|
|
|
<div class="toolbar">
|
|
|
|
<div class="tabs">
|
|
|
|
<div class="tabs">
|
|
|
|
${[['all','All'],['unread','Unread'],['downloaded','Downloaded'],['flagged','Kept']].map(([t,label])=>
|
|
|
|
${[['all','All'],['unread','Unread'],['downloaded','Downloaded'],['flagged','Pinned']].map(([t,label])=>
|
|
|
|
`<button data-f="${t}" class="${S.filter===t?'on':''}">${label}</button>`).join('')}
|
|
|
|
`<button data-f="${t}" class="${S.filter===t?'on':''}">${label}</button>`).join('')}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>`;
|
|
|
|
</div>`;
|
|
|
|
@@ -1038,7 +1041,7 @@ function renderFeed(){
|
|
|
|
|
|
|
|
|
|
|
|
/// The item table's headings, each a button that sorts by its column. The first click goes the
|
|
|
|
/// The item table's headings, each a button that sorts by its column. The first click goes the
|
|
|
|
/// natural way round (A to Z; newest, largest and kept first) and the next one reverses it.
|
|
|
|
/// natural way round (A to Z; newest, largest and kept first) and the next one reverses it.
|
|
|
|
const COLS=[['kept','Kept',ICON.flag],['title','Title'],['feed','Feed'],['type','File'],['size','Size'],['published','Published']];
|
|
|
|
const COLS=[['kept','Pinned',ICON.pin],['title','Title'],['feed','Feed'],['type','File'],['size','Size'],['published','Published']];
|
|
|
|
function sortHead(){
|
|
|
|
function sortHead(){
|
|
|
|
return '<div class="ephead"><span></span>'+COLS.map(([k,label,icon])=>{
|
|
|
|
return '<div class="ephead"><span></span>'+COLS.map(([k,label,icon])=>{
|
|
|
|
const on=S.sort.col===k;
|
|
|
|
const on=S.sort.col===k;
|
|
|
|
@@ -1194,7 +1197,7 @@ function epEl(e){
|
|
|
|
<button class="st" data-a="read" title="Mark ${e.read?'unread':'read'}">${
|
|
|
|
<button class="st" data-a="read" title="Mark ${e.read?'unread':'read'}">${
|
|
|
|
player.guid===e.guid?EQ:(e.read?'':'●')}</button>
|
|
|
|
player.guid===e.guid?EQ:(e.read?'':'●')}</button>
|
|
|
|
<button class="fl${e.flagged?' on':''}" data-a="flag" title="${
|
|
|
|
<button class="fl${e.flagged?' on':''}" data-a="flag" title="${
|
|
|
|
e.flagged?'Stop keeping':'Keep, so it is never deleted'}">${e.flagged?ICON.flagOn:ICON.flag}</button>
|
|
|
|
e.flagged?'Unpin':'Pin, so it is never deleted'}">${e.flagged?ICON.pinOn:ICON.pin}</button>
|
|
|
|
<div class="body">
|
|
|
|
<div class="body">
|
|
|
|
<span class="t">${esc(e.title||'(untitled)')}</span>
|
|
|
|
<span class="t">${esc(e.title||'(untitled)')}</span>
|
|
|
|
<div class="line">${[
|
|
|
|
<div class="line">${[
|
|
|
|
@@ -1319,10 +1322,10 @@ function syncTools(e){
|
|
|
|
$('#tbRead').disabled=$('#tbFlag').disabled=!e;
|
|
|
|
$('#tbRead').disabled=$('#tbFlag').disabled=!e;
|
|
|
|
// The same icons as the item's own buttons beside its title, so the two never disagree.
|
|
|
|
// The same icons as the item's own buttons beside its title, so the two never disagree.
|
|
|
|
$('#tbRead').innerHTML=e&&e.read?ICON.unread:ICON.check;
|
|
|
|
$('#tbRead').innerHTML=e&&e.read?ICON.unread:ICON.check;
|
|
|
|
$('#tbFlag').innerHTML=e&&e.flagged?ICON.flagOn:ICON.flag;
|
|
|
|
$('#tbFlag').innerHTML=e&&e.flagged?ICON.pinOn:ICON.pin;
|
|
|
|
if(e){
|
|
|
|
if(e){
|
|
|
|
$('#tbRead').title=`Mark ${e.read?'unread':'read'}`;
|
|
|
|
$('#tbRead').title=`Mark ${e.read?'unread':'read'}`;
|
|
|
|
$('#tbFlag').title=e.flagged?'Stop keeping':'Keep, so it is never deleted';
|
|
|
|
$('#tbFlag').title=e.flagged?'Unpin':'Pin, so it is never deleted';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1352,8 +1355,8 @@ function showDetail(e){
|
|
|
|
.filter(Boolean).map(s=>`<span>${s}</span>`).join('<span class="dot"></span>')}
|
|
|
|
.filter(Boolean).map(s=>`<span>${s}</span>`).join('<span class="dot"></span>')}
|
|
|
|
<button class="btn ico" data-a="read" title="Mark ${e.read?'unread':'read'}"
|
|
|
|
<button class="btn ico" data-a="read" title="Mark ${e.read?'unread':'read'}"
|
|
|
|
aria-label="Mark ${e.read?'unread':'read'}">${e.read?ICON.unread:ICON.check}</button>
|
|
|
|
aria-label="Mark ${e.read?'unread':'read'}">${e.read?ICON.unread:ICON.check}</button>
|
|
|
|
<button class="btn ico" data-a="flag" title="${e.flagged?'Kept: never deleted. Stop keeping':'Keep, so it is never deleted'}"
|
|
|
|
<button class="btn ico" data-a="flag" title="${e.flagged?'Pinned: never deleted. Unpin':'Pin, so it is never deleted'}"
|
|
|
|
aria-label="${e.flagged?'Stop keeping':'Keep'}">${e.flagged?ICON.flagOn:ICON.flag}</button>
|
|
|
|
aria-label="${e.flagged?'Unpin':'Pin'}">${e.flagged?ICON.pinOn:ICON.pin}</button>
|
|
|
|
${e.link?`<a class="btn ico" href="${esc(e.link)}" target="_blank" rel="noopener noreferrer"
|
|
|
|
${e.link?`<a class="btn ico" href="${esc(e.link)}" target="_blank" rel="noopener noreferrer"
|
|
|
|
title="Open the original" aria-label="Open the original">${ICON.open}</a>`:''}
|
|
|
|
title="Open the original" aria-label="Open the original">${ICON.open}</a>`:''}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@@ -1601,7 +1604,7 @@ function keysModal(){
|
|
|
|
[k('j')+' or '+k('n'),'Next item'],[k('k')+' or '+k('p'),'Previous item'],
|
|
|
|
[k('j')+' or '+k('n'),'Next item'],[k('k')+' or '+k('p'),'Previous item'],
|
|
|
|
[k('Shift')+' '+k('A'),'Mark all read'],
|
|
|
|
[k('Shift')+' '+k('A'),'Mark all read'],
|
|
|
|
['The selected item'],
|
|
|
|
['The selected item'],
|
|
|
|
[k('o'),'Play it'],[k('m'),'Mark it read or unread'],[k('s'),'Keep it, or stop keeping it'],
|
|
|
|
[k('o'),'Play it'],[k('m'),'Mark it read or unread'],[k('s'),'Pin it, or unpin it'],
|
|
|
|
[k('v'),'Open the original in a new tab'],
|
|
|
|
[k('v'),'Open the original in a new tab'],
|
|
|
|
['The player'],
|
|
|
|
['The player'],
|
|
|
|
[k('Space'),'Play or pause'],[k('←')+' '+k('→'),'Back 15 seconds, forward 30'],
|
|
|
|
[k('Space'),'Play or pause'],[k('←')+' '+k('→'),'Back 15 seconds, forward 30'],
|
|
|
|
@@ -1940,7 +1943,7 @@ async function prefsModal(){
|
|
|
|
put article images in enclosures, and those are not worth keeping. Empty takes everything.</span></div>
|
|
|
|
put article images in enclosures, and those are not worth keeping. Empty takes everything.</span></div>
|
|
|
|
<div class="field"><label>Disk quota (GB, 0 = unlimited)</label>
|
|
|
|
<div class="field"><label>Disk quota (GB, 0 = unlimited)</label>
|
|
|
|
<input type="number" id="gquota" min="0" step="0.5" value="${g.max_total_gb}">
|
|
|
|
<input type="number" id="gquota" min="0" step="0.5" value="${g.max_total_gb}">
|
|
|
|
<span class="hint">Over this, the oldest played items are deleted first. Kept
|
|
|
|
<span class="hint">Over this, the oldest played items are deleted first. Pinned
|
|
|
|
items are never touched.</span></div>
|
|
|
|
items are never touched.</span></div>
|
|
|
|
<div class="field"><label>Delete items older than (days, 0 = keep)</label>
|
|
|
|
<div class="field"><label>Delete items older than (days, 0 = keep)</label>
|
|
|
|
<input type="number" id="gage" min="0" value="${g.max_age_days}"></div>`:''}
|
|
|
|
<input type="number" id="gage" min="0" value="${g.max_age_days}"></div>`:''}
|
|
|
|
|