Merge branch 'js-objects' into weblate-integration
This commit is contained in:
+4
-4
@@ -727,7 +727,7 @@ class Article extends Handler_Protected {
|
||||
if (!$zoom_mode) {
|
||||
$rv['content'] .= "<span id=\"ATSTR-$id\">$tags_str</span>
|
||||
<a title=\"".__('Edit tags for this article')."\"
|
||||
href=\"#\" onclick=\"editArticleTags($id, $feed_id)\">(+)</a>";
|
||||
href=\"#\" onclick=\"Article.editTags($id)\">(+)</a>";
|
||||
|
||||
$rv['content'] .= "<div dojoType=\"dijit.Tooltip\"
|
||||
id=\"ATSTRTIP-$id\" connectId=\"ATSTR-$id\"
|
||||
@@ -877,7 +877,7 @@ class Article extends Handler_Protected {
|
||||
$tags_str = "";
|
||||
|
||||
for ($i = 0; $i < $maxtags; $i++) {
|
||||
$tags_str .= "<a class=\"tag\" href=\"#\" onclick=\"viewfeed({feed:'".$tags[$i]."'})\">" . $tags[$i] . "</a>, ";
|
||||
$tags_str .= "<a class=\"tag\" href=\"#\" onclick=\"Feeds.open({feed:'".$tags[$i]."'})\">" . $tags[$i] . "</a>, ";
|
||||
}
|
||||
|
||||
$tags_str = mb_substr($tags_str, 0, mb_strlen($tags_str)-2);
|
||||
@@ -907,8 +907,8 @@ class Article extends Handler_Protected {
|
||||
|
||||
static function format_article_note($id, $note, $allow_edit = true) {
|
||||
|
||||
$str = "<div class='articleNote' onclick=\"editArticleNote($id)\">
|
||||
<div class='noteEdit' onclick=\"editArticleNote($id)\">".
|
||||
$str = "<div class='articleNote' onclick=\"Plugins.Note.edit($id)\">
|
||||
<div class='noteEdit' onclick=\"Plugins.Note.edit($id)\">".
|
||||
($allow_edit ? __('(edit note)') : "")."</div>$note</div>";
|
||||
|
||||
return $str;
|
||||
|
||||
+12
-10
@@ -49,10 +49,10 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
print "<div align='center'>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return opmlRegenKey()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return Helpers.OPML.changeKey()\">".
|
||||
__('Generate new URL')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.closeInfoBox()\">".
|
||||
__('Close this window')."</button>";
|
||||
|
||||
print "</div>";
|
||||
@@ -85,7 +85,7 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
print "<div align='center'>";
|
||||
|
||||
print "<button onclick=\"return closeInfoBox()\">".
|
||||
print "<button onclick=\"return CommonDialogs.closeInfoBox()\">".
|
||||
__('Close this window')."</button>";
|
||||
|
||||
print "</div>";
|
||||
@@ -139,7 +139,7 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
$key_escaped = str_replace("'", "\\'", $key);
|
||||
|
||||
echo "<a href=\"javascript:viewfeed({feed:'$key_escaped'}) \" style=\"font-size: " .
|
||||
echo "<a href=\"#\" onclick=\"Feeds.open({feed:'$key_escaped'}) \" style=\"font-size: " .
|
||||
$size . "px\" title=\"$value articles tagged with " .
|
||||
$key . '">' . $key . '</a> ';
|
||||
}
|
||||
@@ -150,7 +150,7 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
print "<div align='center'>";
|
||||
print "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"return closeInfoBox()\">".
|
||||
onclick=\"return CommonDialogs.closeInfoBox()\">".
|
||||
__('Close this window')."</button>";
|
||||
print "</div>";
|
||||
|
||||
@@ -166,7 +166,9 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
$url_path = htmlspecialchars($this->params[2]) . "&key=" . $key;
|
||||
|
||||
print "<h2>".__("You can view this feed as RSS using the following URL:")."</h2>";
|
||||
$feed_title = Feeds::getFeedTitle($feed_id, $is_cat);
|
||||
|
||||
print "<div>".T_sprintf("%s can be accessed via the following secret URL:", $feed_title)."</div>";
|
||||
|
||||
print "<div class=\"tagCloudContainer\">";
|
||||
print "<a id='gen_feed_url' href='$url_path' target='_blank'>$url_path</a>";
|
||||
@@ -174,10 +176,10 @@ class Dlg extends Handler_Protected {
|
||||
|
||||
print "<div align='center'>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return genUrlChangeKey('$feed_id', '$is_cat')\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.genUrlChangeKey('$feed_id', '$is_cat')\">".
|
||||
__('Generate new URL')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.closeInfoBox()\">".
|
||||
__('Close this window')."</button>";
|
||||
|
||||
print "</div>";
|
||||
@@ -190,10 +192,10 @@ class Dlg extends Handler_Protected {
|
||||
print_warning(__("You are using default tt-rss password. Please change it in the Preferences (Personal data / Authentication)."));
|
||||
|
||||
print "<div align='center'>";
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"gotoPreferences()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"document.location.href = 'prefs.php'\">".
|
||||
__('Open Preferences')."</button> ";
|
||||
print "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"return closeInfoBox()\">".
|
||||
onclick=\"return CommonDialogs.closeInfoBox()\">".
|
||||
__('Close this window')."</button>";
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
+47
-42
@@ -15,21 +15,21 @@ class Feeds extends Handler_Protected {
|
||||
$feed_id, $is_cat, $search,
|
||||
$error, $feed_last_updated) {
|
||||
|
||||
$catchup_sel_link = "catchupSelection()";
|
||||
$catchup_sel_link = "Headlines.catchupSelection()";
|
||||
|
||||
$archive_sel_link = "archiveSelection()";
|
||||
$delete_sel_link = "deleteSelection()";
|
||||
$archive_sel_link = "Headlines.archiveSelection()";
|
||||
$delete_sel_link = "Headlines.deleteSelection()";
|
||||
|
||||
$sel_all_link = "selectArticles('all')";
|
||||
$sel_unread_link = "selectArticles('unread')";
|
||||
$sel_none_link = "selectArticles('none')";
|
||||
$sel_inv_link = "selectArticles('invert')";
|
||||
$sel_all_link = "Headlines.select('all')";
|
||||
$sel_unread_link = "Headlines.select('unread')";
|
||||
$sel_none_link = "Headlines.select('none')";
|
||||
$sel_inv_link = "Headlines.select('invert')";
|
||||
|
||||
$tog_unread_link = "selectionToggleUnread()";
|
||||
$tog_marked_link = "selectionToggleMarked()";
|
||||
$tog_published_link = "selectionTogglePublished()";
|
||||
$tog_unread_link = "Headlines.selectionToggleUnread()";
|
||||
$tog_marked_link = "Headlines.selectionToggleMarked()";
|
||||
$tog_published_link = "Headlines.selectionTogglePublished()";
|
||||
|
||||
$set_score_link = "setSelectionScore()";
|
||||
$set_score_link = "Article.selectionSetScore()";
|
||||
|
||||
if ($is_cat) $cat_q = "&is_cat=$is_cat";
|
||||
|
||||
@@ -50,8 +50,8 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$reply .= "<span class='r'>
|
||||
<a href=\"#\"
|
||||
title=\"".__("View as RSS feed")."\"
|
||||
onclick=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
||||
title=\"".__("Show as feed")."\"
|
||||
onclick=\"App.displayDlg('".__("Show as feed")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
||||
<img class=\"noborder\" src=\"images/pub_set.png\"></a>";
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class Feeds extends Handler_Protected {
|
||||
$reply .= "</span> "; */
|
||||
|
||||
$reply .= "<select dojoType=\"dijit.form.Select\"
|
||||
onchange=\"headlineActionsChange(this)\">";
|
||||
onchange=\"Headlines.onActionChanged(this)\">";
|
||||
|
||||
$reply .= "<option value=\"0\" disabled='1'>".__('Select...')."</option>";
|
||||
|
||||
@@ -124,12 +124,12 @@ class Feeds extends Handler_Protected {
|
||||
}
|
||||
|
||||
if (PluginHost::getInstance()->get_plugin("mail")) {
|
||||
$reply .= "<option value=\"emailArticle(false)\">".__('Forward by email').
|
||||
$reply .= "<option value=\"Plugins.Mail.send()\">".__('Forward by email').
|
||||
"</option>";
|
||||
}
|
||||
|
||||
if (PluginHost::getInstance()->get_plugin("mailto")) {
|
||||
$reply .= "<option value=\"mailtoArticle(false)\">".__('Forward by email').
|
||||
$reply .= "<option value=\"Plugins.Mailto.send()\">".__('Forward by email').
|
||||
"</option>";
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
//$reply .= "<option value=\"catchupPage()\">".__('Mark as read')."</option>";
|
||||
|
||||
$reply .= "<option value=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">".__('View as RSS')."</option>";
|
||||
$reply .= "<option value=\"App.displayDlg('".__("Show as feed")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">".
|
||||
__('Show as feed')."</option>";
|
||||
|
||||
$reply .= "</select>";
|
||||
|
||||
@@ -299,7 +300,7 @@ class Feeds extends Handler_Protected {
|
||||
$label_cache = $line["label_cache"];
|
||||
$labels = false;
|
||||
|
||||
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)' onmouseout='postMouseOut($id)'";
|
||||
$mouseover_attrs = "onmouseover='Article.mouseIn($id)' onmouseout='Article.mouseOut($id)'";
|
||||
|
||||
if ($label_cache) {
|
||||
$label_cache = json_decode($label_cache, true);
|
||||
@@ -331,11 +332,11 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$marked_pic_src = $line["marked"] ? "mark_set.png" : "mark_unset.png";
|
||||
$class .= $line["marked"] ? " marked" : "";
|
||||
$marked_pic = "<img src=\"images/$marked_pic_src\" class=\"marked-pic marked-$id\" onclick='toggleMark($id)'>";
|
||||
$marked_pic = "<img src=\"images/$marked_pic_src\" class=\"marked-pic marked-$id\" onclick='Headlines.toggleMark($id)'>";
|
||||
|
||||
$published_pic_src = $line["published"] ? "pub_set.png" : "pub_unset.png";
|
||||
$class .= $line["published"] ? " published" : "";
|
||||
$published_pic = "<img src=\"images/$published_pic_src\" class=\"pub-pic pub-$id\" onclick='togglePub($id)'>";
|
||||
$published_pic = "<img src=\"images/$published_pic_src\" class=\"pub-pic pub-$id\" onclick='Headlines.togglePub($id)'>";
|
||||
|
||||
$updated_fmt = make_local_datetime($line["updated"], false, false, false, true);
|
||||
$date_entered_fmt = T_sprintf("Imported at %s",
|
||||
@@ -345,7 +346,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$score_pic = "images/" . get_score_pic($score);
|
||||
|
||||
$score_pic = "<img class='score-pic' score='$score' onclick='changeScore($id, this)' src=\"$score_pic\"
|
||||
$score_pic = "<img class='score-pic' score='$score' onclick='Article.setScore($id, this)' src=\"$score_pic\"
|
||||
title=\"$score\">";
|
||||
|
||||
if ($score > 500) {
|
||||
@@ -388,11 +389,11 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$vgroup_last_feed = $feed_id;
|
||||
|
||||
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||
$vf_catchup_link = "<a class='catchup' onclick='Feeds.catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||
|
||||
$reply['content'] .= "<div data-feed-id='$feed_id' class='feed-titl'>".
|
||||
$reply['content'] .= "<div data-feed-id='$feed_id' class='feed-title'>".
|
||||
"<div style='float : right'>$feed_icon_img</div>".
|
||||
"<a class='title' href=\"#\" onclick=\"viewfeed({feed:$feed_id})\">".
|
||||
"<a class='title' href=\"#\" onclick=\"Feeds.open({feed:$feed_id})\">".
|
||||
$line["feed_title"]."</a>
|
||||
$vf_catchup_link</div>";
|
||||
|
||||
@@ -405,7 +406,7 @@ class Feeds extends Handler_Protected {
|
||||
$reply['content'] .= "<div class='left'>";
|
||||
|
||||
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\" onclick=\"toggleSelectRow2(this)\"
|
||||
type=\"checkbox\" onclick=\"Headlines.onRowChecked(this)\"
|
||||
class='rchk'>";
|
||||
|
||||
$reply['content'] .= "$marked_pic";
|
||||
@@ -413,7 +414,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$reply['content'] .= "</div>";
|
||||
|
||||
$reply['content'] .= "<div onclick='return hlClicked(event, $id)'
|
||||
$reply['content'] .= "<div onclick='return Headlines.click(event, $id)'
|
||||
class=\"title\"><span class='hl-content $hlc_suffix'>";
|
||||
$reply['content'] .= "<a class=\"title $hlc_suffix\"
|
||||
href=\"" . htmlspecialchars($line["link"]) . "\"
|
||||
@@ -434,7 +435,7 @@ class Feeds extends Handler_Protected {
|
||||
if (@$line["feed_title"]) {
|
||||
$rgba = @$rgba_cache[$feed_id];
|
||||
|
||||
$reply['content'] .= "<span class=\"feed\"><a style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed({feed:$feed_id})\">".
|
||||
$reply['content'] .= "<span class=\"feed\"><a style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"Feeds.open({feed:$feed_id})\">".
|
||||
truncate_string($line["feed_title"],30)."</a></span>";
|
||||
}
|
||||
}
|
||||
@@ -451,7 +452,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
if ($line["feed_title"] && !$vfeed_group_enabled) {
|
||||
|
||||
$reply['content'] .= "<span onclick=\"viewfeed({feed:$feed_id})\"
|
||||
$reply['content'] .= "<span onclick=\"Feeds.open({feed:$feed_id})\"
|
||||
style=\"cursor : pointer\"
|
||||
title=\"".htmlspecialchars($line['feed_title'])."\">
|
||||
$feed_icon_img</span>";
|
||||
@@ -481,14 +482,14 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$vgroup_last_feed = $feed_id;
|
||||
|
||||
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||
$vf_catchup_link = "<a class='catchup' onclick='Feeds.catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||
|
||||
$feed_icon_src = Feeds::getFeedIcon($feed_id);
|
||||
$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"$feed_icon_src\">";
|
||||
|
||||
$reply['content'] .= "<div data-feed-id='$feed_id' class='feed-title'>".
|
||||
"<div style=\"float : right\">$feed_icon_img</div>".
|
||||
"<a href=\"#\" class='title' onclick=\"viewfeed({feed:$feed_id})\">".
|
||||
"<a href=\"#\" class='title' onclick=\"Feeds.open({feed:$feed_id})\">".
|
||||
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
||||
|
||||
}
|
||||
@@ -504,7 +505,7 @@ class Feeds extends Handler_Protected {
|
||||
$tmp_content .= "<div style=\"vertical-align : middle\">";
|
||||
|
||||
$tmp_content .= "<input dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\" onclick=\"toggleSelectRow2(this, false, true)\"
|
||||
type=\"checkbox\" onclick=\"Headlines.onRowChecked(this)\"
|
||||
class='rchk'>";
|
||||
|
||||
$tmp_content .= "$marked_pic";
|
||||
@@ -523,7 +524,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
// data-article-id included for context menu
|
||||
$tmp_content .= "<span
|
||||
onclick=\"return cdmClicked(event, $id);\"
|
||||
onclick=\"return Headlines.click(event, $id);\"
|
||||
data-article-id=\"$id\"
|
||||
class=\"titleWrap hlMenuAttach $hlc_suffix\">
|
||||
<a class=\"title $hlc_suffix\"
|
||||
@@ -535,9 +536,13 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$tmp_content .= $labels_str;
|
||||
|
||||
$tmp_content .= "<span class='collapse'>
|
||||
<img src=\"images/collapse.png\" onclick=\"return cdmCollapseActive(event)\"
|
||||
title=\"".__("Collapse article")."\"/></span>";
|
||||
if (!get_pref("CDM_EXPANDED")) {
|
||||
$tmp_content .= "<span class='collapse'>
|
||||
<img src=\"images/collapse.png\" onclick=\"return Article.cdmUnsetActive(event)\"
|
||||
title=\"" . __("Collapse article") . "\"/></span>";
|
||||
|
||||
$tmp_content .= "<span class='excerpt'>" . $line["content_preview"] . "</span>";
|
||||
}
|
||||
|
||||
$tmp_content .= "</span>";
|
||||
|
||||
@@ -547,7 +552,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$tmp_content .= "<div class=\"feed\">
|
||||
<a href=\"#\" style=\"background-color: rgba($rgba,0.3)\"
|
||||
onclick=\"viewfeed({feed:$feed_id})\">".
|
||||
onclick=\"Feeds.open({feed:$feed_id})\">".
|
||||
truncate_string($line["feed_title"],30)."</a>
|
||||
</div>";
|
||||
}
|
||||
@@ -561,13 +566,13 @@ class Feeds extends Handler_Protected {
|
||||
if (!get_pref("VFEED_GROUP_BY_FEED") && $line["feed_title"]) {
|
||||
$tmp_content .= "<span style=\"cursor : pointer\"
|
||||
title=\"".htmlspecialchars($line["feed_title"])."\"
|
||||
onclick=\"viewfeed({feed:$feed_id})\">$feed_icon_img</span>";
|
||||
onclick=\"Feeds.open({feed:$feed_id})\">$feed_icon_img</span>";
|
||||
}
|
||||
$tmp_content .= "</div>"; //score wrapper2
|
||||
|
||||
$tmp_content .= "</div>"; //header
|
||||
|
||||
$tmp_content .= "<div class=\"content\" onclick=\"return cdmClicked(event, $id, true);\">";
|
||||
$tmp_content .= "<div class=\"content\" onclick=\"return Headlines.click(event, $id, true);\">";
|
||||
|
||||
$tmp_content .= "<div id=\"POSTNOTE-$id\">";
|
||||
if ($line['note']) {
|
||||
@@ -628,7 +633,7 @@ class Feeds extends Handler_Protected {
|
||||
$tmp_content .= "<img src='images/tag.png' alt='Tags' title='Tags'>
|
||||
<span id=\"ATSTR-$id\">$tags_str</span>
|
||||
<a title=\"".__('Edit tags for this article')."\"
|
||||
href=\"#\" onclick=\"editArticleTags($id)\">(+)</a>";
|
||||
href=\"#\" onclick=\"Article.editTags($id)\">(+)</a>";
|
||||
|
||||
$num_comments = (int) $line["num_comments"];
|
||||
$entry_comments = "";
|
||||
@@ -722,7 +727,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
if ($num_errors > 0) {
|
||||
$reply['content'] .= "<br/>";
|
||||
$reply['content'] .= "<a class=\"insensitive\" href=\"#\" onclick=\"showFeedsWithErrors()\">" .
|
||||
$reply['content'] .= "<a class=\"insensitive\" href=\"#\" onclick=\"CommonDialogs.showFeedsWithErrors()\">" .
|
||||
__('Some feeds have update errors (click for details)') . "</a>";
|
||||
}
|
||||
$reply['content'] .= "</span></p></div>";
|
||||
@@ -913,7 +918,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
if ($num_errors > 0) {
|
||||
$reply['headlines']['content'] .= "<br/>";
|
||||
$reply['headlines']['content'] .= "<a class=\"insensitive\" href=\"#\" onclick=\"showFeedsWithErrors()\">".
|
||||
$reply['headlines']['content'] .= "<a class=\"insensitive\" href=\"#\" onclick=\"CommonDialogs.showFeedsWithErrors()\">".
|
||||
__('Some feeds have update errors (click for details)')."</a>";
|
||||
}
|
||||
$reply['headlines']['content'] .= "</span></p>";
|
||||
@@ -1014,7 +1019,7 @@ class Feeds extends Handler_Protected {
|
||||
<button dojoType=\"dijit.form.Button\" class=\"btn-primary\" type=\"submit\" onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>";
|
||||
|
||||
if (!(defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER)) {
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return feedBrowser()\">".__('More feeds')."</button>";
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.feedBrowser()\">".__('More feeds')."</button>";
|
||||
}
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button>
|
||||
|
||||
+2
-5
@@ -8,11 +8,8 @@ class Opml extends Handler_Protected {
|
||||
}
|
||||
|
||||
function export() {
|
||||
$output_name = $_REQUEST["filename"];
|
||||
if (!$output_name) $output_name = "TinyTinyRSS.opml";
|
||||
|
||||
$show_settings = $_REQUEST["settings"];
|
||||
|
||||
$output_name = "tt-rss_".date("Y-m-d").".opml";
|
||||
$show_settings = $_REQUEST["include_settings"];
|
||||
$owner_uid = $_SESSION["uid"];
|
||||
|
||||
$rc = $this->opml_export($output_name, $owner_uid, false, ($show_settings == 1));
|
||||
|
||||
+56
-57
@@ -492,7 +492,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
@unlink($icon_file);
|
||||
|
||||
print "<script type=\"text/javascript\">";
|
||||
print "parent.uploadIconHandler($rc);";
|
||||
print "parent.CommonDialogs.uploadIconHandler($rc);";
|
||||
print "</script>";
|
||||
return;
|
||||
}
|
||||
@@ -745,9 +745,9 @@ class Pref_Feeds extends Handler_Protected {
|
||||
<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
|
||||
<input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
|
||||
<input type=\"hidden\" name=\"method\" value=\"uploadicon\">
|
||||
<button class=\"\" dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
|
||||
<button class=\"\" dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.uploadFeedIcon();\"
|
||||
type=\"submit\">".__('Replace')."</button>
|
||||
<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
|
||||
<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.removeFeedIcon($feed_id);\"
|
||||
type=\"submit\">".__('Remove')."</button>
|
||||
</form>";
|
||||
|
||||
@@ -765,7 +765,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
|
||||
print "<div class='dlgButtons'>
|
||||
<div style=\"float : left\">
|
||||
<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
|
||||
<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick='return CommonDialogs.unsubscribeFeed($feed_id, \"$title\")'>".
|
||||
__('Unsubscribe')."</button>";
|
||||
|
||||
print "</div>";
|
||||
@@ -1149,14 +1149,14 @@ class Pref_Feeds extends Handler_Protected {
|
||||
if ($num_errors > 0) {
|
||||
|
||||
$error_button = "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
|
||||
onclick=\"CommonDialogs.showFeedsWithErrors()\" id=\"errorButton\">" .
|
||||
__("Feeds with errors") . "</button>";
|
||||
}
|
||||
|
||||
$inactive_button = "<button dojoType=\"dijit.form.Button\"
|
||||
id=\"pref_feeds_inactive_btn\"
|
||||
style=\"display : none\"
|
||||
onclick=\"showInactiveFeeds()\">" .
|
||||
onclick=\"dijit.byId('feedTree').showInactiveFeeds()\">" .
|
||||
__("Inactive feeds") . "</button>";
|
||||
|
||||
$feed_search = clean($_REQUEST["search"]);
|
||||
@@ -1174,7 +1174,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
print "<div style='float : right; padding-right : 4px;'>
|
||||
<input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
|
||||
value=\"$feed_search\">
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedTree').reload()\">".
|
||||
__('Search')."</button>
|
||||
</div>";
|
||||
|
||||
@@ -1190,15 +1190,15 @@ class Pref_Feeds extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Feeds')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"quickAddFeed()\"
|
||||
print "<div onclick=\"CommonDialogs.quickAddFeed()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
|
||||
print "<div onclick=\"editSelectedFeed()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').editSelectedFeed()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
|
||||
print "<div onclick=\"resetFeedOrder()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').resetFeedOrder()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
|
||||
print "<div onclick=\"batchSubscribe()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').batchSubscribe()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Batch subscribe')."</div>";
|
||||
print "<div dojoType=\"dijit.MenuItem\" onclick=\"removeSelectedFeeds()\">"
|
||||
print "<div dojoType=\"dijit.MenuItem\" onclick=\"dijit.byId('feedTree').removeSelectedFeeds()\">"
|
||||
.__('Unsubscribe')."</div> ";
|
||||
print "</div></div>";
|
||||
|
||||
@@ -1206,11 +1206,11 @@ class Pref_Feeds extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Categories')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"createCategory()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').createCategory()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Add category')."</div>";
|
||||
print "<div onclick=\"resetCatOrder()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').resetCatOrder()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
|
||||
print "<div onclick=\"removeSelectedCategories()\"
|
||||
print "<div onclick=\"dijit.byId('feedTree').removeSelectedCategories()\"
|
||||
dojoType=\"dijit.MenuItem\">".__('Remove selected')."</div>";
|
||||
print "</div></div>";
|
||||
|
||||
@@ -1247,15 +1247,15 @@ class Pref_Feeds extends Handler_Protected {
|
||||
var bare_id = id.substr(id.indexOf(':')+1);
|
||||
|
||||
if (id.match('FEED:')) {
|
||||
editFeed(bare_id);
|
||||
CommonDialogs.editFeed(bare_id);
|
||||
} else if (id.match('CAT:')) {
|
||||
editCat(bare_id, item);
|
||||
dijit.byId('feedTree').editCategory(bare_id, item);
|
||||
}
|
||||
</script>
|
||||
<script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
|
||||
Element.hide(\"feedlistLoading\");
|
||||
|
||||
checkInactiveFeeds();
|
||||
dijit.byId('feedTree').checkInactiveFeeds();
|
||||
</script>
|
||||
</div>";
|
||||
|
||||
@@ -1270,11 +1270,11 @@ class Pref_Feeds extends Handler_Protected {
|
||||
|
||||
print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('OPML')."\">";
|
||||
|
||||
print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") .
|
||||
__("Only main settings profile can be migrated using OPML.") . "</p>";
|
||||
print_notice(__("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") .
|
||||
__("Only main settings profile can be migrated using OPML."));
|
||||
|
||||
print "<iframe id=\"upload_iframe\"
|
||||
name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
|
||||
name=\"upload_iframe\" onload=\"Helpers.OPML.onImportComplete(this)\"
|
||||
style=\"width: 400px; height: 100px; display: none;\"></iframe>";
|
||||
|
||||
print "<form name=\"opml_form\" style='display : block' target=\"upload_iframe\"
|
||||
@@ -1285,28 +1285,33 @@ class Pref_Feeds extends Handler_Protected {
|
||||
</label>
|
||||
<input type=\"hidden\" name=\"op\" value=\"dlg\">
|
||||
<input type=\"hidden\" name=\"method\" value=\"importOpml\">
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
|
||||
__('Import my OPML') . "</button>";
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"return Helpers.OPML.import();\" type=\"submit\">" .
|
||||
__('Import OPML') . "</button>";
|
||||
|
||||
print "</form>";
|
||||
|
||||
print "<p/>";
|
||||
|
||||
print "<form dojoType=\"dijit.form.Form\" id=\"opmlExportForm\">";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"Helpers.OPML.export()\" >" .
|
||||
__('Export OPML') . "</button>";
|
||||
|
||||
print "<label>";
|
||||
print_checkbox("include_settings", true, "1", "");
|
||||
print " " . __("Include settings");
|
||||
print "</label>";
|
||||
|
||||
print "</form>";
|
||||
|
||||
print "<hr>";
|
||||
|
||||
$opml_export_filename = "TinyTinyRSS_".date("Y-m-d").".opml";
|
||||
|
||||
print "<p>" . __('Filename:') .
|
||||
" <input class=\"input input-text\" type=\"text\" id=\"filename\" value=\"$opml_export_filename\" /> " .
|
||||
__('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
|
||||
|
||||
print "</p><button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
|
||||
__('Export OPML') . "</button></p></form>";
|
||||
|
||||
print "<hr>";
|
||||
|
||||
print "<p>" . __('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . "</p>";
|
||||
print_notice(__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.'));
|
||||
|
||||
print_warning("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.");
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('".__("Public OPML URL")."','pubOPMLUrl')\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return App.displayDlg('".__("Public OPML URL")."','pubOPMLUrl')\">".
|
||||
__('Display published OPML URL')."</button> ";
|
||||
|
||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
|
||||
@@ -1323,10 +1328,10 @@ class Pref_Feeds extends Handler_Protected {
|
||||
|
||||
print "<p>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('".__("View as RSS")."','generatedFeed', '$rss_url')\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return App.displayDlg('".__("Show as feed")."','generatedFeed', '$rss_url')\">".
|
||||
__('Display URL')."</button> ";
|
||||
|
||||
print "<button class=\"warning\" dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
|
||||
print "<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick=\"return Helpers.clearFeedAccessKeys()\">".
|
||||
__('Clear all generated URLs')."</button> ";
|
||||
|
||||
print "</p>";
|
||||
@@ -1412,9 +1417,9 @@ class Pref_Feeds extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Select')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"selectTableRows('prefInactiveFeedList', 'all')\"
|
||||
print "<div onclick=\"Tables.select('prefInactiveFeedList', true)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('All')."</div>";
|
||||
print "<div onclick=\"selectTableRows('prefInactiveFeedList', 'none')\"
|
||||
print "<div onclick=\"Tables.select('prefInactiveFeedList', false)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
print "</div>"; #toolbar
|
||||
@@ -1428,20 +1433,17 @@ class Pref_Feeds extends Handler_Protected {
|
||||
while ($line = $sth->fetch()) {
|
||||
|
||||
$feed_id = $line["id"];
|
||||
$this_row_id = "id=\"FUPDD-$feed_id\"";
|
||||
|
||||
# class needed for selectTableRows()
|
||||
print "<tr class=\"placeholder\" $this_row_id>";
|
||||
print "<tr class=\"placeholder\" data-row-id='$feed_id'>";
|
||||
|
||||
# id needed for selectTableRows()
|
||||
print "<td width='5%' align='center'><input
|
||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\" id=\"FUPDC-$feed_id\"></td>";
|
||||
onclick='Tables.onRowChecked(this);' dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\"></td>";
|
||||
print "<td>";
|
||||
|
||||
print "<a class=\"visibleLink\" href=\"#\" ".
|
||||
"title=\"".__("Click to edit feed")."\" ".
|
||||
"onclick=\"editFeed(".$line["id"].")\">".
|
||||
"onclick=\"CommonDialogs.editFeed(".$line["id"].")\">".
|
||||
htmlspecialchars($line["title"])."</a>";
|
||||
|
||||
print "</td><td class=\"insensitive\" align='right'>";
|
||||
@@ -1477,9 +1479,9 @@ class Pref_Feeds extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Select')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"selectTableRows('prefErrorFeedList', 'all')\"
|
||||
print "<div onclick=\"Tables.select('prefErrorFeedList', true)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('All')."</div>";
|
||||
print "<div onclick=\"selectTableRows('prefErrorFeedList', 'none')\"
|
||||
print "<div onclick=\"Tables.select('prefErrorFeedList', false)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
print "</div>"; #toolbar
|
||||
@@ -1493,20 +1495,17 @@ class Pref_Feeds extends Handler_Protected {
|
||||
while ($line = $sth->fetch()) {
|
||||
|
||||
$feed_id = $line["id"];
|
||||
$this_row_id = "id=\"FERDD-$feed_id\"";
|
||||
|
||||
# class needed for selectTableRows()
|
||||
print "<tr class=\"placeholder\" $this_row_id>";
|
||||
print "<tr class=\"placeholder\" data-row-id='$feed_id'>";
|
||||
|
||||
# id needed for selectTableRows()
|
||||
print "<td width='5%' align='center'><input
|
||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\" id=\"FERDC-$feed_id\"></td>";
|
||||
onclick='Tables.onRowChecked(this);' dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\"></td>";
|
||||
print "<td>";
|
||||
|
||||
print "<a class=\"visibleLink\" href=\"#\" ".
|
||||
"title=\"".__("Click to edit feed")."\" ".
|
||||
"onclick=\"editFeed(".$line["id"].")\">".
|
||||
"onclick=\"CommonDialogs.editFeed(".$line["id"].")\">".
|
||||
htmlspecialchars($line["title"])."</a>: ";
|
||||
|
||||
print "<span class=\"insensitive\">";
|
||||
|
||||
@@ -429,7 +429,7 @@ class Pref_Filters extends Handler_Protected {
|
||||
|
||||
$data = htmlspecialchars(json_encode($line));
|
||||
|
||||
print "<li><input dojoType='dijit.form.CheckBox' type='checkbox' onclick='toggleSelectListRow2(this)'>".
|
||||
print "<li><input dojoType='dijit.form.CheckBox' type='checkbox' onclick='Lists.onRowChecked(this)'>".
|
||||
"<span onclick=\"dijit.byId('filterEditDlg').editRule(this)\">".$this->getRuleName($line)."</span>".
|
||||
"<input type='hidden' name='rule[]' value=\"$data\"/></li>";
|
||||
}
|
||||
@@ -473,7 +473,7 @@ class Pref_Filters extends Handler_Protected {
|
||||
|
||||
$data = htmlspecialchars(json_encode($line));
|
||||
|
||||
print "<li><input dojoType='dijit.form.CheckBox' type='checkbox' onclick='toggleSelectListRow2(this)'>".
|
||||
print "<li><input dojoType='dijit.form.CheckBox' type='checkbox' onclick='Lists.onRowChecked(this)'>".
|
||||
"<span onclick=\"dijit.byId('filterEditDlg').editAction(this)\">".$this->getActionName($line)."</span>".
|
||||
"<input type='hidden' name='action[]' value=\"$data\"/></li>";
|
||||
}
|
||||
@@ -797,20 +797,20 @@ class Pref_Filters extends Handler_Protected {
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return quickAddFilter()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return Filters.quickAddFilter()\">".
|
||||
__('Create filter')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return joinSelectedFilters()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterTree').joinSelectedFilters()\">".
|
||||
__('Combine')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return editSelectedFilter()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterTree').editSelectedFilter()\">".
|
||||
__('Edit')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return resetFilterOrder()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterTree').resetFilterOrder()\">".
|
||||
__('Reset sort order')."</button> ";
|
||||
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return removeSelectedFilters()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterTree').removeSelectedFilters()\">".
|
||||
__('Remove')."</button> ";
|
||||
|
||||
print "</div>"; # toolbar
|
||||
@@ -840,7 +840,7 @@ class Pref_Filters extends Handler_Protected {
|
||||
var bare_id = id.substr(id.indexOf(':')+1);
|
||||
|
||||
if (id.match('FILTER:')) {
|
||||
editFilter(bare_id);
|
||||
dijit.byId('filterTree').editFilter(bare_id);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1044,7 +1044,7 @@ class Pref_Filters extends Handler_Protected {
|
||||
print "<div class=\"dlgSecCont\">";
|
||||
|
||||
print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
|
||||
onchange=\"filterDlgCheckAction(this)\">";
|
||||
onchange=\"Filters.filterDlgCheckAction(this)\">";
|
||||
|
||||
$res = $this->pdo->query("SELECT id,description FROM ttrss_filter_actions
|
||||
ORDER BY name");
|
||||
|
||||
@@ -275,13 +275,13 @@ class Pref_Labels extends Handler_Protected {
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
|
||||
print"<button dojoType=\"dijit.form.Button\" onclick=\"return addLabel()\">".
|
||||
print"<button dojoType=\"dijit.form.Button\" onclick=\"CommonDialogs.addLabel()\">".
|
||||
__('Create label')."</button dojoType=\"dijit.form.Button\"> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedLabels()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelTree').removeSelected()\">".
|
||||
__('Remove')."</button dojoType=\"dijit.form.Button\"> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"labelColorReset()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelTree').resetColors()\">".
|
||||
__('Clear colors')."</button dojoType=\"dijit.form.Button\">";
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ class Pref_Labels extends Handler_Protected {
|
||||
var bare_id = id.substr(id.indexOf(':')+1);
|
||||
|
||||
if (id.match('LABEL:')) {
|
||||
editLabel(bare_id);
|
||||
dijit.byId('labelTree').editLabel(bare_id);
|
||||
}
|
||||
</script>
|
||||
</div>";
|
||||
@@ -323,4 +323,4 @@ class Pref_Labels extends Handler_Protected {
|
||||
print "</div>"; #container
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-30
@@ -183,7 +183,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
|
||||
evt.preventDefault();
|
||||
if (this.validate()) {
|
||||
notify_progress('Saving data...', true);
|
||||
Notify.progress('Saving data...', true);
|
||||
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
@@ -249,12 +249,12 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
|
||||
evt.preventDefault();
|
||||
if (this.validate()) {
|
||||
notify_progress('Changing password...', true);
|
||||
Notify.progress('Changing password...', true);
|
||||
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify('');
|
||||
Notify.close();
|
||||
if (transport.responseText.indexOf('ERROR: ') == 0) {
|
||||
|
||||
$('pwd_change_infobox').innerHTML =
|
||||
@@ -316,14 +316,14 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
|
||||
evt.preventDefault();
|
||||
if (this.validate()) {
|
||||
notify_progress('Disabling OTP', true);
|
||||
Notify.progress('Disabling OTP', true);
|
||||
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify('');
|
||||
Notify.close();
|
||||
if (transport.responseText.indexOf('ERROR: ') == 0) {
|
||||
notify_error(transport.responseText.replace('ERROR: ', ''));
|
||||
Notify.error(transport.responseText.replace('ERROR: ', ''));
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -367,14 +367,14 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
|
||||
evt.preventDefault();
|
||||
if (this.validate()) {
|
||||
notify_progress('Saving data...', true);
|
||||
Notify.progress('Saving data...', true);
|
||||
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify('');
|
||||
Notify.close();
|
||||
if (transport.responseText.indexOf('ERROR:') == 0) {
|
||||
notify_error(transport.responseText.replace('ERROR:', ''));
|
||||
Notify.error(transport.responseText.replace('ERROR:', ''));
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -436,12 +436,12 @@ class Pref_Prefs extends Handler_Protected {
|
||||
onComplete: function(transport) {
|
||||
var msg = transport.responseText;
|
||||
if (quit) {
|
||||
gotoMain();
|
||||
document.location.href = 'index.php';
|
||||
} else {
|
||||
if (msg == 'PREFS_NEED_RELOAD') {
|
||||
window.location.reload();
|
||||
} else {
|
||||
notify_info(msg);
|
||||
Notify.info(msg);
|
||||
}
|
||||
}
|
||||
} });
|
||||
@@ -542,7 +542,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
} else if ($pref_name == "USER_STYLESHEET") {
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"customizeCSS()\">" . __('Customize') . "</button>";
|
||||
onclick=\"Helpers.customizeCSS()\">" . __('Customize') . "</button>";
|
||||
|
||||
} else if ($pref_name == "USER_CSS_THEME") {
|
||||
|
||||
@@ -608,11 +608,11 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<br/>";
|
||||
|
||||
print " <button dojoType=\"dijit.form.Button\" disabled=\"$has_serial\"
|
||||
onclick=\"insertSSLserial('$cert_serial')\">" .
|
||||
onclick=\"dijit.byId('SSL_CERT_SERIAL').attr('value', '$cert_serial')\">" .
|
||||
__('Register') . "</button>";
|
||||
|
||||
print " <button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"insertSSLserial('')\">" .
|
||||
onclick=\"dijit.byId('SSL_CERT_SERIAL').attr('value', '')\">" .
|
||||
__('Clear') . "</button>";
|
||||
|
||||
} else if ($pref_name == 'DIGEST_PREFERRED_TIME') {
|
||||
@@ -659,10 +659,10 @@ class Pref_Prefs extends Handler_Protected {
|
||||
</div>
|
||||
</div>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return editProfiles()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"return Helpers.editProfiles()\">".
|
||||
__('Manage profiles')."</button> ";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" class=\"btn-danger\" onclick=\"return validatePrefsReset()\">".
|
||||
print "<button dojoType=\"dijit.form.Button\" class=\"btn-danger\" onclick=\"return Helpers.confirmReset()\">".
|
||||
__('Reset to defaults')."</button>";
|
||||
|
||||
print " ";
|
||||
@@ -689,12 +689,12 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
|
||||
evt.preventDefault();
|
||||
if (this.validate()) {
|
||||
notify_progress('Saving data...', true);
|
||||
Notify.progress('Saving data...', true);
|
||||
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify('');
|
||||
Notify.close();
|
||||
if (confirm(__('Selected plugins have been enabled. Reload?'))) {
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -756,7 +756,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
|
||||
if (count($tmppluginhost->get_all($plugin)) > 0) {
|
||||
if (in_array($name, $system_enabled)) {
|
||||
print "<td><a href='#' onclick=\"clearPluginData('$name')\"
|
||||
print "<td><a href='#' onclick=\"Helpers.clearPluginData('$name')\"
|
||||
class='visibleLink'>".__("Clear data")."</a></td>";
|
||||
}
|
||||
}
|
||||
@@ -799,7 +799,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
|
||||
$plugin_icon = $checked ? "plugin.png" : "plugin_disabled.png";
|
||||
|
||||
print "<td align='center'><input id='FPCHK-$name' name='plugins[]' value='$name' onclick='toggleSelectRow2(this);'
|
||||
print "<td align='center'><input id='FPCHK-$name' name='plugins[]' value='$name' onclick='Tables.onRowChecked(this);'
|
||||
dojoType=\"dijit.form.CheckBox\" $checked $disabled
|
||||
type=\"checkbox\"></td>";
|
||||
|
||||
@@ -816,7 +816,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
|
||||
if (count($tmppluginhost->get_all($plugin)) > 0) {
|
||||
if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) {
|
||||
print "<td><a href='#' onclick=\"clearPluginData('$name')\" class='visibleLink'>".__("Clear data")."</a></td>";
|
||||
print "<td><a href='#' onclick=\"Helpers.clearPluginData('$name')\" class='visibleLink'>".__("Clear data")."</a></td>";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -992,9 +992,9 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Select')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"selectTableRows('prefFeedProfileList', 'all')\"
|
||||
print "<div onclick=\"Tables.select('prefFeedProfileList', true)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('All')."</div>";
|
||||
print "<div onclick=\"selectTableRows('prefFeedProfileList', 'none')\"
|
||||
print "<div onclick=\"Tables.select('prefFeedProfileList', false)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
|
||||
@@ -1019,11 +1019,10 @@ class Pref_Prefs extends Handler_Protected {
|
||||
print "<table width=\"100%\" class=\"prefFeedProfileList\"
|
||||
cellspacing=\"0\" id=\"prefFeedProfileList\">";
|
||||
|
||||
print "<tr class=\"placeholder\" id=\"FCATR-0\">"; #odd
|
||||
print "<tr class=\"placeholder\">"; # data-row-id='0' <-- no point, shouldn't be removed
|
||||
|
||||
print "<td width='5%' align='center'><input
|
||||
id='FCATC-0'
|
||||
onclick='toggleSelectRow2(this);'
|
||||
onclick='Tables.onRowChecked(this);'
|
||||
dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\"></td>";
|
||||
|
||||
@@ -1043,15 +1042,13 @@ class Pref_Prefs extends Handler_Protected {
|
||||
while ($line = $sth->fetch()) {
|
||||
|
||||
$profile_id = $line["id"];
|
||||
$this_row_id = "id=\"FCATR-$profile_id\"";
|
||||
|
||||
print "<tr class=\"placeholder\" $this_row_id>";
|
||||
print "<tr class=\"placeholder\" data-row-id='$profile_id'>";
|
||||
|
||||
$edit_title = htmlspecialchars($line["title"]);
|
||||
|
||||
print "<td width='5%' align='center'><input
|
||||
onclick='toggleSelectRow2(this);'
|
||||
id='FCATC-$profile_id'
|
||||
onclick='Tables.onRowChecked(this);'
|
||||
dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\"></td>";
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class Pref_System extends Handler_Protected {
|
||||
function index() {
|
||||
|
||||
print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
|
||||
print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Error Log')."\">";
|
||||
print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Event Log')."\">";
|
||||
|
||||
if (LOG_DESTINATION == "sql") {
|
||||
|
||||
@@ -37,10 +37,10 @@ class Pref_System extends Handler_Protected {
|
||||
LIMIT 100");
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"updateSystemList()\">".__('Refresh')."</button> ";
|
||||
onclick=\"Helpers.updateEventLog()\">".__('Refresh')."</button> ";
|
||||
|
||||
print " <button dojoType=\"dijit.form.Button\"
|
||||
onclick=\"clearSqlLog()\">".__('Clear log')."</button> ";
|
||||
class=\"btn-danger\" onclick=\"Helpers.clearEventLog()\">".__('Clear')."</button> ";
|
||||
|
||||
print "<p><table width=\"100%\" cellspacing=\"10\" class=\"prefErrorLog\">";
|
||||
|
||||
|
||||
+28
-33
@@ -218,12 +218,13 @@ class Pref_Users extends Handler_Protected {
|
||||
}
|
||||
|
||||
function add() {
|
||||
|
||||
$login = trim(clean($_REQUEST["login"]));
|
||||
$tmp_user_pwd = make_password(8);
|
||||
$salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
|
||||
$pwd_hash = encrypt_password($tmp_user_pwd, $salt, true);
|
||||
|
||||
if (!$login) return; // no blank usernames
|
||||
|
||||
$sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE
|
||||
login = ?");
|
||||
$sth->execute([$login]);
|
||||
@@ -243,18 +244,18 @@ class Pref_Users extends Handler_Protected {
|
||||
|
||||
$new_uid = $row['id'];
|
||||
|
||||
print format_notice(T_sprintf("Added user <b>%s</b> with password <b>%s</b>",
|
||||
$login, $tmp_user_pwd));
|
||||
print T_sprintf("Added user %s with password %s",
|
||||
$login, $tmp_user_pwd);
|
||||
|
||||
initialize_user($new_uid);
|
||||
|
||||
} else {
|
||||
|
||||
print format_warning(T_sprintf("Could not create user <b>%s</b>", $login));
|
||||
print T_sprintf("Could not create user %s", $login);
|
||||
|
||||
}
|
||||
} else {
|
||||
print format_warning(T_sprintf("User <b>%s</b> already exists.", $login));
|
||||
print T_sprintf("User %s already exists.", $login);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,9 +283,9 @@ class Pref_Users extends Handler_Protected {
|
||||
$sth->execute([$pwd_hash, $new_salt, $uid]);
|
||||
|
||||
if ($show_password) {
|
||||
print T_sprintf("Changed password of user <b>%s</b> to <b>%s</b>", $login, $tmp_user_pwd);
|
||||
print T_sprintf("Changed password of user %s to %s", $login, $tmp_user_pwd);
|
||||
} else {
|
||||
print_notice(T_sprintf("Sending new password of user <b>%s</b> to <b>%s</b>", $login, $email));
|
||||
print_notice(T_sprintf("Sending new password of user %s to %s", $login, $email));
|
||||
}
|
||||
|
||||
if ($email) {
|
||||
@@ -341,7 +342,7 @@ class Pref_Users extends Handler_Protected {
|
||||
print "<div style='float : right; padding-right : 4px;'>
|
||||
<input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\"
|
||||
value=\"$user_search\">
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"updateUsersList()\">".
|
||||
<button dojoType=\"dijit.form.Button\" oncl1ick=\"Users.reload()\">".
|
||||
__('Search')."</button>
|
||||
</div>";
|
||||
|
||||
@@ -354,20 +355,20 @@ class Pref_Users extends Handler_Protected {
|
||||
print "<div dojoType=\"dijit.form.DropDownButton\">".
|
||||
"<span>" . __('Select')."</span>";
|
||||
print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
|
||||
print "<div onclick=\"selectTableRows('prefUserList', 'all')\"
|
||||
print "<div onclick=\"Tables.select('prefUserList', true)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('All')."</div>";
|
||||
print "<div onclick=\"selectTableRows('prefUserList', 'none')\"
|
||||
print "<div onclick=\"Tables.select('prefUserList', false)\"
|
||||
dojoType=\"dijit.MenuItem\">".__('None')."</div>";
|
||||
print "</div></div>";
|
||||
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"addUser()\">".__('Create user')."</button>";
|
||||
print "<button dojoType=\"dijit.form.Button\" onclick=\"Users.add()\">".__('Create user')."</button>";
|
||||
|
||||
print "
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"editSelectedUser()\">".
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"Users.editSelected()\">".
|
||||
__('Edit')."</button dojoType=\"dijit.form.Button\">
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedUsers()\">".
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"Users.removeSelected()\">".
|
||||
__('Remove')."</button dojoType=\"dijit.form.Button\">
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"resetSelectedUserPass()\">".
|
||||
<button dojoType=\"dijit.form.Button\" onclick=\"Users.resetSelected()\">".
|
||||
__('Reset password')."</button dojoType=\"dijit.form.Button\">";
|
||||
|
||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
|
||||
@@ -400,11 +401,11 @@ class Pref_Users extends Handler_Protected {
|
||||
|
||||
print "<tr class=\"title\">
|
||||
<td align='center' width=\"5%\"> </td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('login')\">".__('Login')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('access_level')\">".__('Access Level')."</a></td>
|
||||
<td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">".__('Subscribed feeds')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('created')\">".__('Registered')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('last_login')\">".__('Last login')."</a></td></tr>";
|
||||
<td width='20%'><a href=\"#\" onclick=\"Users.reload('login')\">".__('Login')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"Users.reload('access_level')\">".__('Access Level')."</a></td>
|
||||
<td width='10%'><a href=\"#\" onclick=\"Users.reload('num_feeds')\">".__('Subscribed feeds')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"Users.reload('created')\">".__('Registered')."</a></td>
|
||||
<td width='20%'><a href=\"#\" onclick=\"Users.reload('last_login')\">".__('Last login')."</a></td></tr>";
|
||||
|
||||
$lnum = 0;
|
||||
|
||||
@@ -412,27 +413,21 @@ class Pref_Users extends Handler_Protected {
|
||||
|
||||
$uid = $line["id"];
|
||||
|
||||
print "<tr id=\"UMRR-$uid\">";
|
||||
print "<tr data-row-id=\"$uid\" onclick='Users.edit($uid)'>";
|
||||
|
||||
$line["login"] = htmlspecialchars($line["login"]);
|
||||
|
||||
$line["created"] = make_local_datetime($line["created"], false);
|
||||
$line["last_login"] = make_local_datetime($line["last_login"], false);
|
||||
|
||||
print "<td align='center'><input onclick='toggleSelectRow2(this);'
|
||||
dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"
|
||||
id=\"UMCHK-$uid\"></td>";
|
||||
print "<td align='center'><input onclick='Tables.onRowChecked(this); event.stopPropagation();'
|
||||
dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"></td>";
|
||||
|
||||
$onclick = "onclick='editUser($uid, event)' title='".__('Click to edit')."'";
|
||||
print "<td title='".__('Click to edit')."'><img src='images/user.png' class='marked-pic' alt=''> " . $line["login"] . "</td>";
|
||||
|
||||
print "<td $onclick><img src='images/user.png' class='marked-pic' alt=''> " . $line["login"] . "</td>";
|
||||
|
||||
if (!$line["email"]) $line["email"] = " ";
|
||||
|
||||
print "<td $onclick>" . $access_level_names[$line["access_level"]] . "</td>";
|
||||
print "<td $onclick>" . $line["num_feeds"] . "</td>";
|
||||
print "<td $onclick>" . $line["created"] . "</td>";
|
||||
print "<td $onclick>" . $line["last_login"] . "</td>";
|
||||
print "<td>" . $access_level_names[$line["access_level"]] . "</td>";
|
||||
print "<td>" . $line["num_feeds"] . "</td>";
|
||||
print "<td>" . $line["created"] . "</td>";
|
||||
print "<td>" . $line["last_login"] . "</td>";
|
||||
|
||||
print "</tr>";
|
||||
|
||||
|
||||
+24
-9
@@ -103,7 +103,7 @@
|
||||
margin-top : 4px;
|
||||
margin-bottom : 4px;
|
||||
|
||||
.collapse {
|
||||
.collapse, .excerpt {
|
||||
display : none;
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ div#floatingTitle {
|
||||
color : @default-text;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
.collapse, .excerpt {
|
||||
display : none;
|
||||
}
|
||||
|
||||
@@ -373,6 +373,15 @@ div#floatingTitle.Unread a.title {
|
||||
overflow : hidden;
|
||||
max-width : 500px;
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
white-space : nowrap;
|
||||
font-size : 11px;
|
||||
color : #999;
|
||||
font-weight : normal;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.cdm.expandable.Unread {
|
||||
@@ -410,12 +419,18 @@ div.cdm.expandable.Unread div.header a.title {
|
||||
color : black;
|
||||
}
|
||||
|
||||
div.cdm.expandable.active div.header a.title {
|
||||
color: @color-link;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-rendering: optimizelegibility;
|
||||
font-family: @fonts-ui-bold;
|
||||
div.cdm.expandable.active {
|
||||
.excerpt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.header a.title {
|
||||
color: @color-link;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-rendering: optimizelegibility;
|
||||
font-family: @fonts-ui-bold;
|
||||
}
|
||||
}
|
||||
|
||||
div.cdm.expandable:not(.active) {
|
||||
@@ -424,4 +439,4 @@ div.cdm.expandable:not(.active) {
|
||||
.content, .collapse {
|
||||
display : none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -910,6 +910,25 @@ body.ttrss_main {
|
||||
-webkit-overflow-scrolling : touch;
|
||||
-webkit-transform: translateZ(0);
|
||||
-webkit-backface-visibility: hidden;
|
||||
|
||||
div.feed-title {
|
||||
border: 0px solid @color-link;
|
||||
border-bottom-width: 1px;
|
||||
padding: 5px 3px 5px 5px;
|
||||
}
|
||||
|
||||
div.feed-title a.title {
|
||||
color: @default-text;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.feed-title a {
|
||||
color: @default-text;
|
||||
}
|
||||
|
||||
div.feed-title a:hover {
|
||||
color: @color-link;
|
||||
}
|
||||
}
|
||||
|
||||
#headlines-toolbar_splitter, #toolbar_splitter {
|
||||
|
||||
@@ -53,12 +53,10 @@
|
||||
$site_url = htmlspecialchars($line["site_url"]);
|
||||
$subscribers = $line["subscribers"];
|
||||
|
||||
$check_box = "<input onclick='toggleSelectListRow2(this)'
|
||||
$check_box = "<input onclick='Lists.onRowChecked(this)'
|
||||
dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\" \">";
|
||||
|
||||
$class = ($feedctr % 2) ? "even" : "odd";
|
||||
|
||||
$site_url = "<a target=\"_blank\" rel=\"noopener noreferrer\"
|
||||
href=\"$site_url\">
|
||||
<span class=\"fb_feedTitle\">".
|
||||
@@ -75,11 +73,9 @@
|
||||
$feed_url = htmlspecialchars($line["feed_url"]);
|
||||
$site_url = htmlspecialchars($line["site_url"]);
|
||||
|
||||
$check_box = "<input onclick='toggleSelectListRow2(this)' dojoType=\"dijit.form.CheckBox\"
|
||||
$check_box = "<input onclick='Lists.onRowChecked(this)' dojoType=\"dijit.form.CheckBox\"
|
||||
type=\"checkbox\">";
|
||||
|
||||
$class = ($feedctr % 2) ? "even" : "odd";
|
||||
|
||||
if ($line['articles_archived'] > 0) {
|
||||
$archived = sprintf(_ngettext("%d archived article", "%d archived articles", (int) $line['articles_archived']), $line['articles_archived']);
|
||||
$archived = " <span class='subscribers'>($archived)</span>";
|
||||
|
||||
+13
-50
@@ -1244,7 +1244,7 @@
|
||||
"g t" => "goto_tagcloud",
|
||||
"g *p" => "goto_prefs",
|
||||
// "other" => array(
|
||||
"(9)|Tab" => "select_article_cursor", // tab
|
||||
"r" => "select_article_cursor",
|
||||
"c l" => "create_label",
|
||||
"c f" => "create_filter",
|
||||
"c s" => "collapse_sidebar",
|
||||
@@ -1310,9 +1310,6 @@
|
||||
$data['last_article_id'] = Article::getLastArticleId();
|
||||
$data['cdm_expanded'] = get_pref('CDM_EXPANDED');
|
||||
|
||||
$data['dep_ts'] = calculate_dep_timestamp();
|
||||
$data['reload_on_ts_change'] = !defined('_NO_RELOAD_ON_TS_CHANGE');
|
||||
|
||||
$data["labels"] = Labels::get_all_labels($_SESSION["uid"]);
|
||||
|
||||
if (CHECK_FOR_UPDATES && !$disable_update_check && $_SESSION["last_version_check"] + 86400 + rand(-1000, 1000) < time()) {
|
||||
@@ -2379,52 +2376,6 @@
|
||||
return in_array($interface, class_implements($class));
|
||||
}
|
||||
|
||||
function get_minified_js($files) {
|
||||
|
||||
$rv = '';
|
||||
|
||||
foreach ($files as $js) {
|
||||
if (!isset($_GET['debug'])) {
|
||||
$cached_file = CACHE_DIR . "/js/".basename($js);
|
||||
|
||||
if (file_exists($cached_file) && is_readable($cached_file) && filemtime($cached_file) >= filemtime("js/$js")) {
|
||||
|
||||
list($header, $contents) = explode("\n", file_get_contents($cached_file), 2);
|
||||
|
||||
if ($header && $contents) {
|
||||
list($htag, $hversion) = explode(":", $header);
|
||||
|
||||
if ($htag == "tt-rss" && $hversion == VERSION) {
|
||||
$rv .= $contents;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$minified = JShrink\Minifier::minify(file_get_contents("js/$js"));
|
||||
file_put_contents($cached_file, "tt-rss:" . VERSION . "\n" . $minified);
|
||||
$rv .= $minified;
|
||||
|
||||
} else {
|
||||
$rv .= file_get_contents("js/$js"); // no cache in debug mode
|
||||
}
|
||||
}
|
||||
|
||||
return $rv;
|
||||
}
|
||||
|
||||
function calculate_dep_timestamp() {
|
||||
$files = array_merge(glob("js/*.js"), glob("css/*.css"));
|
||||
|
||||
$max_ts = -1;
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (filemtime($file) > $max_ts) $max_ts = filemtime($file);
|
||||
}
|
||||
|
||||
return $max_ts;
|
||||
}
|
||||
|
||||
function T_js_decl($s1, $s2) {
|
||||
if ($s1 && $s2) {
|
||||
$s1 = preg_replace("/\n/", "", $s1);
|
||||
@@ -2615,3 +2566,15 @@
|
||||
function arr_qmarks($arr) {
|
||||
return str_repeat('?,', count($arr) - 1) . '?';
|
||||
}
|
||||
|
||||
function get_scripts_timestamp() {
|
||||
$files = glob("js/*.js");
|
||||
$ts = 0;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$file_ts = filemtime($file);
|
||||
if ($file_ts > $ts) $ts = $file_ts;
|
||||
}
|
||||
|
||||
return $ts;
|
||||
}
|
||||
+26
-44
@@ -10,7 +10,7 @@
|
||||
foreach (array("lib/prototype.js",
|
||||
"lib/dojo/dojo.js",
|
||||
"lib/dojo/tt-rss-layer.js",
|
||||
"js/functions.js",
|
||||
"js/common.js",
|
||||
"errors.php?mode=js") as $jsfile) {
|
||||
|
||||
echo javascript_tag($jsfile);
|
||||
@@ -19,67 +19,49 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
require({cache:{}});
|
||||
Event.observe(window, 'load', function() {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="claro ttrss_main ttrss_login">
|
||||
|
||||
<script type="text/javascript">
|
||||
function init() {
|
||||
require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox','dijit/form/Form',
|
||||
'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){
|
||||
ready(function() {
|
||||
parser.parse();
|
||||
|
||||
require(['dojo/parser','dijit/form/Button','dijit/form/CheckBox','dijit/form/Form',
|
||||
'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser){
|
||||
parser.parse();
|
||||
//show tooltip node only after this widget is instaniated.
|
||||
dojo.query('div[dojoType="dijit.Tooltip"]').style({
|
||||
display:''
|
||||
});
|
||||
fetchProfiles();
|
||||
dijit.byId("bw_limit").attr("checked", getCookie("ttrss_bwlimit") == 'true');
|
||||
document.forms.loginForm.login.focus();
|
||||
});
|
||||
//show tooltip node only after this widget is instaniated.
|
||||
dojo.query('div[dojoType="dijit.Tooltip"]').style({
|
||||
display:''
|
||||
});
|
||||
|
||||
}
|
||||
fetchProfiles();
|
||||
dijit.byId("bw_limit").attr("checked", Cookie.get("ttrss_bwlimit") == 'true');
|
||||
document.forms.loginForm.login.focus();
|
||||
});
|
||||
});
|
||||
|
||||
function fetchProfiles() {
|
||||
try {
|
||||
var query = "op=getProfiles&login=" + param_escape(document.forms["loginForm"].login.value);
|
||||
const query = "op=getProfiles&login=" + encodeURIComponent(document.forms["loginForm"].login.value);
|
||||
|
||||
if (query) {
|
||||
new Ajax.Request("public.php", {
|
||||
parameters: query,
|
||||
onComplete: function(transport) {
|
||||
if (transport.responseText.match("select")) {
|
||||
$('profile_box').innerHTML = transport.responseText;
|
||||
//dojo.parser.parse('profile_box');
|
||||
}
|
||||
} });
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
exception_error("fetchProfiles", e);
|
||||
}
|
||||
new Ajax.Request("public.php", {
|
||||
parameters: query,
|
||||
onComplete: function(transport) {
|
||||
if (transport.responseText.match("select")) {
|
||||
$('profile_box').innerHTML = transport.responseText;
|
||||
//dojo.parser.parse('profile_box');
|
||||
}
|
||||
} });
|
||||
}
|
||||
|
||||
|
||||
function gotoRegForm() {
|
||||
window.location.href = "register.php";
|
||||
return false;
|
||||
}
|
||||
|
||||
function bwLimitChange(elem) {
|
||||
try {
|
||||
var limit_set = elem.checked;
|
||||
|
||||
setCookie("ttrss_bwlimit", limit_set,
|
||||
<?php print SESSION_COOKIE_LIFETIME ?>);
|
||||
|
||||
} catch (e) {
|
||||
exception_error("bwLimitChange", e);
|
||||
}
|
||||
Cookie.set("ttrss_bwlimit", elem.checked,
|
||||
<?php print SESSION_COOKIE_LIFETIME ?>);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -142,7 +124,7 @@ function bwLimitChange(elem) {
|
||||
</div>
|
||||
|
||||
<div dojoType="dijit.Tooltip" connectId="bw_limit_label" position="below" style="display:none">
|
||||
<?php echo __("Does not display images in articles, reduces automatic refreshes."); ?>
|
||||
<?php echo __("Does not display images in articles, reduces automatic refreshes."); ?>
|
||||
</div>
|
||||
|
||||
<?php if (SESSION_COOKIE_LIFETIME > 0) { ?>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<script>
|
||||
dojoConfig = {
|
||||
async: true,
|
||||
cacheBust: new Date(),
|
||||
cacheBust: "<?php echo get_scripts_timestamp(); ?>",
|
||||
packages: [
|
||||
{ name: "fox", location: "../../js" },
|
||||
]
|
||||
@@ -103,6 +103,8 @@
|
||||
"lib/scriptaculous/scriptaculous.js?load=effects,controls",
|
||||
"lib/dojo/dojo.js",
|
||||
"lib/dojo/tt-rss-layer.js",
|
||||
"js/tt-rss.js",
|
||||
"js/common.js",
|
||||
"errors.php?mode=js") as $jsfile) {
|
||||
|
||||
echo javascript_tag($jsfile);
|
||||
@@ -110,13 +112,9 @@
|
||||
} ?>
|
||||
|
||||
<script type="text/javascript">
|
||||
'use strict';
|
||||
require({cache:{}});
|
||||
<?php
|
||||
print get_minified_js(["tt-rss.js",
|
||||
"functions.js", "feedlist.js", "viewfeed.js", "PluginHost.js"]);
|
||||
?>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
|
||||
@@ -136,12 +134,6 @@
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="referrer" content="no-referrer"/>
|
||||
|
||||
<script type="text/javascript">
|
||||
Event.observe(window, 'load', function() {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="claro ttrss_main">
|
||||
@@ -187,7 +179,7 @@
|
||||
<form id="main_toolbar_form" action="" onsubmit='return false'>
|
||||
|
||||
<select name="view_mode" title="<?php echo __('Show articles') ?>"
|
||||
onchange="viewModeChanged()"
|
||||
onchange="App.onViewModeChanged()"
|
||||
dojoType="dijit.form.Select">
|
||||
<option selected="selected" value="adaptive"><?php echo __('Adaptive') ?></option>
|
||||
<option value="all_articles"><?php echo __('All Articles') ?></option>
|
||||
@@ -199,7 +191,7 @@
|
||||
</select>
|
||||
|
||||
<select title="<?php echo __('Sort articles') ?>"
|
||||
onchange="viewModeChanged()"
|
||||
onchange="App.onViewModeChanged()"
|
||||
dojoType="dijit.form.Select" name="order_by">
|
||||
<option selected="selected" value="default"><?php echo __('Default') ?></option>
|
||||
<option value="feed_dates"><?php echo __('Newest first') ?></option>
|
||||
@@ -207,16 +199,16 @@
|
||||
<option value="title"><?php echo __('Title') ?></option>
|
||||
</select>
|
||||
|
||||
<div dojoType="dijit.form.ComboButton" onclick="catchupCurrentFeed()">
|
||||
<div dojoType="dijit.form.ComboButton" onclick="Feeds.catchupCurrent()">
|
||||
<span><?php echo __('Mark as read') ?></span>
|
||||
<div dojoType="dijit.DropDownMenu">
|
||||
<div dojoType="dijit.MenuItem" onclick="catchupCurrentFeed('1day')">
|
||||
<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('1day')">
|
||||
<?php echo __('Older than one day') ?>
|
||||
</div>
|
||||
<div dojoType="dijit.MenuItem" onclick="catchupCurrentFeed('1week')">
|
||||
<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('1week')">
|
||||
<?php echo __('Older than one week') ?>
|
||||
</div>
|
||||
<div dojoType="dijit.MenuItem" onclick="catchupCurrentFeed('2week')">
|
||||
<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('2week')">
|
||||
<?php echo __('Older than two weeks') ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -240,18 +232,18 @@
|
||||
<div dojoType="dijit.form.DropDownButton">
|
||||
<span><?php echo __('Actions...') ?></span>
|
||||
<div dojoType="dijit.Menu" style="display: none">
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcPrefs')"><?php echo __('Preferences...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcSearch')"><?php echo __('Search...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcPrefs')"><?php echo __('Preferences...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcSearch')"><?php echo __('Search...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" disabled="1"><?php echo __('Feed actions:') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcAddFeed')"><?php echo __('Subscribe to feed...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcEditFeed')"><?php echo __('Edit this feed...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcRemoveFeed')"><?php echo __('Unsubscribe') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcAddFeed')"><?php echo __('Subscribe to feed...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcEditFeed')"><?php echo __('Edit this feed...') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcRemoveFeed')"><?php echo __('Unsubscribe') ?></div>
|
||||
<div dojoType="dijit.MenuItem" disabled="1"><?php echo __('All feeds:') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcCatchupAll')"><?php echo __('Mark as read') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcShowOnlyUnread')"><?php echo __('(Un)hide read feeds') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcCatchupAll')"><?php echo __('Mark as read') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcShowOnlyUnread')"><?php echo __('(Un)hide read feeds') ?></div>
|
||||
<div dojoType="dijit.MenuItem" disabled="1"><?php echo __('Other actions:') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcToggleWidescreen')"><?php echo __('Toggle widescreen mode') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcHKhelp')"><?php echo __('Keyboard shortcuts help') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcToggleWidescreen')"><?php echo __('Toggle widescreen mode') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcHKhelp')"><?php echo __('Keyboard shortcuts help') ?></div>
|
||||
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ACTION_ITEM) as $p) {
|
||||
@@ -260,7 +252,7 @@
|
||||
?>
|
||||
|
||||
<?php if (!$_SESSION["hide_logout"]) { ?>
|
||||
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcLogout')"><?php echo __('Logout') ?></div>
|
||||
<div dojoType="dijit.MenuItem" onclick="App.onActionSelected('qmcLogout')"><?php echo __('Logout') ?></div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+421
@@ -0,0 +1,421 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
return declare("fox.AppBase", null, {
|
||||
_initParams: [],
|
||||
_rpc_seq: 0,
|
||||
hotkey_prefix: 0,
|
||||
hotkey_prefix_pressed: false,
|
||||
hotkey_prefix_timeout: 0,
|
||||
constructor: function() {
|
||||
window.onerror = this.Error.onWindowError;
|
||||
},
|
||||
getInitParam: function(k) {
|
||||
return this._initParams[k];
|
||||
},
|
||||
setInitParam: function(k, v) {
|
||||
this._initParams[k] = v;
|
||||
},
|
||||
enableCsrfSupport: function() {
|
||||
Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap(
|
||||
function (callOriginal, options) {
|
||||
|
||||
if (App.getInitParam("csrf_token") != undefined) {
|
||||
Object.extend(options, options || { });
|
||||
|
||||
if (Object.isString(options.parameters))
|
||||
options.parameters = options.parameters.toQueryParams();
|
||||
else if (Object.isHash(options.parameters))
|
||||
options.parameters = options.parameters.toObject();
|
||||
|
||||
options.parameters["csrf_token"] = App.getInitParam("csrf_token");
|
||||
}
|
||||
|
||||
return callOriginal(options);
|
||||
}
|
||||
);
|
||||
},
|
||||
urlParam: function(param) {
|
||||
return String(window.location.href).parseQuery()[param];
|
||||
},
|
||||
next_seq: function() {
|
||||
this._rpc_seq += 1;
|
||||
return this._rpc_seq;
|
||||
},
|
||||
get_seq: function() {
|
||||
return this._rpc_seq;
|
||||
},
|
||||
setLoadingProgress: function(p) {
|
||||
loading_progress += p;
|
||||
|
||||
if (dijit.byId("loading_bar"))
|
||||
dijit.byId("loading_bar").update({progress: loading_progress});
|
||||
|
||||
if (loading_progress >= 90)
|
||||
Element.hide("overlay");
|
||||
|
||||
},
|
||||
keyeventToAction: function(event) {
|
||||
|
||||
const hotkeys_map = App.getInitParam("hotkeys");
|
||||
const keycode = event.which;
|
||||
const keychar = String.fromCharCode(keycode).toLowerCase();
|
||||
|
||||
if (keycode == 27) { // escape and drop prefix
|
||||
this.hotkey_prefix = false;
|
||||
}
|
||||
|
||||
if (keycode == 16 || keycode == 17) return; // ignore lone shift / ctrl
|
||||
|
||||
if (!this.hotkey_prefix && hotkeys_map[0].indexOf(keychar) != -1) {
|
||||
|
||||
this.hotkey_prefix = keychar;
|
||||
$("cmdline").innerHTML = keychar;
|
||||
Element.show("cmdline");
|
||||
|
||||
window.clearTimeout(this.hotkey_prefix_timeout);
|
||||
this.hotkey_prefix_timeout = window.setTimeout(() => {
|
||||
this.hotkey_prefix = false;
|
||||
Element.hide("cmdline");
|
||||
}, 3 * 1000);
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Element.hide("cmdline");
|
||||
|
||||
let hotkey_name = keychar.search(/[a-zA-Z0-9]/) != -1 ? keychar : "(" + keycode + ")";
|
||||
|
||||
// ensure ^*char notation
|
||||
if (event.shiftKey) hotkey_name = "*" + hotkey_name;
|
||||
if (event.ctrlKey) hotkey_name = "^" + hotkey_name;
|
||||
if (event.altKey) hotkey_name = "+" + hotkey_name;
|
||||
if (event.metaKey) hotkey_name = "%" + hotkey_name;
|
||||
|
||||
const hotkey_full = this.hotkey_prefix ? this.hotkey_prefix + " " + hotkey_name : hotkey_name;
|
||||
this.hotkey_prefix = false;
|
||||
|
||||
let action_name = false;
|
||||
|
||||
for (const sequence in hotkeys_map[1]) {
|
||||
if (hotkeys_map[1].hasOwnProperty(sequence)) {
|
||||
if (sequence == hotkey_full) {
|
||||
action_name = hotkeys_map[1][sequence];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('keyeventToAction', hotkey_full, '=>', action_name);
|
||||
|
||||
return action_name;
|
||||
},
|
||||
cleanupMemory: function(root) {
|
||||
const dijits = dojo.query("[widgetid]", dijit.byId(root).domNode).map(dijit.byNode);
|
||||
|
||||
dijits.each(function (d) {
|
||||
dojo.destroy(d.domNode);
|
||||
});
|
||||
|
||||
$$("#" + root + " *").each(function (i) {
|
||||
i.parentNode ? i.parentNode.removeChild(i) : true;
|
||||
});
|
||||
},
|
||||
helpDialog: function(topic) {
|
||||
const query = "backend.php?op=backend&method=help&topic=" + encodeURIComponent(topic);
|
||||
|
||||
if (dijit.byId("helpDlg"))
|
||||
dijit.byId("helpDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "helpDlg",
|
||||
title: __("Help"),
|
||||
style: "width: 600px",
|
||||
href: query,
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
displayDlg: function(title, id, param, callback) {
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
const query = {op: "dlg", method: id, param: param};
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
try {
|
||||
const content = transport.responseText;
|
||||
|
||||
let dialog = dijit.byId("infoBox");
|
||||
|
||||
if (!dialog) {
|
||||
dialog = new dijit.Dialog({
|
||||
title: title,
|
||||
id: 'infoBox',
|
||||
style: "width: 600px",
|
||||
onCancel: function () {
|
||||
return true;
|
||||
},
|
||||
onExecute: function () {
|
||||
return true;
|
||||
},
|
||||
onClose: function () {
|
||||
return true;
|
||||
},
|
||||
content: content
|
||||
});
|
||||
} else {
|
||||
dialog.attr('title', title);
|
||||
dialog.attr('content', content);
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
|
||||
Notify.close();
|
||||
|
||||
if (callback) callback(transport);
|
||||
} catch (e) {
|
||||
this.Error.report(e);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
handleRpcJson: function(transport) {
|
||||
|
||||
const netalert_dijit = dijit.byId("net-alert");
|
||||
let netalert = false;
|
||||
|
||||
if (netalert_dijit) netalert = netalert_dijit.domNode;
|
||||
|
||||
try {
|
||||
const reply = JSON.parse(transport.responseText);
|
||||
|
||||
if (reply) {
|
||||
|
||||
const error = reply['error'];
|
||||
|
||||
if (error) {
|
||||
const code = error['code'];
|
||||
const msg = error['msg'];
|
||||
|
||||
console.warn("[handleRpcJson] received fatal error " + code + "/" + msg);
|
||||
|
||||
if (code != 0) {
|
||||
fatalError(code, msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const seq = reply['seq'];
|
||||
|
||||
if (seq && this.get_seq() != seq) {
|
||||
console.log("[handleRpcJson] sequence mismatch: " + seq +
|
||||
" (want: " + this.get_seq() + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
const message = reply['message'];
|
||||
|
||||
if (message == "UPDATE_COUNTERS") {
|
||||
console.log("need to refresh counters...");
|
||||
App.setInitParam("last_article_id", -1);
|
||||
Feeds.requestCounters(true);
|
||||
}
|
||||
|
||||
const counters = reply['counters'];
|
||||
|
||||
if (counters)
|
||||
Feeds.parseCounters(counters);
|
||||
|
||||
const runtime_info = reply['runtime-info'];
|
||||
|
||||
if (runtime_info)
|
||||
App.parseRuntimeInfo(runtime_info);
|
||||
|
||||
if (netalert) netalert.hide();
|
||||
|
||||
return reply;
|
||||
|
||||
} else {
|
||||
if (netalert)
|
||||
netalert.show();
|
||||
else
|
||||
Notify.error("Communication problem with server.");
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
if (netalert)
|
||||
netalert.show();
|
||||
else
|
||||
Notify.error("Communication problem with server.");
|
||||
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
parseRuntimeInfo: function(data) {
|
||||
for (const k in data) {
|
||||
if (data.hasOwnProperty(k)) {
|
||||
const v = data[k];
|
||||
|
||||
console.log("RI:", k, "=>", v);
|
||||
|
||||
if (k == "daemon_is_running" && v != 1) {
|
||||
Notify.error("<span onclick=\"App.explainError(1)\">Update daemon is not running.</span>", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == "update_result") {
|
||||
const updatesIcon = dijit.byId("updatesIcon").domNode;
|
||||
|
||||
if (v) {
|
||||
Element.show(updatesIcon);
|
||||
} else {
|
||||
Element.hide(updatesIcon);
|
||||
}
|
||||
}
|
||||
|
||||
if (k == "daemon_stamp_ok" && v != 1) {
|
||||
Notify.error("<span onclick=\"App.explainError(3)\">Update daemon is not updating feeds.</span>", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == "max_feed_id" || k == "num_feeds") {
|
||||
if (App.getInitParam(k) != v) {
|
||||
console.log("feed count changed, need to reload feedlist.");
|
||||
Feeds.reload();
|
||||
}
|
||||
}
|
||||
|
||||
this.setInitParam(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
PluginHost.run(PluginHost.HOOK_RUNTIME_INFO_LOADED, data);
|
||||
},
|
||||
backendSanityCallback: function (transport) {
|
||||
|
||||
const reply = JSON.parse(transport.responseText);
|
||||
|
||||
if (!reply) {
|
||||
fatalError(3, "Sanity check: invalid RPC reply", transport.responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
const error_code = reply['error']['code'];
|
||||
|
||||
if (error_code && error_code != 0) {
|
||||
return fatalError(error_code, reply['error']['message']);
|
||||
}
|
||||
|
||||
console.log("sanity check ok");
|
||||
|
||||
const params = reply['init-params'];
|
||||
|
||||
if (params) {
|
||||
console.log('reading init-params...');
|
||||
|
||||
for (const k in params) {
|
||||
if (params.hasOwnProperty(k)) {
|
||||
switch (k) {
|
||||
case "label_base_index":
|
||||
_label_base_index = parseInt(params[k]);
|
||||
break;
|
||||
case "hotkeys":
|
||||
// filter mnemonic definitions (used for help panel) from hotkeys map
|
||||
// i.e. *(191)|Ctrl-/ -> *(191)
|
||||
|
||||
const tmp = [];
|
||||
for (const sequence in params[k][1]) {
|
||||
if (params[k][1].hasOwnProperty(sequence)) {
|
||||
const filtered = sequence.replace(/\|.*$/, "");
|
||||
tmp[filtered] = params[k][1][sequence];
|
||||
}
|
||||
}
|
||||
|
||||
params[k][1] = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("IP:", k, "=>", params[k]);
|
||||
this.setInitParam(k, params[k]);
|
||||
}
|
||||
}
|
||||
|
||||
// PluginHost might not be available on non-index pages
|
||||
if (typeof PluginHost !== 'undefined')
|
||||
PluginHost.run(PluginHost.HOOK_PARAMS_LOADED, App._initParams);
|
||||
}
|
||||
|
||||
this.initSecondStage();
|
||||
},
|
||||
explainError: function(code) {
|
||||
return this.displayDlg(__("Error explained"), "explainError", code);
|
||||
},
|
||||
Error: {
|
||||
report: function(error, params) {
|
||||
params = params || {};
|
||||
|
||||
if (!error) return;
|
||||
|
||||
console.error("[Error.report]", error, params);
|
||||
|
||||
const message = params.message ? params.message : error.toString();
|
||||
|
||||
try {
|
||||
xhrPost("backend.php",
|
||||
{op: "rpc", method: "log",
|
||||
file: params.filename ? params.filename : error.fileName,
|
||||
line: params.lineno ? params.lineno : error.lineNumber,
|
||||
msg: message,
|
||||
context: error.stack},
|
||||
(transport) => {
|
||||
console.warn("[Error.report] log response", transport.responseText);
|
||||
});
|
||||
} catch (re) {
|
||||
console.error("[Error.report] exception while saving logging error on server", re);
|
||||
}
|
||||
|
||||
try {
|
||||
if (dijit.byId("exceptionDlg"))
|
||||
dijit.byId("exceptionDlg").destroyRecursive();
|
||||
|
||||
let content = "<div class='fatalError'><p>" + message + "</p>";
|
||||
|
||||
if (error.stack)
|
||||
content += "<div><b>Stack trace:</b></div>" +
|
||||
"<textarea name=\"stack\" readonly=\"1\">" + error.stack + "</textarea>";
|
||||
|
||||
content += "<div style='text-align : center'>";
|
||||
|
||||
content += "<button dojoType=\"dijit.form.Button\" " +
|
||||
"onclick=\"dijit.byId('exceptionDlg').hide()\">" +
|
||||
__('Close this window') + "</button>";
|
||||
content += "</div>";
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "exceptionDlg",
|
||||
title: "Unhandled exception",
|
||||
style: "width: 600px",
|
||||
content: content
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
} catch (de) {
|
||||
console.error("[Error.report] exception while showing error dialog", de);
|
||||
|
||||
alert(error.stack ? error.stack : message);
|
||||
}
|
||||
|
||||
},
|
||||
onWindowError: function (message, filename, lineno, colno, error) {
|
||||
// called without context (this) from window.onerror
|
||||
App.Error.report(error,
|
||||
{message: message, filename: filename, lineno: lineno, colno: colno});
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
Article = {
|
||||
_active_article_id: 0,
|
||||
selectionSetScore: function () {
|
||||
const ids = Headlines.getSelected();
|
||||
|
||||
if (ids.length > 0) {
|
||||
console.log(ids);
|
||||
|
||||
const score = prompt(__("Please enter new score for selected articles:"));
|
||||
|
||||
if (score != undefined) {
|
||||
const query = {
|
||||
op: "article", method: "setScore", id: ids.toString(),
|
||||
score: score
|
||||
};
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
if (reply) {
|
||||
reply.id.each((id) => {
|
||||
const row = $("RROW-" + id);
|
||||
|
||||
if (row) {
|
||||
const pic = row.getElementsByClassName("score-pic")[0];
|
||||
|
||||
if (pic) {
|
||||
pic.src = pic.src.replace(/score_.*?\.png/,
|
||||
reply["score_pic"]);
|
||||
pic.setAttribute("score", reply["score"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No articles selected."));
|
||||
}
|
||||
},
|
||||
setScore: function (id, pic) {
|
||||
const score = pic.getAttribute("score");
|
||||
|
||||
const new_score = prompt(__("Please enter new score for this article:"), score);
|
||||
|
||||
if (new_score != undefined) {
|
||||
const query = {op: "article", method: "setScore", id: id, score: new_score};
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
if (reply) {
|
||||
pic.src = pic.src.replace(/score_.*?\.png/, reply["score_pic"]);
|
||||
pic.setAttribute("score", new_score);
|
||||
pic.setAttribute("title", new_score);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
cdmUnsetActive: function (event) {
|
||||
const row = $("RROW-" + Article.getActive());
|
||||
|
||||
if (row) {
|
||||
row.removeClassName("active");
|
||||
const cb = dijit.getEnclosingWidget(row.select(".rchk")[0]);
|
||||
|
||||
if (cb && !row.hasClassName("Selected"))
|
||||
cb.attr("checked", false);
|
||||
|
||||
Article.setActive(0);
|
||||
|
||||
if (event)
|
||||
event.stopPropagation();
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
close: function () {
|
||||
if (dijit.byId("content-insert"))
|
||||
dijit.byId("headlines-wrap-inner").removeChild(
|
||||
dijit.byId("content-insert"));
|
||||
},
|
||||
displayUrl: function (id) {
|
||||
const query = {op: "rpc", method: "getlinktitlebyid", id: id};
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
if (reply && reply.link) {
|
||||
prompt(__("Article URL:"), reply.link);
|
||||
}
|
||||
});
|
||||
},
|
||||
openInNewWindow: function (id) {
|
||||
const w = window.open("");
|
||||
w.opener = null;
|
||||
w.location = "backend.php?op=article&method=redirect&id=" + id;
|
||||
|
||||
Article.setActive(id);
|
||||
},
|
||||
render: function (article) {
|
||||
App.cleanupMemory("content-insert");
|
||||
|
||||
dijit.byId("headlines-wrap-inner").addChild(
|
||||
dijit.byId("content-insert"));
|
||||
|
||||
const c = dijit.byId("content-insert");
|
||||
|
||||
try {
|
||||
c.domNode.scrollTop = 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
c.attr('content', article);
|
||||
PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED, c.domNode);
|
||||
|
||||
Headlines.correctHeadlinesOffset(Article.getActive());
|
||||
|
||||
try {
|
||||
c.focus();
|
||||
} catch (e) {
|
||||
}
|
||||
},
|
||||
view: function (id, noexpand) {
|
||||
this.setActive(id);
|
||||
|
||||
if (!noexpand) {
|
||||
console.log("loading article", id);
|
||||
|
||||
const cids = [];
|
||||
|
||||
/* only request uncached articles */
|
||||
|
||||
this.getRelativeIds(id).each((n) => {
|
||||
if (!ArticleCache.get(n))
|
||||
cids.push(n);
|
||||
});
|
||||
|
||||
const cached_article = ArticleCache.get(id);
|
||||
|
||||
if (cached_article) {
|
||||
console.log('rendering cached', id);
|
||||
this.render(cached_article);
|
||||
return false;
|
||||
}
|
||||
|
||||
xhrPost("backend.php", {op: "article", method: "view", id: id, cids: cids.toString()}, (transport) => {
|
||||
try {
|
||||
const reply = App.handleRpcJson(transport);
|
||||
|
||||
if (reply) {
|
||||
|
||||
reply.each(function (article) {
|
||||
if (Article.getActive() == article['id']) {
|
||||
Article.render(article['content']);
|
||||
}
|
||||
ArticleCache.set(article['id'], article['content']);
|
||||
});
|
||||
|
||||
} else {
|
||||
console.error("Invalid object received: " + transport.responseText);
|
||||
|
||||
Article.render("<div class='whiteBox'>" +
|
||||
__('Could not display article (invalid object received - see error console for details)') + "</div>");
|
||||
}
|
||||
|
||||
//const unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length;
|
||||
//request_counters(unread_in_buffer == 0);
|
||||
|
||||
Notify.close();
|
||||
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
editTags: function (id) {
|
||||
const query = "backend.php?op=article&method=editArticleTags¶m=" + encodeURIComponent(id);
|
||||
|
||||
if (dijit.byId("editTagsDlg"))
|
||||
dijit.byId("editTagsDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "editTagsDlg",
|
||||
title: __("Edit article Tags"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Notify.progress("Saving article tags...", true);
|
||||
|
||||
xhrPost("backend.php", this.attr('value'), (transport) => {
|
||||
try {
|
||||
Notify.close();
|
||||
dialog.hide();
|
||||
|
||||
const data = JSON.parse(transport.responseText);
|
||||
|
||||
if (data) {
|
||||
const id = data.id;
|
||||
|
||||
const tags = $("ATSTR-" + id);
|
||||
const tooltip = dijit.byId("ATSTRTIP-" + id);
|
||||
|
||||
if (tags) tags.innerHTML = data.content;
|
||||
if (tooltip) tooltip.attr('label', data.content_full);
|
||||
}
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
const tmph = dojo.connect(dialog, 'onLoad', function () {
|
||||
dojo.disconnect(tmph);
|
||||
|
||||
new Ajax.Autocompleter('tags_str', 'tags_choices',
|
||||
"backend.php?op=article&method=completeTags",
|
||||
{tokens: ',', paramName: "search"});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
cdmScrollToId: function (id, force) {
|
||||
const ctr = $("headlines-frame");
|
||||
const e = $("RROW-" + id);
|
||||
|
||||
if (!e || !ctr) return;
|
||||
|
||||
if (force || e.offsetTop + e.offsetHeight > (ctr.scrollTop + ctr.offsetHeight) ||
|
||||
e.offsetTop < ctr.scrollTop) {
|
||||
|
||||
// expanded cdm has a 4px margin now
|
||||
ctr.scrollTop = parseInt(e.offsetTop) - 4;
|
||||
|
||||
Element.hide("floatingTitle");
|
||||
}
|
||||
},
|
||||
setActive: function (id) {
|
||||
console.log("setActive", id);
|
||||
|
||||
$$("div[id*=RROW][class*=active]").each((e) => {
|
||||
e.removeClassName("active");
|
||||
|
||||
if (!e.hasClassName("Selected")) {
|
||||
const cb = dijit.getEnclosingWidget(e.select(".rchk")[0]);
|
||||
if (cb) cb.attr("checked", false);
|
||||
}
|
||||
});
|
||||
|
||||
this._active_article_id = id;
|
||||
|
||||
const row = $("RROW-" + id);
|
||||
|
||||
if (row) {
|
||||
if (row.hasAttribute("data-content")) {
|
||||
console.log("unpacking: " + row.id);
|
||||
|
||||
row.select(".content-inner")[0].innerHTML = row.getAttribute("data-content");
|
||||
row.removeAttribute("data-content");
|
||||
|
||||
PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED_CDM, row);
|
||||
}
|
||||
|
||||
if (row.hasClassName("Unread")) {
|
||||
|
||||
Headlines.catchupBatched(() => {
|
||||
Feeds.decrementFeedCounter(Feeds.getActive(), Feeds.activeIsCat());
|
||||
Headlines.toggleUnread(id, 0);
|
||||
Headlines.updateFloatingTitle(true);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
row.addClassName("active");
|
||||
|
||||
if (!row.hasClassName("Selected")) {
|
||||
const cb = dijit.getEnclosingWidget(row.select(".rchk")[0]);
|
||||
if (cb) cb.attr("checked", true);
|
||||
}
|
||||
|
||||
PluginHost.run(PluginHost.HOOK_ARTICLE_SET_ACTIVE, this._active_article_id);
|
||||
}
|
||||
|
||||
Headlines.updateSelectedPrompt();
|
||||
},
|
||||
getActive: function () {
|
||||
return this._active_article_id;
|
||||
},
|
||||
scroll: function (offset) {
|
||||
if (!App.isCombinedMode()) {
|
||||
const ci = $("content-insert");
|
||||
if (ci) {
|
||||
ci.scrollTop += offset;
|
||||
}
|
||||
} else {
|
||||
const hi = $("headlines-frame");
|
||||
if (hi) {
|
||||
hi.scrollTop += offset;
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
getRelativeIds: function (id, limit) {
|
||||
|
||||
const tmp = [];
|
||||
|
||||
if (!limit) limit = 6; //3
|
||||
|
||||
const ids = Headlines.getLoaded();
|
||||
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
if (ids[i] == id) {
|
||||
for (let k = 1; k <= limit; k++) {
|
||||
//if (i > k-1) tmp.push(ids[i-k]);
|
||||
if (i < ids.length - k) tmp.push(ids[i + k]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
},
|
||||
mouseIn: function (id) {
|
||||
this.post_under_pointer = id;
|
||||
},
|
||||
mouseOut: function (id) {
|
||||
this.post_under_pointer = false;
|
||||
},
|
||||
getUnderPointer: function () {
|
||||
return this.post_under_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
return Article;
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
ArticleCache = {
|
||||
has_storage: 'sessionStorage' in window && window['sessionStorage'] !== null,
|
||||
set: function (id, obj) {
|
||||
if (this.has_storage)
|
||||
try {
|
||||
sessionStorage["article:" + id] = obj;
|
||||
} catch (e) {
|
||||
sessionStorage.clear();
|
||||
}
|
||||
},
|
||||
get: function (id) {
|
||||
if (this.has_storage)
|
||||
return sessionStorage["article:" + id];
|
||||
},
|
||||
clear: function () {
|
||||
if (this.has_storage)
|
||||
sessionStorage.clear();
|
||||
},
|
||||
del: function (id) {
|
||||
if (this.has_storage)
|
||||
sessionStorage.removeItem("article:" + id);
|
||||
},
|
||||
}
|
||||
|
||||
return ArticleCache;
|
||||
});
|
||||
@@ -0,0 +1,449 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
CommonDialogs = {
|
||||
closeInfoBox: function() {
|
||||
const dialog = dijit.byId("infoBox");
|
||||
if (dialog) dialog.hide();
|
||||
},
|
||||
uploadIconHandler: function(rc) {
|
||||
switch (rc) {
|
||||
case 0:
|
||||
Notify.info("Upload complete.");
|
||||
if (App.isPrefs()) {
|
||||
Feeds.reload();
|
||||
} else {
|
||||
setTimeout('Feeds.reload(false, false)', 50);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
Notify.error("Upload failed: icon is too big.");
|
||||
break;
|
||||
case 2:
|
||||
Notify.error("Upload failed.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
removeFeedIcon: function(id) {
|
||||
if (confirm(__("Remove stored feed icon?"))) {
|
||||
Notify.progress("Removing feed icon...", true);
|
||||
|
||||
const query = {op: "pref-feeds", method: "removeicon", feed_id: id};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.info("Feed icon removed.");
|
||||
if (App.isPrefs()) {
|
||||
Feeds.reload();
|
||||
} else {
|
||||
setTimeout('Feeds.reload(false, false)', 50);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
uploadFeedIcon: function() {
|
||||
const file = $("icon_file");
|
||||
|
||||
if (file.value.length == 0) {
|
||||
alert(__("Please select an image file to upload."));
|
||||
} else if (confirm(__("Upload new icon for this feed?"))) {
|
||||
Notify.progress("Uploading, please wait...", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
quickAddFeed: function() {
|
||||
const query = "backend.php?op=feeds&method=quickAddFeed";
|
||||
|
||||
// overlapping widgets
|
||||
if (dijit.byId("batchSubDlg")) dijit.byId("batchSubDlg").destroyRecursive();
|
||||
if (dijit.byId("feedAddDlg")) dijit.byId("feedAddDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "feedAddDlg",
|
||||
title: __("Subscribe to Feed"),
|
||||
style: "width: 600px",
|
||||
show_error: function (msg) {
|
||||
const elem = $("fadd_error_message");
|
||||
|
||||
elem.innerHTML = msg;
|
||||
|
||||
if (!Element.visible(elem))
|
||||
new Effect.Appear(elem);
|
||||
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
console.log(dojo.objectToQuery(this.attr('value')));
|
||||
|
||||
const feed_url = this.attr('value').feed;
|
||||
|
||||
Element.show("feed_add_spinner");
|
||||
Element.hide("fadd_error_message");
|
||||
|
||||
xhrPost("backend.php", this.attr('value'), (transport) => {
|
||||
try {
|
||||
|
||||
try {
|
||||
var reply = JSON.parse(transport.responseText);
|
||||
} catch (e) {
|
||||
Element.hide("feed_add_spinner");
|
||||
alert(__("Failed to parse output. This can indicate server timeout and/or network issues. Backend output was logged to browser console."));
|
||||
console.log('quickAddFeed, backend returned:' + transport.responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
const rc = reply['result'];
|
||||
|
||||
Notify.close();
|
||||
Element.hide("feed_add_spinner");
|
||||
|
||||
console.log(rc);
|
||||
|
||||
switch (parseInt(rc['code'])) {
|
||||
case 1:
|
||||
dialog.hide();
|
||||
Notify.info(__("Subscribed to %s").replace("%s", feed_url));
|
||||
|
||||
Feeds.reload();
|
||||
break;
|
||||
case 2:
|
||||
dialog.show_error(__("Specified URL seems to be invalid."));
|
||||
break;
|
||||
case 3:
|
||||
dialog.show_error(__("Specified URL doesn't seem to contain any feeds."));
|
||||
break;
|
||||
case 4:
|
||||
const feeds = rc['feeds'];
|
||||
|
||||
Element.show("fadd_multiple_notify");
|
||||
|
||||
const select = dijit.byId("feedDlg_feedContainerSelect");
|
||||
|
||||
while (select.getOptions().length > 0)
|
||||
select.removeOption(0);
|
||||
|
||||
select.addOption({value: '', label: __("Expand to select feed")});
|
||||
|
||||
let count = 0;
|
||||
for (const feedUrl in feeds) {
|
||||
if (feeds.hasOwnProperty(feedUrl)) {
|
||||
select.addOption({value: feedUrl, label: feeds[feedUrl]});
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
Effect.Appear('feedDlg_feedsContainer', {duration: 0.5});
|
||||
|
||||
break;
|
||||
case 5:
|
||||
dialog.show_error(__("Couldn't download the specified URL: %s").replace("%s", rc['message']));
|
||||
break;
|
||||
case 6:
|
||||
dialog.show_error(__("XML validation failed: %s").replace("%s", rc['message']));
|
||||
break;
|
||||
case 0:
|
||||
dialog.show_error(__("You are already subscribed to this feed."));
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error(transport.responseText);
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
showFeedsWithErrors: function() {
|
||||
const query = {op: "pref-feeds", method: "feedsWithErrors"};
|
||||
|
||||
if (dijit.byId("errorFeedsDlg"))
|
||||
dijit.byId("errorFeedsDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "errorFeedsDlg",
|
||||
title: __("Feeds with update errors"),
|
||||
style: "width: 600px",
|
||||
getSelectedFeeds: function () {
|
||||
return Tables.getSelected("prefErrorFeedList");
|
||||
},
|
||||
removeSelected: function () {
|
||||
const sel_rows = this.getSelectedFeeds();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected feeds?"))) {
|
||||
Notify.progress("Removing selected feeds...", true);
|
||||
|
||||
const query = {
|
||||
op: "pref-feeds", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.close();
|
||||
dialog.hide();
|
||||
Feeds.reload();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No feeds selected."));
|
||||
}
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
//
|
||||
}
|
||||
},
|
||||
href: "backend.php?" + dojo.objectToQuery(query)
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
feedBrowser: function() {
|
||||
const query = {op: "feeds", method: "feedBrowser"};
|
||||
|
||||
if (dijit.byId("feedAddDlg"))
|
||||
dijit.byId("feedAddDlg").hide();
|
||||
|
||||
if (dijit.byId("feedBrowserDlg"))
|
||||
dijit.byId("feedBrowserDlg").destroyRecursive();
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "feedBrowserDlg",
|
||||
title: __("More Feeds"),
|
||||
style: "width: 600px",
|
||||
getSelectedFeedIds: function () {
|
||||
const list = $$("#browseFeedList li[id*=FBROW]");
|
||||
const selected = [];
|
||||
|
||||
list.each(function (child) {
|
||||
const id = child.id.replace("FBROW-", "");
|
||||
|
||||
if (child.hasClassName('Selected')) {
|
||||
selected.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
return selected;
|
||||
},
|
||||
getSelectedFeeds: function () {
|
||||
const list = $$("#browseFeedList li.Selected");
|
||||
const selected = [];
|
||||
|
||||
list.each(function (child) {
|
||||
const title = child.getElementsBySelector("span.fb_feedTitle")[0].innerHTML;
|
||||
const url = child.getElementsBySelector("a.fb_feedUrl")[0].href;
|
||||
|
||||
selected.push([title, url]);
|
||||
|
||||
});
|
||||
|
||||
return selected;
|
||||
},
|
||||
|
||||
subscribe: function () {
|
||||
const mode = this.attr('value').mode;
|
||||
let selected = [];
|
||||
|
||||
if (mode == "1")
|
||||
selected = this.getSelectedFeeds();
|
||||
else
|
||||
selected = this.getSelectedFeedIds();
|
||||
|
||||
if (selected.length > 0) {
|
||||
dijit.byId("feedBrowserDlg").hide();
|
||||
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
const query = {
|
||||
op: "rpc", method: "massSubscribe",
|
||||
payload: JSON.stringify(selected), mode: mode
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.close();
|
||||
Feeds.reload();
|
||||
});
|
||||
|
||||
} else {
|
||||
alert(__("No feeds selected."));
|
||||
}
|
||||
|
||||
},
|
||||
update: function () {
|
||||
Element.show('feed_browser_spinner');
|
||||
|
||||
xhrPost("backend.php", dialog.attr("value"), (transport) => {
|
||||
Notify.close();
|
||||
|
||||
Element.hide('feed_browser_spinner');
|
||||
|
||||
const reply = JSON.parse(transport.responseText);
|
||||
const mode = reply['mode'];
|
||||
|
||||
if ($("browseFeedList") && reply['content']) {
|
||||
$("browseFeedList").innerHTML = reply['content'];
|
||||
}
|
||||
|
||||
dojo.parser.parse("browseFeedList");
|
||||
|
||||
if (mode == 2) {
|
||||
Element.show(dijit.byId('feed_archive_remove').domNode);
|
||||
} else {
|
||||
Element.hide(dijit.byId('feed_archive_remove').domNode);
|
||||
}
|
||||
});
|
||||
},
|
||||
removeFromArchive: function () {
|
||||
const selected = this.getSelectedFeedIds();
|
||||
|
||||
if (selected.length > 0) {
|
||||
if (confirm(__("Remove selected feeds from the archive? Feeds with stored articles will not be removed."))) {
|
||||
Element.show('feed_browser_spinner');
|
||||
|
||||
const query = {op: "rpc", method: "remarchive", ids: selected.toString()};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
dialog.update();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
this.subscribe();
|
||||
}
|
||||
},
|
||||
href: "backend.php?" + dojo.objectToQuery(query)
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
addLabel: function(select, callback) {
|
||||
const caption = prompt(__("Please enter label caption:"), "");
|
||||
|
||||
if (caption != undefined && caption.trim().length > 0) {
|
||||
|
||||
const query = {op: "pref-labels", method: "add", caption: caption.trim()};
|
||||
|
||||
if (select)
|
||||
Object.extend(query, {output: "select"});
|
||||
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
if (callback) {
|
||||
callback(transport);
|
||||
} else if (App.isPrefs()) {
|
||||
dijit.byId("labelTree").reload();
|
||||
} else {
|
||||
Feeds.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
unsubscribeFeed: function(feed_id, title) {
|
||||
|
||||
const msg = __("Unsubscribe from %s?").replace("%s", title);
|
||||
|
||||
if (title == undefined || confirm(msg)) {
|
||||
Notify.progress("Removing feed...");
|
||||
|
||||
const query = {op: "pref-feeds", quiet: 1, method: "remove", ids: feed_id};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
if (dijit.byId("feedEditDlg")) dijit.byId("feedEditDlg").hide();
|
||||
|
||||
if (App.isPrefs()) {
|
||||
Feeds.reload();
|
||||
} else {
|
||||
if (feed_id == Feeds.getActive())
|
||||
setTimeout(() => {
|
||||
Feeds.open({feed: -5})
|
||||
},
|
||||
100);
|
||||
|
||||
if (feed_id < 0) Feeds.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
editFeed: function (feed) {
|
||||
if (feed <= 0)
|
||||
return alert(__("You can't edit this kind of feed."));
|
||||
|
||||
const query = {op: "pref-feeds", method: "editfeed", id: feed};
|
||||
|
||||
console.log("editFeed", query);
|
||||
|
||||
if (dijit.byId("filterEditDlg"))
|
||||
dijit.byId("filterEditDlg").destroyRecursive();
|
||||
|
||||
if (dijit.byId("feedEditDlg"))
|
||||
dijit.byId("feedEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "feedEditDlg",
|
||||
title: __("Edit Feed"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Notify.progress("Saving data...", true);
|
||||
|
||||
xhrPost("backend.php", dialog.attr('value'), () => {
|
||||
dialog.hide();
|
||||
Notify.close();
|
||||
Feeds.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
href: "backend.php?" + dojo.objectToQuery(query)
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
genUrlChangeKey: function(feed, is_cat) {
|
||||
if (confirm(__("Generate new syndication address for this feed?"))) {
|
||||
|
||||
Notify.progress("Trying to change address...", true);
|
||||
|
||||
const query = {op: "pref-feeds", method: "regenFeedKey", id: feed, is_cat: is_cat};
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
const new_link = reply.link;
|
||||
const e = $('gen_feed_url');
|
||||
|
||||
if (new_link) {
|
||||
e.innerHTML = e.innerHTML.replace(/&key=.*$/,
|
||||
"&key=" + new_link);
|
||||
|
||||
e.href = e.href.replace(/&key=.*$/,
|
||||
"&key=" + new_link);
|
||||
|
||||
new Effect.Highlight(e);
|
||||
|
||||
Notify.close();
|
||||
|
||||
} else {
|
||||
Notify.error("Could not change feed URL.");
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return CommonDialogs;
|
||||
});
|
||||
@@ -0,0 +1,393 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
Filters = {
|
||||
filterDlgCheckAction: function(sender) {
|
||||
const action = sender.value;
|
||||
|
||||
const action_param = $("filterDlg_paramBox");
|
||||
|
||||
if (!action_param) {
|
||||
console.log("filterDlgCheckAction: can't find action param box!");
|
||||
return;
|
||||
}
|
||||
|
||||
// if selected action supports parameters, enable params field
|
||||
if (action == 4 || action == 6 || action == 7 || action == 9) {
|
||||
new Effect.Appear(action_param, {duration: 0.5});
|
||||
|
||||
Element.hide(dijit.byId("filterDlg_actionParam").domNode);
|
||||
Element.hide(dijit.byId("filterDlg_actionParamLabel").domNode);
|
||||
Element.hide(dijit.byId("filterDlg_actionParamPlugin").domNode);
|
||||
|
||||
if (action == 7) {
|
||||
Element.show(dijit.byId("filterDlg_actionParamLabel").domNode);
|
||||
} else if (action == 9) {
|
||||
Element.show(dijit.byId("filterDlg_actionParamPlugin").domNode);
|
||||
} else {
|
||||
Element.show(dijit.byId("filterDlg_actionParam").domNode);
|
||||
}
|
||||
|
||||
} else {
|
||||
Element.hide(action_param);
|
||||
}
|
||||
},
|
||||
createNewRuleElement: function(parentNode, replaceNode) {
|
||||
const form = document.forms["filter_new_rule_form"];
|
||||
const query = {op: "pref-filters", method: "printrulename", rule: dojo.formToJson(form)};
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
try {
|
||||
const li = dojo.create("li");
|
||||
|
||||
const cb = dojo.create("input", {type: "checkbox"}, li);
|
||||
|
||||
new dijit.form.CheckBox({
|
||||
onChange: function () {
|
||||
Lists.onRowChecked(this);
|
||||
},
|
||||
}, cb);
|
||||
|
||||
dojo.create("input", {
|
||||
type: "hidden",
|
||||
name: "rule[]",
|
||||
value: dojo.formToJson(form)
|
||||
}, li);
|
||||
|
||||
dojo.create("span", {
|
||||
onclick: function () {
|
||||
dijit.byId('filterEditDlg').editRule(this);
|
||||
},
|
||||
innerHTML: transport.responseText
|
||||
}, li);
|
||||
|
||||
if (replaceNode) {
|
||||
parentNode.replaceChild(li, replaceNode);
|
||||
} else {
|
||||
parentNode.appendChild(li);
|
||||
}
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
createNewActionElement: function(parentNode, replaceNode) {
|
||||
const form = document.forms["filter_new_action_form"];
|
||||
|
||||
if (form.action_id.value == 7) {
|
||||
form.action_param.value = form.action_param_label.value;
|
||||
} else if (form.action_id.value == 9) {
|
||||
form.action_param.value = form.action_param_plugin.value;
|
||||
}
|
||||
|
||||
const query = {
|
||||
op: "pref-filters", method: "printactionname",
|
||||
action: dojo.formToJson(form)
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
try {
|
||||
const li = dojo.create("li");
|
||||
|
||||
const cb = dojo.create("input", {type: "checkbox"}, li);
|
||||
|
||||
new dijit.form.CheckBox({
|
||||
onChange: function () {
|
||||
Lists.onRowChecked(this);
|
||||
},
|
||||
}, cb);
|
||||
|
||||
dojo.create("input", {
|
||||
type: "hidden",
|
||||
name: "action[]",
|
||||
value: dojo.formToJson(form)
|
||||
}, li);
|
||||
|
||||
dojo.create("span", {
|
||||
onclick: function () {
|
||||
dijit.byId('filterEditDlg').editAction(this);
|
||||
},
|
||||
innerHTML: transport.responseText
|
||||
}, li);
|
||||
|
||||
if (replaceNode) {
|
||||
parentNode.replaceChild(li, replaceNode);
|
||||
} else {
|
||||
parentNode.appendChild(li);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
addFilterRule: function(replaceNode, ruleStr) {
|
||||
if (dijit.byId("filterNewRuleDlg"))
|
||||
dijit.byId("filterNewRuleDlg").destroyRecursive();
|
||||
|
||||
const query = "backend.php?op=pref-filters&method=newrule&rule=" +
|
||||
encodeURIComponent(ruleStr);
|
||||
|
||||
const rule_dlg = new dijit.Dialog({
|
||||
id: "filterNewRuleDlg",
|
||||
title: ruleStr ? __("Edit rule") : __("Add rule"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Filters.createNewRuleElement($("filterDlg_Matches"), replaceNode);
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
rule_dlg.show();
|
||||
},
|
||||
addFilterAction: function(replaceNode, actionStr) {
|
||||
if (dijit.byId("filterNewActionDlg"))
|
||||
dijit.byId("filterNewActionDlg").destroyRecursive();
|
||||
|
||||
const query = "backend.php?op=pref-filters&method=newaction&action=" +
|
||||
encodeURIComponent(actionStr);
|
||||
|
||||
const rule_dlg = new dijit.Dialog({
|
||||
id: "filterNewActionDlg",
|
||||
title: actionStr ? __("Edit action") : __("Add action"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Filters.createNewActionElement($("filterDlg_Actions"), replaceNode);
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
rule_dlg.show();
|
||||
},
|
||||
editFilterTest: function(query) {
|
||||
|
||||
if (dijit.byId("filterTestDlg"))
|
||||
dijit.byId("filterTestDlg").destroyRecursive();
|
||||
|
||||
const test_dlg = new dijit.Dialog({
|
||||
id: "filterTestDlg",
|
||||
title: "Test Filter",
|
||||
style: "width: 600px",
|
||||
results: 0,
|
||||
limit: 100,
|
||||
max_offset: 10000,
|
||||
getTestResults: function (query, offset) {
|
||||
const updquery = query + "&offset=" + offset + "&limit=" + test_dlg.limit;
|
||||
|
||||
console.log("getTestResults:" + offset);
|
||||
|
||||
xhrPost("backend.php", updquery, (transport) => {
|
||||
try {
|
||||
const result = JSON.parse(transport.responseText);
|
||||
|
||||
if (result && dijit.byId("filterTestDlg") && dijit.byId("filterTestDlg").open) {
|
||||
test_dlg.results += result.length;
|
||||
|
||||
console.log("got results:" + result.length);
|
||||
|
||||
$("prefFilterProgressMsg").innerHTML = __("Looking for articles (%d processed, %f found)...")
|
||||
.replace("%f", test_dlg.results)
|
||||
.replace("%d", offset);
|
||||
|
||||
console.log(offset + " " + test_dlg.max_offset);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const tmp = new Element("table");
|
||||
tmp.innerHTML = result[i];
|
||||
dojo.parser.parse(tmp);
|
||||
|
||||
$("prefFilterTestResultList").innerHTML += tmp.innerHTML;
|
||||
}
|
||||
|
||||
if (test_dlg.results < 30 && offset < test_dlg.max_offset) {
|
||||
|
||||
// get the next batch
|
||||
window.setTimeout(function () {
|
||||
test_dlg.getTestResults(query, offset + test_dlg.limit);
|
||||
}, 0);
|
||||
|
||||
} else {
|
||||
// all done
|
||||
|
||||
Element.hide("prefFilterLoadingIndicator");
|
||||
|
||||
if (test_dlg.results == 0) {
|
||||
$("prefFilterTestResultList").innerHTML = "<tr><td align='center'>No recent articles matching this filter have been found.</td></tr>";
|
||||
$("prefFilterProgressMsg").innerHTML = "Articles matching this filter:";
|
||||
} else {
|
||||
$("prefFilterProgressMsg").innerHTML = __("Found %d articles matching this filter:")
|
||||
.replace("%d", test_dlg.results);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (!result) {
|
||||
console.log("getTestResults: can't parse results object");
|
||||
|
||||
Element.hide("prefFilterLoadingIndicator");
|
||||
|
||||
Notify.error("Error while trying to get filter test results.");
|
||||
|
||||
} else {
|
||||
console.log("getTestResults: dialog closed, bailing out.");
|
||||
}
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dojo.connect(test_dlg, "onLoad", null, function (e) {
|
||||
test_dlg.getTestResults(query, 0);
|
||||
});
|
||||
|
||||
test_dlg.show();
|
||||
},
|
||||
quickAddFilter: function() {
|
||||
let query;
|
||||
|
||||
if (!App.isPrefs()) {
|
||||
query = {
|
||||
op: "pref-filters", method: "newfilter",
|
||||
feed: Feeds.getActive(), is_cat: Feeds.activeIsCat()
|
||||
};
|
||||
} else {
|
||||
query = {op: "pref-filters", method: "newfilter"};
|
||||
}
|
||||
|
||||
console.log('quickAddFilter', query);
|
||||
|
||||
if (dijit.byId("feedEditDlg"))
|
||||
dijit.byId("feedEditDlg").destroyRecursive();
|
||||
|
||||
if (dijit.byId("filterEditDlg"))
|
||||
dijit.byId("filterEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "filterEditDlg",
|
||||
title: __("Create Filter"),
|
||||
style: "width: 600px",
|
||||
test: function () {
|
||||
const query = "backend.php?" + dojo.formToQuery("filter_new_form") + "&savemode=test";
|
||||
|
||||
Filters.editFilterTest(query);
|
||||
},
|
||||
selectRules: function (select) {
|
||||
$$("#filterDlg_Matches input[type=checkbox]").each(function (e) {
|
||||
e.checked = select;
|
||||
if (select)
|
||||
e.parentNode.addClassName("Selected");
|
||||
else
|
||||
e.parentNode.removeClassName("Selected");
|
||||
});
|
||||
},
|
||||
selectActions: function (select) {
|
||||
$$("#filterDlg_Actions input[type=checkbox]").each(function (e) {
|
||||
e.checked = select;
|
||||
|
||||
if (select)
|
||||
e.parentNode.addClassName("Selected");
|
||||
else
|
||||
e.parentNode.removeClassName("Selected");
|
||||
|
||||
});
|
||||
},
|
||||
editRule: function (e) {
|
||||
const li = e.parentNode;
|
||||
const rule = li.getElementsByTagName("INPUT")[1].value;
|
||||
Filters.addFilterRule(li, rule);
|
||||
},
|
||||
editAction: function (e) {
|
||||
const li = e.parentNode;
|
||||
const action = li.getElementsByTagName("INPUT")[1].value;
|
||||
Filters.addFilterAction(li, action);
|
||||
},
|
||||
addAction: function () {
|
||||
Filters.addFilterAction();
|
||||
},
|
||||
addRule: function () {
|
||||
Filters.addFilterRule();
|
||||
},
|
||||
deleteAction: function () {
|
||||
$$("#filterDlg_Actions li[class*=Selected]").each(function (e) {
|
||||
e.parentNode.removeChild(e)
|
||||
});
|
||||
},
|
||||
deleteRule: function () {
|
||||
$$("#filterDlg_Matches li[class*=Selected]").each(function (e) {
|
||||
e.parentNode.removeChild(e)
|
||||
});
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
|
||||
const query = dojo.formToQuery("filter_new_form");
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
if (App.isPrefs()) {
|
||||
dijit.byId("filterTree").reload();
|
||||
}
|
||||
|
||||
dialog.hide();
|
||||
});
|
||||
}
|
||||
},
|
||||
href: "backend.php?" + dojo.objectToQuery(query)
|
||||
});
|
||||
|
||||
if (!App.isPrefs()) {
|
||||
const selectedText = getSelectionText();
|
||||
|
||||
const lh = dojo.connect(dialog, "onLoad", function () {
|
||||
dojo.disconnect(lh);
|
||||
|
||||
if (selectedText != "") {
|
||||
|
||||
const feed_id = Feeds.activeIsCat() ? 'CAT:' + parseInt(Feeds.getActive()) :
|
||||
Feeds.getActive();
|
||||
|
||||
const rule = {reg_exp: selectedText, feed_id: [feed_id], filter_type: 1};
|
||||
|
||||
Filters.addFilterRule(null, dojo.toJson(rule));
|
||||
|
||||
} else {
|
||||
|
||||
const query = {op: "rpc", method: "getlinktitlebyid", id: Article.getActive()};
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
const reply = JSON.parse(transport.responseText);
|
||||
|
||||
let title = false;
|
||||
|
||||
if (reply && reply.title) title = reply.title;
|
||||
|
||||
if (title || Feeds.getActive() || Feeds.activeIsCat()) {
|
||||
|
||||
console.log(title + " " + Feeds.getActive());
|
||||
|
||||
const feed_id = Feeds.activeIsCat() ? 'CAT:' + parseInt(Feeds.getActive()) :
|
||||
Feeds.getActive();
|
||||
|
||||
const rule = {reg_exp: title, feed_id: [feed_id], filter_type: 1};
|
||||
|
||||
Filters.addFilterRule(null, dojo.toJson(rule));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
dialog.show();
|
||||
},
|
||||
};
|
||||
|
||||
return Filters;
|
||||
});
|
||||
+7
-7
@@ -41,14 +41,14 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Mark as read"),
|
||||
onClick: function() {
|
||||
catchupFeed(this.getParent().row_id);
|
||||
Feeds.catchupFeed(this.getParent().row_id);
|
||||
}}));
|
||||
|
||||
if (bare_id > 0) {
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Edit feed"),
|
||||
onClick: function() {
|
||||
editFeed(this.getParent().row_id, false);
|
||||
CommonDialogs.editFeed(this.getParent().row_id, false);
|
||||
}}));
|
||||
|
||||
/* menu.addChild(new dijit.MenuItem({
|
||||
@@ -69,7 +69,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Mark as read"),
|
||||
onClick: function() {
|
||||
catchupFeed(this.getParent().row_id, true);
|
||||
Feeds.catchupFeed(this.getParent().row_id, true);
|
||||
}}));
|
||||
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
@@ -97,7 +97,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Mark all feeds as read"),
|
||||
onClick: function() {
|
||||
catchupAllFeeds();
|
||||
Feeds.catchupAllFeeds();
|
||||
}}));
|
||||
|
||||
menu.bindDomNode(tnode.domNode);
|
||||
@@ -123,7 +123,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
postCreate: function() {
|
||||
this.connect(this.model, "onChange", "updateCounter");
|
||||
this.connect(this, "_expandNode", function() {
|
||||
this.hideRead(getInitParam("hide_read_feeds"), getInitParam("hide_read_shows_special"));
|
||||
this.hideRead(App.getInitParam("hide_read_feeds"), App.getInitParam("hide_read_shows_special"));
|
||||
});
|
||||
|
||||
this.inherited(arguments);
|
||||
@@ -207,7 +207,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
exception_error(e);
|
||||
App.Error.report(e);
|
||||
}
|
||||
},
|
||||
findNodeParentsAndExpandThem: function(feed, is_cat, root, parents) {
|
||||
@@ -242,7 +242,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
|
||||
this.expandParentNodes(feed, is_cat, parents.slice(0));
|
||||
}
|
||||
} catch (e) {
|
||||
exception_error(e);
|
||||
App.Error.report(e);
|
||||
}
|
||||
},
|
||||
selectFeed: function(feed, is_cat) {
|
||||
|
||||
+642
@@ -0,0 +1,642 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
Feeds = {
|
||||
counters_last_request: 0,
|
||||
_active_feed_id: 0,
|
||||
_active_feed_is_cat: false,
|
||||
infscroll_in_progress: 0,
|
||||
infscroll_disabled: 0,
|
||||
_infscroll_timeout: false,
|
||||
_search_query: false,
|
||||
last_search_query: [],
|
||||
_viewfeed_wait_timeout: false,
|
||||
_counters_prev: [],
|
||||
// NOTE: this implementation is incomplete
|
||||
// for general objects but good enough for counters
|
||||
// http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
|
||||
counterEquals: function(a, b) {
|
||||
// Create arrays of property names
|
||||
const aProps = Object.getOwnPropertyNames(a);
|
||||
const bProps = Object.getOwnPropertyNames(b);
|
||||
|
||||
// If number of properties is different,
|
||||
// objects are not equivalent
|
||||
if (aProps.length != bProps.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < aProps.length; i++) {
|
||||
const propName = aProps[i];
|
||||
|
||||
// If values of same property are not equal,
|
||||
// objects are not equivalent
|
||||
if (a[propName] !== b[propName]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we made it this far, objects
|
||||
// are considered equivalent
|
||||
return true;
|
||||
},
|
||||
resetCounters: function () {
|
||||
this._counters_prev = [];
|
||||
},
|
||||
parseCounters: function (elems) {
|
||||
for (let l = 0; l < elems.length; l++) {
|
||||
|
||||
if (Feeds._counters_prev[l] && this.counterEquals(elems[l], this._counters_prev[l])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const id = elems[l].id;
|
||||
const kind = elems[l].kind;
|
||||
const ctr = parseInt(elems[l].counter);
|
||||
const error = elems[l].error;
|
||||
const has_img = elems[l].has_img;
|
||||
const updated = elems[l].updated;
|
||||
const auxctr = parseInt(elems[l].auxcounter);
|
||||
|
||||
if (id == "global-unread") {
|
||||
App.global_unread = ctr;
|
||||
App.updateTitle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id == "subscribed-feeds") {
|
||||
/* feeds_found = ctr; */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (this.getUnread(id, (kind == "cat")) != ctr ||
|
||||
(kind == "cat")) {
|
||||
}*/
|
||||
|
||||
this.setUnread(id, (kind == "cat"), ctr);
|
||||
this.setValue(id, (kind == "cat"), 'auxcounter', auxctr);
|
||||
|
||||
if (kind != "cat") {
|
||||
this.setValue(id, false, 'error', error);
|
||||
this.setValue(id, false, 'updated', updated);
|
||||
|
||||
if (id > 0) {
|
||||
if (has_img) {
|
||||
this.setIcon(id, false,
|
||||
App.getInitParam("icons_url") + "/" + id + ".ico?" + has_img);
|
||||
} else {
|
||||
this.setIcon(id, false, 'images/blank_icon.gif');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.hideOrShowFeeds(App.getInitParam("hide_read_feeds") == 1);
|
||||
this._counters_prev = elems;
|
||||
},
|
||||
reloadCurrent: function(method) {
|
||||
console.log("reloadCurrent: " + method);
|
||||
|
||||
if (this.getActive() != undefined) {
|
||||
this.open({feed: this.getActive(), is_cat: this.activeIsCat(), method: method});
|
||||
}
|
||||
return false; // block unneeded form submits
|
||||
},
|
||||
openNextUnread: function() {
|
||||
const is_cat = this.activeIsCat();
|
||||
const nuf = this.getNextUnread(this.getActive(), is_cat);
|
||||
if (nuf) this.open({feed: nuf, is_cat: is_cat});
|
||||
},
|
||||
toggle: function() {
|
||||
Element.toggle("feeds-holder");
|
||||
|
||||
const splitter = $("feeds-holder_splitter");
|
||||
|
||||
Element.visible("feeds-holder") ? splitter.show() : splitter.hide();
|
||||
|
||||
dijit.byId("main").resize();
|
||||
},
|
||||
cancelSearch: function() {
|
||||
this._search_query = "";
|
||||
this.reloadCurrent();
|
||||
},
|
||||
requestCounters: function(force) {
|
||||
const date = new Date();
|
||||
const timestamp = Math.round(date.getTime() / 1000);
|
||||
|
||||
if (force || timestamp - this.counters_last_request > 5) {
|
||||
console.log("scheduling request of counters...");
|
||||
|
||||
this.counters_last_request = timestamp;
|
||||
|
||||
let query = {op: "rpc", method: "getAllCounters", seq: App.next_seq()};
|
||||
|
||||
if (!force)
|
||||
query.last_article_id = App.getInitParam("last_article_id");
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
App.handleRpcJson(transport);
|
||||
});
|
||||
|
||||
} else {
|
||||
console.log("request_counters: rate limit reached: " + (timestamp - this.counters_last_request));
|
||||
}
|
||||
},
|
||||
reload: function() {
|
||||
try {
|
||||
Element.show("feedlistLoading");
|
||||
|
||||
this.resetCounters();
|
||||
|
||||
if (dijit.byId("feedTree")) {
|
||||
dijit.byId("feedTree").destroyRecursive();
|
||||
}
|
||||
|
||||
const store = new dojo.data.ItemFileWriteStore({
|
||||
url: "backend.php?op=pref_feeds&method=getfeedtree&mode=2"
|
||||
});
|
||||
|
||||
// noinspection JSUnresolvedFunction
|
||||
const treeModel = new fox.FeedStoreModel({
|
||||
store: store,
|
||||
query: {
|
||||
"type": App.getInitParam('enable_feed_cats') == 1 ? "category" : "feed"
|
||||
},
|
||||
rootId: "root",
|
||||
rootLabel: "Feeds",
|
||||
childrenAttrs: ["items"]
|
||||
});
|
||||
|
||||
// noinspection JSUnresolvedFunction
|
||||
const tree = new fox.FeedTree({
|
||||
model: treeModel,
|
||||
onClick: function (item/*, node*/) {
|
||||
const id = String(item.id);
|
||||
const is_cat = id.match("^CAT:");
|
||||
const feed = id.substr(id.indexOf(":") + 1);
|
||||
Feeds.open({feed: feed, is_cat: is_cat});
|
||||
return false;
|
||||
},
|
||||
openOnClick: false,
|
||||
showRoot: false,
|
||||
persist: true,
|
||||
id: "feedTree",
|
||||
}, "feedTree");
|
||||
|
||||
const tmph = dojo.connect(dijit.byId('feedMenu'), '_openMyself', function (event) {
|
||||
console.log(dijit.getEnclosingWidget(event.target));
|
||||
dojo.disconnect(tmph);
|
||||
});
|
||||
|
||||
$("feeds-holder").appendChild(tree.domNode);
|
||||
|
||||
const tmph2 = dojo.connect(tree, 'onLoad', function () {
|
||||
dojo.disconnect(tmph2);
|
||||
Element.hide("feedlistLoading");
|
||||
|
||||
try {
|
||||
Feeds.init();
|
||||
App.setLoadingProgress(25);
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
|
||||
tree.startup();
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
},
|
||||
init: function() {
|
||||
console.log("in feedlist init");
|
||||
|
||||
App.setLoadingProgress(50);
|
||||
|
||||
document.onkeydown = (event) => { App.hotkeyHandler(event) };
|
||||
window.setInterval(() => { Headlines.catchupBatched() }, 10 * 1000);
|
||||
|
||||
if (!this.getActive()) {
|
||||
this.open({feed: -3});
|
||||
} else {
|
||||
this.open({feed: this.getActive(), is_cat: this.activeIsCat()});
|
||||
}
|
||||
|
||||
this.hideOrShowFeeds(App.getInitParam("hide_read_feeds") == 1);
|
||||
|
||||
if (App.getInitParam("is_default_pw")) {
|
||||
console.warn("user password is at default value");
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
title: __("Your password is at default value"),
|
||||
href: "backend.php?op=dlg&method=defaultpasswordwarning",
|
||||
id: 'infoBox',
|
||||
style: "width: 600px",
|
||||
onCancel: function () {
|
||||
return true;
|
||||
},
|
||||
onExecute: function () {
|
||||
return true;
|
||||
},
|
||||
onClose: function () {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// bw_limit disables timeout() so we request initial counters separately
|
||||
if (App.getInitParam("bw_limit") == "1") {
|
||||
this.requestCounters(true);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.requestCounters(true);
|
||||
setInterval(() => { this.requestCounters(); }, 60 * 1000)
|
||||
}, 250);
|
||||
}
|
||||
},
|
||||
activeIsCat: function() {
|
||||
return !!this._active_feed_is_cat;
|
||||
},
|
||||
getActive: function() {
|
||||
return this._active_feed_id;
|
||||
},
|
||||
setActive: function(id, is_cat) {
|
||||
hash_set('f', id);
|
||||
hash_set('c', is_cat ? 1 : 0);
|
||||
|
||||
this._active_feed_id = id;
|
||||
this._active_feed_is_cat = is_cat;
|
||||
|
||||
$("headlines-frame").setAttribute("feed-id", id);
|
||||
$("headlines-frame").setAttribute("is-cat", is_cat ? 1 : 0);
|
||||
|
||||
this.select(id, is_cat);
|
||||
|
||||
PluginHost.run(PluginHost.HOOK_FEED_SET_ACTIVE, [this._active_feed_id, this._active_feed_is_cat]);
|
||||
},
|
||||
select: function(feed, is_cat) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.selectFeed(feed, is_cat);
|
||||
},
|
||||
toggleUnread: function() {
|
||||
const hide = !(App.getInitParam("hide_read_feeds") == "1");
|
||||
|
||||
xhrPost("backend.php", {op: "rpc", method: "setpref", key: "HIDE_READ_FEEDS", value: hide}, () => {
|
||||
this.hideOrShowFeeds(hide);
|
||||
App.setInitParam("hide_read_feeds", hide);
|
||||
});
|
||||
},
|
||||
hideOrShowFeeds: function(hide) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree)
|
||||
return tree.hideRead(hide, App.getInitParam("hide_read_shows_special"));
|
||||
},
|
||||
open: function(params) {
|
||||
const feed = params.feed;
|
||||
const is_cat = !!params.is_cat || false;
|
||||
const offset = params.offset || 0;
|
||||
const viewfeed_debug = params.viewfeed_debug;
|
||||
const method = params.method;
|
||||
// this is used to quickly switch between feeds, sets active but xhr is on a timeout
|
||||
const delayed = params.delayed || false;
|
||||
|
||||
if (feed != this.getActive() || this.activeIsCat() != is_cat) {
|
||||
this._search_query = false;
|
||||
Article.setActive(0);
|
||||
}
|
||||
|
||||
if (offset != 0) {
|
||||
if (this.infscroll_in_progress)
|
||||
return;
|
||||
|
||||
this.infscroll_in_progress = 1;
|
||||
|
||||
window.clearTimeout(this._infscroll_timeout);
|
||||
this._infscroll_timeout = window.setTimeout(() => {
|
||||
console.log('infscroll request timed out, aborting');
|
||||
this.infscroll_in_progress = 0;
|
||||
|
||||
// call scroll handler to maybe repeat infscroll request
|
||||
Headlines.scrollHandler();
|
||||
}, 10 * 1000);
|
||||
}
|
||||
|
||||
Form.enable("main_toolbar_form");
|
||||
|
||||
let query = Object.assign({op: "feeds", method: "view", feed: feed},
|
||||
dojo.formToObject("main_toolbar_form"));
|
||||
|
||||
if (method) query.m = method;
|
||||
|
||||
if (offset > 0) {
|
||||
if (Headlines.current_first_id) {
|
||||
query.fid = Headlines.current_first_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._search_query) {
|
||||
query = Object.assign(query, this._search_query);
|
||||
}
|
||||
|
||||
if (offset != 0) {
|
||||
query.skip = offset;
|
||||
|
||||
// to prevent duplicate feed titles when showing grouped vfeeds
|
||||
if (Headlines.vgroup_last_feed != undefined) {
|
||||
query.vgrlf = Headlines.vgroup_last_feed;
|
||||
}
|
||||
} else if (!is_cat && feed == this.getActive() && !params.method) {
|
||||
query.m = "ForceUpdate";
|
||||
}
|
||||
|
||||
Form.enable("main_toolbar_form");
|
||||
|
||||
if (!delayed)
|
||||
if (!this.setExpando(feed, is_cat,
|
||||
(is_cat) ? 'images/indicator_tiny.gif' : 'images/indicator_white.gif'))
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
query.cat = is_cat;
|
||||
|
||||
this.setActive(feed, is_cat);
|
||||
|
||||
if (viewfeed_debug) {
|
||||
window.open("backend.php?" +
|
||||
dojo.objectToQuery(
|
||||
Object.assign({debug: 1, csrf_token: App.getInitParam("csrf_token")}, query)
|
||||
));
|
||||
}
|
||||
|
||||
window.clearTimeout(this._viewfeed_wait_timeout);
|
||||
this._viewfeed_wait_timeout = window.setTimeout(() => {
|
||||
Headlines.catchupBatched(() => {
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
try {
|
||||
window.clearTimeout(this._infscroll_timeout);
|
||||
this.setExpando(feed, is_cat, 'images/blank_icon.gif');
|
||||
Headlines.onLoaded(transport, offset);
|
||||
PluginHost.run(PluginHost.HOOK_FEED_LOADED, [feed, is_cat]);
|
||||
} catch (e) {
|
||||
App.Error.report(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, delayed ? 250 : 0);
|
||||
},
|
||||
catchupAll: function() {
|
||||
const str = __("Mark all articles as read?");
|
||||
|
||||
if (App.getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
|
||||
|
||||
Notify.progress("Marking all feeds as read...");
|
||||
|
||||
xhrPost("backend.php", {op: "feeds", method: "catchupAll"}, () => {
|
||||
this.requestCounters(true);
|
||||
this.reloadCurrent();
|
||||
});
|
||||
|
||||
App.global_unread = 0;
|
||||
App.updateTitle();
|
||||
}
|
||||
},
|
||||
decrementFeedCounter: function(feed, is_cat) {
|
||||
let ctr = this.getUnread(feed, is_cat);
|
||||
|
||||
if (ctr > 0) {
|
||||
this.setUnread(feed, is_cat, ctr - 1);
|
||||
App.global_unread -= 1;
|
||||
App.updateTitle();
|
||||
|
||||
if (!is_cat) {
|
||||
const cat = parseInt(this.getCategory(feed));
|
||||
|
||||
if (!isNaN(cat)) {
|
||||
ctr = this.getUnread(cat, true);
|
||||
|
||||
if (ctr > 0) {
|
||||
this.setUnread(cat, true, ctr - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
catchupFeed: function(feed, is_cat, mode) {
|
||||
if (is_cat == undefined) is_cat = false;
|
||||
|
||||
let str = false;
|
||||
|
||||
switch (mode) {
|
||||
case "1day":
|
||||
str = __("Mark %w in %s older than 1 day as read?");
|
||||
break;
|
||||
case "1week":
|
||||
str = __("Mark %w in %s older than 1 week as read?");
|
||||
break;
|
||||
case "2week":
|
||||
str = __("Mark %w in %s older than 2 weeks as read?");
|
||||
break;
|
||||
default:
|
||||
str = __("Mark %w in %s as read?");
|
||||
}
|
||||
|
||||
const mark_what = this.last_search_query && this.last_search_query[0] ? __("search results") : __("all articles");
|
||||
const fn = this.getName(feed, is_cat);
|
||||
|
||||
str = str.replace("%s", fn)
|
||||
.replace("%w", mark_what);
|
||||
|
||||
if (App.getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const catchup_query = {
|
||||
op: 'rpc', method: 'catchupFeed', feed_id: feed,
|
||||
is_cat: is_cat, mode: mode, search_query: this.last_search_query[0],
|
||||
search_lang: this.last_search_query[1]
|
||||
};
|
||||
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
xhrPost("backend.php", catchup_query, (transport) => {
|
||||
App.handleRpcJson(transport);
|
||||
|
||||
const show_next_feed = App.getInitParam("on_catchup_show_next_feed") == "1";
|
||||
|
||||
if (show_next_feed) {
|
||||
const nuf = this.getNextUnread(feed, is_cat);
|
||||
|
||||
if (nuf) {
|
||||
this.open({feed: nuf, is_cat: is_cat});
|
||||
}
|
||||
} else if (feed == this.getActive() && is_cat == this.activeIsCat()) {
|
||||
this.reloadCurrent();
|
||||
}
|
||||
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
catchupCurrent: function(mode) {
|
||||
this.catchupFeed(this.getActive(), this.activeIsCat(), mode);
|
||||
},
|
||||
catchupFeedInGroup: function(id) {
|
||||
const title = this.getName(id);
|
||||
|
||||
const str = __("Mark all articles in %s as read?").replace("%s", title);
|
||||
|
||||
if (App.getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
|
||||
|
||||
const rows = $$("#headlines-frame > div[id*=RROW][data-orig-feed-id='" + id + "']");
|
||||
|
||||
if (rows.length > 0) {
|
||||
|
||||
rows.each(function (row) {
|
||||
row.removeClassName("Unread");
|
||||
|
||||
if (row.getAttribute("data-article-id") != Article.getActive()) {
|
||||
new Effect.Fade(row, {duration: 0.5});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const feedTitles = $$("#headlines-frame > div[class='feed-title']");
|
||||
|
||||
for (let i = 0; i < feedTitles.length; i++) {
|
||||
if (feedTitles[i].getAttribute("data-feed-id") == id) {
|
||||
|
||||
if (i < feedTitles.length - 1) {
|
||||
new Effect.Fade(feedTitles[i], {duration: 0.5});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Headlines.updateFloatingTitle(true);
|
||||
}
|
||||
|
||||
Notify.progress("Loading, please wait...", true);
|
||||
|
||||
xhrPost("backend.php", {op: "rpc", method: "catchupFeed", feed_id: id, is_cat: false}, (transport) => {
|
||||
App.handleRpcJson(transport);
|
||||
});
|
||||
}
|
||||
},
|
||||
getUnread: function(feed, is_cat) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedUnread(feed, is_cat);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return -1;
|
||||
},
|
||||
getCategory: function(feed) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.getFeedCategory(feed);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
getName: function(feed, is_cat) {
|
||||
if (isNaN(feed)) return feed; // it's a tag
|
||||
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedValue(feed, is_cat, 'name');
|
||||
},
|
||||
setUnread: function(feed, is_cat, unread) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.setFeedUnread(feed, is_cat, unread);
|
||||
},
|
||||
setValue: function(feed, is_cat, key, value) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.setFeedValue(feed, is_cat, key, value);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
},
|
||||
getValue: function(feed, is_cat, key) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedValue(feed, is_cat, key);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
return '';
|
||||
},
|
||||
setIcon: function(feed, is_cat, src) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.setFeedIcon(feed, is_cat, src);
|
||||
},
|
||||
setExpando: function(feed, is_cat, src) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.setFeedExpandoIcon(feed, is_cat, src);
|
||||
|
||||
return false;
|
||||
},
|
||||
getNextUnread: function(feed, is_cat) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
const nuf = tree.model.getNextUnreadFeed(feed, is_cat);
|
||||
|
||||
if (nuf)
|
||||
return tree.model.store.getValue(nuf, 'bare_id');
|
||||
},
|
||||
search: function() {
|
||||
const query = "backend.php?op=feeds&method=search¶m=" +
|
||||
encodeURIComponent(Feeds.getActive() + ":" + Feeds.activeIsCat());
|
||||
|
||||
if (dijit.byId("searchDlg"))
|
||||
dijit.byId("searchDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "searchDlg",
|
||||
title: __("Search"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Feeds._search_query = this.attr('value');
|
||||
this.hide();
|
||||
Feeds.reloadCurrent();
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
updateRandom: function() {
|
||||
console.log("in update_random_feed");
|
||||
|
||||
xhrPost("backend.php", {op: "rpc", method: "updateRandom"}, (transport) => {
|
||||
App.handleRpcJson(transport, true);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return Feeds;
|
||||
});
|
||||
Executable
+1215
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -1,6 +1,6 @@
|
||||
// based on http://www.velvetcache.org/2010/08/19/a-simple-javascript-hooks-system
|
||||
|
||||
const PluginHost = {
|
||||
PluginHost = {
|
||||
HOOK_ARTICLE_RENDERED: 1,
|
||||
HOOK_ARTICLE_RENDERED_CDM: 2,
|
||||
HOOK_ARTICLE_SET_ACTIVE: 3,
|
||||
@@ -19,10 +19,10 @@ const PluginHost = {
|
||||
this.hooks[name].push(callback);
|
||||
},
|
||||
run: function (name, args) {
|
||||
console.warn('PluginHost::run ' + name);
|
||||
//console.warn('PluginHost::run ' + name);
|
||||
|
||||
if (typeof(this.hooks[name]) != 'undefined')
|
||||
for (var i = 0; i < this.hooks[name].length; i++)
|
||||
for (let i = 0; i < this.hooks[name].length; i++)
|
||||
if (!this.hooks[name][i](args)) break;
|
||||
}
|
||||
};
|
||||
|
||||
+298
-4
@@ -35,14 +35,14 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Edit category"),
|
||||
onClick: function() {
|
||||
editCat(this.getParent().row_id, this.getParent().item, null);
|
||||
dijit.byId("feedTree").editCategory(this.getParent().row_id, this.getParent().item, null);
|
||||
}}));
|
||||
|
||||
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Remove category"),
|
||||
onClick: function() {
|
||||
removeCategory(this.getParent().row_id, this.getParent().item);
|
||||
dijit.byId("feedTree").removeCategory(this.getParent().row_id, this.getParent().item);
|
||||
}}));
|
||||
|
||||
menu.bindDomNode(tnode.domNode);
|
||||
@@ -55,13 +55,13 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Edit feed"),
|
||||
onClick: function() {
|
||||
editFeed(this.getParent().row_id);
|
||||
CommonDialogs.editFeed(this.getParent().row_id);
|
||||
}}));
|
||||
|
||||
menu.addChild(new dijit.MenuItem({
|
||||
label: __("Unsubscribe"),
|
||||
onClick: function() {
|
||||
unsubscribeFeed(this.getParent().row_id, this.getParent().item.name);
|
||||
CommonDialogs.unsubscribeFeed(this.getParent().row_id, this.getParent().item.name);
|
||||
}}));
|
||||
|
||||
menu.bindDomNode(tnode.domNode);
|
||||
@@ -82,6 +82,15 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
|
||||
getIconClass: function (item, opened) {
|
||||
return (!item || this.model.store.getValue(item, 'type') == 'category') ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "feedIcon";
|
||||
},
|
||||
reload: function() {
|
||||
const searchElem = $("feed_search");
|
||||
let search = (searchElem) ? searchElem.value : "";
|
||||
|
||||
xhrPost("backend.php", { op: "pref-feeds", search: search }, (transport) => {
|
||||
dijit.byId('feedConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
checkItemAcceptance: function(target, source, position) {
|
||||
const item = dijit.getEnclosingWidget(target).item;
|
||||
|
||||
@@ -109,6 +118,291 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
|
||||
(id.match("root") && position == "over"));
|
||||
}
|
||||
},
|
||||
resetFeedOrder: function() {
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "feedsortreset"}, () => {
|
||||
this.reload();
|
||||
});
|
||||
},
|
||||
resetCatOrder: function() {
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "catsortreset"}, () => {
|
||||
this.reload();
|
||||
});
|
||||
},
|
||||
removeCategory: function(id, item) {
|
||||
if (confirm(__("Remove category %s? Any nested feeds would be placed into Uncategorized.").replace("%s", item.name))) {
|
||||
Notify.progress("Removing category...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "removeCat", ids: id}, () => {
|
||||
Notify.close();
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
removeSelectedFeeds: function() {
|
||||
const sel_rows = this.getSelectedFeeds();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Unsubscribe from selected feeds?"))) {
|
||||
|
||||
Notify.progress("Unsubscribing from selected feeds...", true);
|
||||
|
||||
const query = {
|
||||
op: "pref-feeds", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No feeds selected."));
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
checkInactiveFeeds: function() {
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "getinactivefeeds"}, (transport) => {
|
||||
if (parseInt(transport.responseText) > 0) {
|
||||
Element.show(dijit.byId("pref_feeds_inactive_btn").domNode);
|
||||
}
|
||||
});
|
||||
},
|
||||
getSelectedCategories: function() {
|
||||
const tree = this;
|
||||
const items = tree.model.getCheckedItems();
|
||||
const rv = [];
|
||||
|
||||
items.each(function (item) {
|
||||
if (item.id[0].match("CAT:"))
|
||||
rv.push(tree.model.store.getValue(item, 'bare_id'));
|
||||
});
|
||||
|
||||
return rv;
|
||||
},
|
||||
removeSelectedCategories: function() {
|
||||
const sel_rows = this.getSelectedCategories();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected categories?"))) {
|
||||
Notify.progress("Removing selected categories...");
|
||||
|
||||
const query = {
|
||||
op: "pref-feeds", method: "removeCat",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert(__("No categories selected."));
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
getSelectedFeeds: function() {
|
||||
const tree = this;
|
||||
const items = tree.model.getCheckedItems();
|
||||
const rv = [];
|
||||
|
||||
items.each(function (item) {
|
||||
if (item.id[0].match("FEED:"))
|
||||
rv.push(tree.model.store.getValue(item, 'bare_id'));
|
||||
});
|
||||
|
||||
return rv;
|
||||
},
|
||||
editSelectedFeed: function() {
|
||||
const rows = this.getSelectedFeeds();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No feeds selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
Notify.close();
|
||||
|
||||
if (rows.length > 1) {
|
||||
return this.editMultiple();
|
||||
} else {
|
||||
CommonDialogs.editFeed(rows[0], {});
|
||||
}
|
||||
},
|
||||
editMultiple: function() {
|
||||
const rows = this.getSelectedFeeds();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No feeds selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
if (dijit.byId("feedEditDlg"))
|
||||
dijit.byId("feedEditDlg").destroyRecursive();
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "editfeeds", ids: rows.toString()}, (transport) => {
|
||||
Notify.close();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "feedEditDlg",
|
||||
title: __("Edit Multiple Feeds"),
|
||||
style: "width: 600px",
|
||||
getChildByName: function (name) {
|
||||
let rv = null;
|
||||
this.getChildren().each(
|
||||
function (child) {
|
||||
if (child.name == name) {
|
||||
rv = child;
|
||||
return;
|
||||
}
|
||||
});
|
||||
return rv;
|
||||
},
|
||||
toggleField: function (checkbox, elem, label) {
|
||||
this.getChildByName(elem).attr('disabled', !checkbox.checked);
|
||||
|
||||
if ($(label))
|
||||
if (checkbox.checked)
|
||||
$(label).removeClassName('insensitive');
|
||||
else
|
||||
$(label).addClassName('insensitive');
|
||||
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate() && confirm(__("Save changes to selected feeds?"))) {
|
||||
const query = this.attr('value');
|
||||
|
||||
/* normalize unchecked checkboxes because [] is not serialized */
|
||||
|
||||
Object.keys(query).each((key) => {
|
||||
let val = query[key];
|
||||
|
||||
if (typeof val == "object" && val.length == 0)
|
||||
query[key] = ["off"];
|
||||
});
|
||||
|
||||
Notify.progress("Saving data...", true);
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
dialog.hide();
|
||||
dijit.byId("feedTree").reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
content: transport.responseText
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
});
|
||||
},
|
||||
editCategory: function(id, item) {
|
||||
// uncategorized
|
||||
if (String(item.id) == "CAT:0")
|
||||
return;
|
||||
|
||||
const new_name = prompt(__('Rename category to:'), item.name);
|
||||
|
||||
if (new_name && new_name != item.name) {
|
||||
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", { op: 'pref-feeds', method: 'renamecat', id: id, title: new_name }, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
createCategory: function() {
|
||||
const title = prompt(__("Category title:"));
|
||||
|
||||
if (title) {
|
||||
Notify.progress("Creating category...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "addCat", cat: title}, () => {
|
||||
Notify.close();
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
batchSubscribe: function() {
|
||||
const query = "backend.php?op=pref-feeds&method=batchSubscribe";
|
||||
|
||||
// overlapping widgets
|
||||
if (dijit.byId("batchSubDlg")) dijit.byId("batchSubDlg").destroyRecursive();
|
||||
if (dijit.byId("feedAddDlg")) dijit.byId("feedAddDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "batchSubDlg",
|
||||
title: __("Batch subscribe"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Notify.progress(__("Subscribing to feeds..."), true);
|
||||
|
||||
xhrPost("backend.php", this.attr('value'), () => {
|
||||
Notify.close();
|
||||
dijit.byId("feedTree").reload();
|
||||
dialog.hide();
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
showInactiveFeeds: function() {
|
||||
const query = "backend.php?op=pref-feeds&method=inactiveFeeds";
|
||||
|
||||
if (dijit.byId("inactiveFeedsDlg"))
|
||||
dijit.byId("inactiveFeedsDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "inactiveFeedsDlg",
|
||||
title: __("Feeds without recent updates"),
|
||||
style: "width: 600px",
|
||||
getSelectedFeeds: function () {
|
||||
return Tables.getSelected("prefInactiveFeedList");
|
||||
},
|
||||
removeSelected: function () {
|
||||
const sel_rows = this.getSelectedFeeds();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected feeds?"))) {
|
||||
Notify.progress("Removing selected feeds...", true);
|
||||
|
||||
const query = {
|
||||
op: "pref-feeds", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.close();
|
||||
dijit.byId("feedTree").reload();
|
||||
dialog.hide();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No feeds selected."));
|
||||
}
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+183
-1
@@ -75,8 +75,190 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
|
||||
this.inherited(arguments);
|
||||
this.tree.model.store.save();
|
||||
},
|
||||
});
|
||||
getSelectedFilters: function() {
|
||||
const tree = this;
|
||||
const items = tree.model.getCheckedItems();
|
||||
const rv = [];
|
||||
|
||||
items.each(function (item) {
|
||||
rv.push(tree.model.store.getValue(item, 'bare_id'));
|
||||
});
|
||||
|
||||
return rv;
|
||||
},
|
||||
reload: function() {
|
||||
const user_search = $("filter_search");
|
||||
let search = "";
|
||||
if (user_search) { search = user_search.value; }
|
||||
|
||||
xhrPost("backend.php", { op: "pref-filters", search: search }, (transport) => {
|
||||
dijit.byId('filterConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
resetFilterOrder: function() {
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-filters", method: "filtersortreset"}, () => {
|
||||
this.reload();
|
||||
});
|
||||
},
|
||||
joinSelectedFilters: function() {
|
||||
const rows = getSelectedFilters();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No filters selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(__("Combine selected filters?"))) {
|
||||
Notify.progress("Joining filters...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-filters", method: "join", ids: rows.toString()}, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
editSelectedFilter: function() {
|
||||
const rows = this.getSelectedFilters();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No filters selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rows.length > 1) {
|
||||
alert(__("Please select only one filter."));
|
||||
return;
|
||||
}
|
||||
|
||||
Notify.close();
|
||||
|
||||
this.editFilter(rows[0]);
|
||||
},
|
||||
editFilter: function(id) {
|
||||
|
||||
const query = "backend.php?op=pref-filters&method=edit&id=" + encodeURIComponent(id);
|
||||
|
||||
if (dijit.byId("feedEditDlg"))
|
||||
dijit.byId("feedEditDlg").destroyRecursive();
|
||||
|
||||
if (dijit.byId("filterEditDlg"))
|
||||
dijit.byId("filterEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "filterEditDlg",
|
||||
title: __("Edit Filter"),
|
||||
style: "width: 600px",
|
||||
|
||||
test: function () {
|
||||
const query = "backend.php?" + dojo.formToQuery("filter_edit_form") + "&savemode=test";
|
||||
|
||||
Filters.editFilterTest(query);
|
||||
},
|
||||
selectRules: function (select) {
|
||||
$$("#filterDlg_Matches input[type=checkbox]").each(function (e) {
|
||||
e.checked = select;
|
||||
if (select)
|
||||
e.parentNode.addClassName("Selected");
|
||||
else
|
||||
e.parentNode.removeClassName("Selected");
|
||||
});
|
||||
},
|
||||
selectActions: function (select) {
|
||||
$$("#filterDlg_Actions input[type=checkbox]").each(function (e) {
|
||||
e.checked = select;
|
||||
|
||||
if (select)
|
||||
e.parentNode.addClassName("Selected");
|
||||
else
|
||||
e.parentNode.removeClassName("Selected");
|
||||
|
||||
});
|
||||
},
|
||||
editRule: function (e) {
|
||||
const li = e.parentNode;
|
||||
const rule = li.getElementsByTagName("INPUT")[1].value;
|
||||
Filters.addFilterRule(li, rule);
|
||||
},
|
||||
editAction: function (e) {
|
||||
const li = e.parentNode;
|
||||
const action = li.getElementsByTagName("INPUT")[1].value;
|
||||
Filters.addFilterAction(li, action);
|
||||
},
|
||||
removeFilter: function () {
|
||||
const msg = __("Remove filter?");
|
||||
|
||||
if (confirm(msg)) {
|
||||
this.hide();
|
||||
|
||||
Notify.progress("Removing filter...");
|
||||
|
||||
const query = {op: "pref-filters", method: "remove", ids: this.attr('value').id};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
dijit.byId("filterTree").reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
addAction: function () {
|
||||
Filters.addFilterAction();
|
||||
},
|
||||
addRule: function () {
|
||||
Filters.addFilterRule();
|
||||
},
|
||||
deleteAction: function () {
|
||||
$$("#filterDlg_Actions li[class*=Selected]").each(function (e) {
|
||||
e.parentNode.removeChild(e)
|
||||
});
|
||||
},
|
||||
deleteRule: function () {
|
||||
$$("#filterDlg_Matches li[class*=Selected]").each(function (e) {
|
||||
e.parentNode.removeChild(e)
|
||||
});
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
|
||||
Notify.progress("Saving data...", true);
|
||||
|
||||
xhrPost("backend.php", dojo.formToObject("filter_edit_form"), () => {
|
||||
dialog.hide();
|
||||
dijit.byId("filterTree").reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
removeSelectedFilters: function() {
|
||||
const sel_rows = this.getSelectedFilters();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected filters?"))) {
|
||||
Notify.progress("Removing selected filters...");
|
||||
|
||||
const query = {
|
||||
op: "pref-filters", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert(__("No filters selected."));
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
Helpers = {
|
||||
clearFeedAccessKeys: function() {
|
||||
if (confirm(__("This will invalidate all previously generated feed URLs. Continue?"))) {
|
||||
Notify.progress("Clearing URLs...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-feeds", method: "clearKeys"}, () => {
|
||||
Notify.info("Generated URLs cleared.");
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
updateEventLog: function() {
|
||||
xhrPost("backend.php", { op: "pref-system" }, (transport) => {
|
||||
dijit.byId('systemConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
clearEventLog: function() {
|
||||
if (confirm(__("Clear event log?"))) {
|
||||
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-system", method: "clearLog"}, () => {
|
||||
this.updateEventLog();
|
||||
});
|
||||
}
|
||||
},
|
||||
editProfiles: function() {
|
||||
|
||||
if (dijit.byId("profileEditDlg"))
|
||||
dijit.byId("profileEditDlg").destroyRecursive();
|
||||
|
||||
const query = "backend.php?op=pref-prefs&method=editPrefProfiles";
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "profileEditDlg",
|
||||
title: __("Settings Profiles"),
|
||||
style: "width: 600px",
|
||||
getSelectedProfiles: function () {
|
||||
return Tables.getSelected("prefFeedProfileList");
|
||||
},
|
||||
removeSelected: function () {
|
||||
const sel_rows = this.getSelectedProfiles();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected profiles? Active and default profiles will not be removed."))) {
|
||||
Notify.progress("Removing selected profiles...", true);
|
||||
|
||||
const query = {
|
||||
op: "rpc", method: "remprofiles",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.close();
|
||||
Helpers.editProfiles();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No profiles selected."));
|
||||
}
|
||||
},
|
||||
activateProfile: function () {
|
||||
const sel_rows = this.getSelectedProfiles();
|
||||
|
||||
if (sel_rows.length == 1) {
|
||||
if (confirm(__("Activate selected profile?"))) {
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "rpc", method: "setprofile", id: sel_rows.toString()}, () => {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("Please choose a profile to activate."));
|
||||
}
|
||||
},
|
||||
addProfile: function () {
|
||||
if (this.validate()) {
|
||||
Notify.progress("Creating profile...", true);
|
||||
|
||||
const query = {op: "rpc", method: "addprofile", title: dialog.attr('value').newprofile};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
Notify.close();
|
||||
Helpers.editProfiles();
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
customizeCSS: function() {
|
||||
const query = "backend.php?op=pref-prefs&method=customizeCSS";
|
||||
|
||||
if (dijit.byId("cssEditDlg"))
|
||||
dijit.byId("cssEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "cssEditDlg",
|
||||
title: __("Customize stylesheet"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
Notify.progress('Saving data...', true);
|
||||
|
||||
xhrPost("backend.php", this.attr('value'), () => {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
confirmReset: function() {
|
||||
if (confirm(__("Reset to defaults?"))) {
|
||||
xhrPost("backend.php", {op: "pref-prefs", method: "resetconfig"}, (transport) => {
|
||||
Helpers.refresh();
|
||||
Notify.info(transport.responseText);
|
||||
});
|
||||
}
|
||||
},
|
||||
clearPluginData: function(name) {
|
||||
if (confirm(__("Clear stored data for this plugin?"))) {
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-prefs", method: "clearplugindata", name: name}, () => {
|
||||
Helpers.refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
refresh: function() {
|
||||
xhrPost("backend.php", { op: "pref-prefs" }, (transport) => {
|
||||
dijit.byId('genConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
OPML: {
|
||||
import: function() {
|
||||
const opml_file = $("opml_file");
|
||||
|
||||
if (opml_file.value.length == 0) {
|
||||
alert(__("Please choose an OPML file first."));
|
||||
return false;
|
||||
} else {
|
||||
Notify.progress("Importing, please wait...", true);
|
||||
|
||||
Element.show("upload_iframe");
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onImportComplete: function(iframe) {
|
||||
if (!iframe.contentDocument.body.innerHTML) return false;
|
||||
|
||||
Element.show(iframe);
|
||||
|
||||
Notify.close();
|
||||
|
||||
if (dijit.byId('opmlImportDlg'))
|
||||
dijit.byId('opmlImportDlg').destroyRecursive();
|
||||
|
||||
const content = iframe.contentDocument.body.innerHTML;
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "opmlImportDlg",
|
||||
title: __("OPML Import"),
|
||||
style: "width: 600px",
|
||||
onCancel: function () {
|
||||
window.location.reload();
|
||||
},
|
||||
execute: function () {
|
||||
window.location.reload();
|
||||
},
|
||||
content: content
|
||||
});
|
||||
|
||||
dojo.connect(dialog, "onShow", function () {
|
||||
Element.hide(iframe);
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
export: function() {
|
||||
console.log("export");
|
||||
window.open("backend.php?op=opml&method=export&" + dojo.formToQuery("opmlExportForm"));
|
||||
},
|
||||
changeKey: function() {
|
||||
if (confirm(__("Replace current OPML publishing address with a new one?"))) {
|
||||
Notify.progress("Trying to change address...", true);
|
||||
|
||||
xhrJson("backend.php", {op: "pref-feeds", method: "regenOPMLKey"}, (reply) => {
|
||||
if (reply) {
|
||||
const new_link = reply.link;
|
||||
const e = $('pub_opml_url');
|
||||
|
||||
if (new_link) {
|
||||
e.href = new_link;
|
||||
e.innerHTML = new_link;
|
||||
|
||||
new Effect.Highlight(e);
|
||||
|
||||
Notify.close();
|
||||
|
||||
} else {
|
||||
Notify.error("Could not change feed URL.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
return Helpers;
|
||||
});
|
||||
+123
-1
@@ -37,7 +37,129 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree", "dijit/f
|
||||
getIconClass: function (item, opened) {
|
||||
return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "invisible";
|
||||
},
|
||||
});
|
||||
getSelectedLabels: function() {
|
||||
const tree = this;
|
||||
const items = tree.model.getCheckedItems();
|
||||
const rv = [];
|
||||
|
||||
items.each(function(item) {
|
||||
rv.push(tree.model.store.getValue(item, 'bare_id'));
|
||||
});
|
||||
|
||||
return rv;
|
||||
},
|
||||
reload: function() {
|
||||
xhrPost("backend.php", { op: "pref-labels" }, (transport) => {
|
||||
dijit.byId('labelConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
editLabel: function(id) {
|
||||
const query = "backend.php?op=pref-labels&method=edit&id=" +
|
||||
encodeURIComponent(id);
|
||||
|
||||
if (dijit.byId("labelEditDlg"))
|
||||
dijit.byId("labelEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "labelEditDlg",
|
||||
title: __("Label Editor"),
|
||||
style: "width: 600px",
|
||||
setLabelColor: function (id, fg, bg) {
|
||||
|
||||
let kind = '';
|
||||
let color = '';
|
||||
|
||||
if (fg && bg) {
|
||||
kind = 'both';
|
||||
} else if (fg) {
|
||||
kind = 'fg';
|
||||
color = fg;
|
||||
} else if (bg) {
|
||||
kind = 'bg';
|
||||
color = bg;
|
||||
}
|
||||
|
||||
const e = $("LICID-" + id);
|
||||
|
||||
if (e) {
|
||||
if (fg) e.style.color = fg;
|
||||
if (bg) e.style.backgroundColor = bg;
|
||||
}
|
||||
|
||||
const query = {
|
||||
op: "pref-labels", method: "colorset", kind: kind,
|
||||
ids: id, fg: fg, bg: bg, color: color
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
dijit.byId("filterTree").reload(); // maybe there's labels in there
|
||||
});
|
||||
|
||||
},
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
const caption = this.attr('value').caption;
|
||||
const fg_color = this.attr('value').fg_color;
|
||||
const bg_color = this.attr('value').bg_color;
|
||||
|
||||
dijit.byId('labelTree').setNameById(id, caption);
|
||||
this.setLabelColor(id, fg_color, bg_color);
|
||||
this.hide();
|
||||
|
||||
xhrPost("backend.php", this.attr('value'), () => {
|
||||
dijit.byId("filterTree").reload(); // maybe there's labels in there
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
resetColors: function() {
|
||||
const labels = this.getSelectedLabels();
|
||||
|
||||
if (labels.length > 0) {
|
||||
if (confirm(__("Reset selected labels to default colors?"))) {
|
||||
|
||||
const query = {
|
||||
op: "pref-labels", method: "colorreset",
|
||||
ids: labels.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No labels selected."));
|
||||
}
|
||||
},
|
||||
removeSelected: function() {
|
||||
const sel_rows = this.getSelectedLabels();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected labels?"))) {
|
||||
Notify.progress("Removing selected labels...");
|
||||
|
||||
const query = {
|
||||
op: "pref-labels", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert(__("No labels selected."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
'use strict'
|
||||
/* global __, ngettext */
|
||||
define(["dojo/_base/declare"], function (declare) {
|
||||
Users = {
|
||||
reload: function(sort) {
|
||||
const user_search = $("user_search");
|
||||
const search = user_search ? user_search.value : "";
|
||||
|
||||
xhrPost("backend.php", { op: "pref-users", sort: sort, search: search }, (transport) => {
|
||||
dijit.byId('userConfigTab').attr('content', transport.responseText);
|
||||
Notify.close();
|
||||
});
|
||||
},
|
||||
add: function() {
|
||||
const login = prompt(__("Please enter username:"), "");
|
||||
|
||||
if (login) {
|
||||
Notify.progress("Adding user...");
|
||||
|
||||
xhrPost("backend.php", {op: "pref-users", method: "add", login: login}, (transport) => {
|
||||
alert(transport.responseText);
|
||||
Users.reload();
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
edit: function(id) {
|
||||
const query = "backend.php?op=pref-users&method=edit&id=" +
|
||||
encodeURIComponent(id);
|
||||
|
||||
if (dijit.byId("userEditDlg"))
|
||||
dijit.byId("userEditDlg").destroyRecursive();
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "userEditDlg",
|
||||
title: __("User Editor"),
|
||||
style: "width: 600px",
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
Notify.progress("Saving data...", true);
|
||||
|
||||
xhrPost("backend.php", dojo.formToObject("user_edit_form"), (transport) => {
|
||||
dialog.hide();
|
||||
Users.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
resetSelected: function() {
|
||||
const rows = this.getSelection();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No users selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rows.length > 1) {
|
||||
alert(__("Please select one user."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(__("Reset password of selected user?"))) {
|
||||
Notify.progress("Resetting password for selected user...");
|
||||
|
||||
const id = rows[0];
|
||||
|
||||
xhrPost("backend.php", {op: "pref-users", method: "resetPass", id: id}, (transport) => {
|
||||
Notify.close();
|
||||
alert(transport.responseText);
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
removeSelected: function() {
|
||||
const sel_rows = this.getSelection();
|
||||
|
||||
if (sel_rows.length > 0) {
|
||||
if (confirm(__("Remove selected users? Neither default admin nor your account will be removed."))) {
|
||||
Notify.progress("Removing selected users...");
|
||||
|
||||
const query = {
|
||||
op: "pref-users", method: "remove",
|
||||
ids: sel_rows.toString()
|
||||
};
|
||||
|
||||
xhrPost("backend.php", query, () => {
|
||||
this.reload();
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
alert(__("No users selected."));
|
||||
}
|
||||
},
|
||||
editSelected: function() {
|
||||
const rows = this.getSelection();
|
||||
|
||||
if (rows.length == 0) {
|
||||
alert(__("No users selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rows.length > 1) {
|
||||
alert(__("Please select one user."));
|
||||
return;
|
||||
}
|
||||
|
||||
this.edit(rows[0]);
|
||||
},
|
||||
getSelection :function() {
|
||||
return Tables.getSelected("prefUserList");
|
||||
}
|
||||
}
|
||||
|
||||
return Users;
|
||||
});
|
||||
|
||||
|
||||
Executable
+311
@@ -0,0 +1,311 @@
|
||||
'use strict'
|
||||
/* global dijit, __ */
|
||||
|
||||
let _label_base_index = -1024;
|
||||
let loading_progress = 0;
|
||||
|
||||
/* error reporting shim */
|
||||
|
||||
// TODO: deprecated; remove
|
||||
function exception_error(e, e_compat, filename, lineno, colno) {
|
||||
if (typeof e == "string")
|
||||
e = e_compat;
|
||||
|
||||
App.Error.report(e, {filename: filename, lineno: lineno, colno: colno});
|
||||
}
|
||||
|
||||
/* xhr shorthand helpers */
|
||||
|
||||
function xhrPost(url, params, complete) {
|
||||
console.log("xhrPost:", params);
|
||||
return new Ajax.Request(url, {
|
||||
parameters: params,
|
||||
onComplete: complete
|
||||
});
|
||||
}
|
||||
|
||||
function xhrJson(url, params, complete) {
|
||||
return xhrPost(url, params, (reply) => {
|
||||
try {
|
||||
const obj = JSON.parse(reply.responseText);
|
||||
complete(obj);
|
||||
} catch (e) {
|
||||
console.error("xhrJson", e, reply);
|
||||
complete(null);
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
/* add method to remove element from array */
|
||||
Array.prototype.remove = function(s) {
|
||||
for (let i=0; i < this.length; i++) {
|
||||
if (s == this[i]) this.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/* common helpers not worthy of separate Dojo modules */
|
||||
|
||||
const Lists = {
|
||||
onRowChecked: function(elem) {
|
||||
const checked = elem.domNode ? elem.attr("checked") : elem.checked;
|
||||
// account for dojo checkboxes
|
||||
elem = elem.domNode || elem;
|
||||
|
||||
const row = elem.up("li");
|
||||
|
||||
if (row)
|
||||
checked ? row.addClassName("Selected") : row.removeClassName("Selected");
|
||||
}
|
||||
};
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
const Tables = {
|
||||
onRowChecked: function(elem) {
|
||||
// account for dojo checkboxes
|
||||
const checked = elem.domNode ? elem.attr("checked") : elem.checked;
|
||||
elem = elem.domNode || elem;
|
||||
|
||||
const row = elem.up("tr");
|
||||
|
||||
if (row)
|
||||
checked ? row.addClassName("Selected") : row.removeClassName("Selected");
|
||||
|
||||
},
|
||||
select: function(elemId, selected) {
|
||||
$(elemId).select("tr").each((row) => {
|
||||
const checkNode = row.select(".dijitCheckBox,input[type=checkbox]")[0];
|
||||
if (checkNode) {
|
||||
const widget = dijit.getEnclosingWidget(checkNode);
|
||||
|
||||
if (widget) {
|
||||
widget.attr("checked", selected);
|
||||
} else {
|
||||
checkNode.checked = selected;
|
||||
}
|
||||
|
||||
this.onRowChecked(widget);
|
||||
}
|
||||
});
|
||||
},
|
||||
getSelected: function(elemId) {
|
||||
const rv = [];
|
||||
|
||||
$(elemId).select("tr").each((row) => {
|
||||
if (row.hasClassName("Selected")) {
|
||||
// either older prefix-XXX notation or separate attribute
|
||||
const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, "");
|
||||
|
||||
if (!isNaN(rowId))
|
||||
rv.push(parseInt(rowId));
|
||||
}
|
||||
});
|
||||
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
const Cookie = {
|
||||
set: function (name, value, lifetime) {
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + lifetime * 1000);
|
||||
const expires = "expires=" + d.toUTCString();
|
||||
document.cookie = name + "=" + encodeURIComponent(value) + "; " + expires;
|
||||
},
|
||||
get: function (name) {
|
||||
name = name + "=";
|
||||
const ca = document.cookie.split(';');
|
||||
for (let i=0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1);
|
||||
if (c.indexOf(name) == 0) return decodeURIComponent(c.substring(name.length, c.length));
|
||||
}
|
||||
return "";
|
||||
},
|
||||
delete: function(name) {
|
||||
const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
document.cookie = name + "=" + "" + "; " + expires;
|
||||
}
|
||||
};
|
||||
|
||||
/* runtime notifications */
|
||||
|
||||
const Notify = {
|
||||
KIND_GENERIC: 0,
|
||||
KIND_INFO: 1,
|
||||
KIND_ERROR: 2,
|
||||
KIND_PROGRESS: 3,
|
||||
timeout: 0,
|
||||
default_timeout: 5 * 1000,
|
||||
close: function() {
|
||||
this.msg("");
|
||||
},
|
||||
msg: function(msg, keep, kind) {
|
||||
kind = kind || this.KIND_GENERIC;
|
||||
keep = keep || false;
|
||||
|
||||
const notify = $("notify");
|
||||
|
||||
window.clearTimeout(this.timeout);
|
||||
|
||||
if (!msg) {
|
||||
notify.removeClassName("visible");
|
||||
return;
|
||||
}
|
||||
|
||||
let msgfmt = "<span class=\"msg\">%s</span>".replace("%s", __(msg));
|
||||
let icon = false;
|
||||
|
||||
|
||||
notify.className = "notify";
|
||||
|
||||
console.warn('notify', msg, kind);
|
||||
|
||||
switch (kind) {
|
||||
case this.KIND_INFO:
|
||||
notify.addClassName("notify_info")
|
||||
icon = App.getInitParam("icon_information");
|
||||
break;
|
||||
case this.KIND_ERROR:
|
||||
notify.addClassName("notify_error");
|
||||
icon = App.getInitParam("icon_alert");
|
||||
break;
|
||||
case this.KIND_PROGRESS:
|
||||
notify.addClassName("notify_progress");
|
||||
icon = App.getInitParam("icon_indicator_white")
|
||||
break;
|
||||
}
|
||||
|
||||
if (icon) msgfmt = "<span><img src=\"%s\"></span>".replace("%s", icon) + msgfmt;
|
||||
|
||||
msgfmt += (" <span><img src=\"%s\" class='close' title=\"" +
|
||||
__("Click to close") + "\" onclick=\"Notify.close()\"></span>")
|
||||
.replace("%s", App.getInitParam("icon_cross"));
|
||||
|
||||
notify.innerHTML = msgfmt;
|
||||
notify.addClassName("visible");
|
||||
|
||||
if (!keep)
|
||||
this.timeout = window.setTimeout(() => {
|
||||
notify.removeClassName("visible");
|
||||
}, this.default_timeout);
|
||||
|
||||
},
|
||||
info: function(msg, keep) {
|
||||
keep = keep || false;
|
||||
this.msg(msg, keep, this.KIND_INFO);
|
||||
},
|
||||
progress: function(msg, keep) {
|
||||
keep = keep || true;
|
||||
this.msg(msg, keep, this.KIND_PROGRESS);
|
||||
},
|
||||
error: function(msg, keep) {
|
||||
keep = keep || true;
|
||||
this.msg(msg, keep, this.KIND_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function displayIfChecked(checkbox, elemId) {
|
||||
if (checkbox.checked) {
|
||||
Effect.Appear(elemId, {duration : 0.5});
|
||||
} else {
|
||||
Effect.Fade(elemId, {duration : 0.5});
|
||||
}
|
||||
}
|
||||
|
||||
function fatalError(code, msg, ext_info) {
|
||||
if (code == 6) {
|
||||
window.location.href = "index.php";
|
||||
} else if (code == 5) {
|
||||
window.location.href = "public.php?op=dbupdate";
|
||||
} else {
|
||||
|
||||
if (msg == "") msg = "Unknown error";
|
||||
|
||||
if (ext_info) {
|
||||
if (ext_info.responseText) {
|
||||
ext_info = ext_info.responseText;
|
||||
}
|
||||
}
|
||||
|
||||
/* global ERRORS */
|
||||
if (ERRORS && ERRORS[code] && !msg) {
|
||||
msg = ERRORS[code];
|
||||
}
|
||||
|
||||
let content = "<div><b>Error code:</b> " + code + "</div>" +
|
||||
"<p>" + msg + "</p>";
|
||||
|
||||
if (ext_info) {
|
||||
content = content + "<div><b>Additional information:</b></div>" +
|
||||
"<textarea style='width: 100%' readonly=\"1\">" +
|
||||
ext_info + "</textarea>";
|
||||
}
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
title: "Fatal error",
|
||||
style: "width: 600px",
|
||||
content: content});
|
||||
|
||||
dialog.show();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/* function strip_tags(s) {
|
||||
return s.replace(/<\/?[^>]+(>|$)/g, "");
|
||||
} */
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function label_to_feed_id(label) {
|
||||
return _label_base_index - 1 - Math.abs(label);
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function feed_to_label_id(feed) {
|
||||
return _label_base_index - 1 + Math.abs(feed);
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/6251937/how-to-get-selecteduser-highlighted-text-in-contenteditable-element-and-replac
|
||||
function getSelectionText() {
|
||||
let text = "";
|
||||
|
||||
if (typeof window.getSelection != "undefined") {
|
||||
const sel = window.getSelection();
|
||||
if (sel.rangeCount) {
|
||||
const container = document.createElement("div");
|
||||
for (let i = 0, len = sel.rangeCount; i < len; ++i) {
|
||||
container.appendChild(sel.getRangeAt(i).cloneContents());
|
||||
}
|
||||
text = container.innerHTML;
|
||||
}
|
||||
} else if (typeof document.selection != "undefined") {
|
||||
if (document.selection.type == "Text") {
|
||||
text = document.selection.createRange().textText;
|
||||
}
|
||||
}
|
||||
|
||||
return text.stripTags();
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function popupOpenUrl(url) {
|
||||
const w = window.open("");
|
||||
|
||||
w.opener = null;
|
||||
w.location = url;
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function popupOpenArticle(id) {
|
||||
const w = window.open("",
|
||||
"ttrss_article_popup",
|
||||
"height=900,width=900,resizable=yes,status=no,location=no,menubar=no,directories=no,scrollbars=yes,toolbar=no");
|
||||
|
||||
w.opener = null;
|
||||
w.location = "backend.php?op=article&method=view&mode=raw&html=1&zoom=1&id=" + id + "&csrf_token=" + App.getInitParam("csrf_token");
|
||||
}
|
||||
-532
@@ -1,532 +0,0 @@
|
||||
let infscroll_in_progress = 0;
|
||||
let infscroll_disabled = 0;
|
||||
|
||||
let _infscroll_timeout = false;
|
||||
let _search_query = false;
|
||||
let _viewfeed_wait_timeout = false;
|
||||
|
||||
let counters_last_request = 0;
|
||||
let _counters_prev = [];
|
||||
|
||||
function resetCounterCache() {
|
||||
_counters_prev = [];
|
||||
}
|
||||
|
||||
function loadMoreHeadlines() {
|
||||
const view_mode = document.forms["main_toolbar_form"].view_mode.value;
|
||||
const unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length;
|
||||
const num_all = $$("#headlines-frame > div[id*=RROW]").length;
|
||||
const num_unread = getFeedUnread(getActiveFeedId(), activeFeedIsCat());
|
||||
|
||||
// TODO implement marked & published
|
||||
|
||||
let offset = num_all;
|
||||
|
||||
switch (view_mode) {
|
||||
case "marked":
|
||||
case "published":
|
||||
console.warn("loadMoreHeadlines: ", view_mode, "not implemented");
|
||||
break;
|
||||
case "unread":
|
||||
offset = unread_in_buffer;
|
||||
break;
|
||||
case "adaptive":
|
||||
if (!(getActiveFeedId() == -1 && !activeFeedIsCat()))
|
||||
offset = num_unread > 0 ? unread_in_buffer : num_all;
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("loadMoreHeadlines, offset=", offset);
|
||||
|
||||
viewfeed({feed: getActiveFeedId(), is_cat: activeFeedIsCat(), offset: offset, infscroll_req: true});
|
||||
}
|
||||
|
||||
function cleanup_memory(root) {
|
||||
const dijits = dojo.query("[widgetid]", dijit.byId(root).domNode).map(dijit.byNode);
|
||||
|
||||
dijits.each(function (d) {
|
||||
dojo.destroy(d.domNode);
|
||||
});
|
||||
|
||||
$$("#" + root + " *").each(function (i) {
|
||||
i.parentNode ? i.parentNode.removeChild(i) : true;
|
||||
});
|
||||
}
|
||||
|
||||
function viewfeed(params) {
|
||||
const feed = params.feed;
|
||||
const is_cat = !!params.is_cat || false;
|
||||
const offset = params.offset || 0;
|
||||
const viewfeed_debug = params.viewfeed_debug;
|
||||
const method = params.method;
|
||||
// this is used to quickly switch between feeds, sets active but xhr is on a timeout
|
||||
const delayed = params.delayed || false;
|
||||
|
||||
if (feed != getActiveFeedId() || activeFeedIsCat() != is_cat) {
|
||||
_search_query = false;
|
||||
setActiveArticleId(0);
|
||||
}
|
||||
|
||||
if (offset != 0) {
|
||||
if (infscroll_in_progress)
|
||||
return;
|
||||
|
||||
infscroll_in_progress = 1;
|
||||
|
||||
window.clearTimeout(_infscroll_timeout);
|
||||
_infscroll_timeout = window.setTimeout(() => {
|
||||
console.log('infscroll request timed out, aborting');
|
||||
infscroll_in_progress = 0;
|
||||
|
||||
// call scroll handler to maybe repeat infscroll request
|
||||
headlinesScrollHandler();
|
||||
}, 10 * 1000);
|
||||
}
|
||||
|
||||
Form.enable("main_toolbar_form");
|
||||
|
||||
let query = Object.assign({op: "feeds", method: "view", feed: feed},
|
||||
dojo.formToObject("main_toolbar_form"));
|
||||
|
||||
if (method) query.m = method;
|
||||
|
||||
if (offset > 0) {
|
||||
if (current_first_id) {
|
||||
query.fid = current_first_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (_search_query) {
|
||||
query = Object.assign(query, _search_query);
|
||||
}
|
||||
|
||||
if (offset != 0) {
|
||||
query.skip = offset;
|
||||
|
||||
// to prevent duplicate feed titles when showing grouped vfeeds
|
||||
if (vgroup_last_feed) {
|
||||
query.vgrlf = vgroup_last_feed;
|
||||
}
|
||||
} else if (!is_cat && feed == getActiveFeedId() && !params.method) {
|
||||
query.m = "ForceUpdate";
|
||||
}
|
||||
|
||||
Form.enable("main_toolbar_form");
|
||||
|
||||
if (!delayed)
|
||||
if (!setFeedExpandoIcon(feed, is_cat,
|
||||
(is_cat) ? 'images/indicator_tiny.gif' : 'images/indicator_white.gif'))
|
||||
notify_progress("Loading, please wait...", true);
|
||||
|
||||
query.cat = is_cat;
|
||||
|
||||
setActiveFeedId(feed, is_cat);
|
||||
|
||||
if (viewfeed_debug) {
|
||||
window.open("backend.php?" +
|
||||
dojo.objectToQuery(
|
||||
Object.assign({debug: 1, csrf_token: getInitParam("csrf_token")}, query)
|
||||
));
|
||||
}
|
||||
|
||||
window.clearTimeout(_viewfeed_wait_timeout);
|
||||
_viewfeed_wait_timeout = window.setTimeout(() => {
|
||||
catchupBatchedArticles(() => {
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
try {
|
||||
setFeedExpandoIcon(feed, is_cat, 'images/blank_icon.gif');
|
||||
headlines_callback2(transport, offset);
|
||||
PluginHost.run(PluginHost.HOOK_FEED_LOADED, [feed, is_cat]);
|
||||
} catch (e) {
|
||||
exception_error(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, delayed ? 250 : 0);
|
||||
}
|
||||
|
||||
function feedlist_init() {
|
||||
console.log("in feedlist init");
|
||||
|
||||
setLoadingProgress(50);
|
||||
|
||||
document.onkeydown = hotkey_handler;
|
||||
setInterval(hotkeyPrefixTimeout, 3*1000);
|
||||
setInterval(catchupBatchedArticles, 10*1000);
|
||||
|
||||
if (!getActiveFeedId()) {
|
||||
viewfeed({feed: -3});
|
||||
} else {
|
||||
viewfeed({feed: getActiveFeedId(), is_cat: activeFeedIsCat()});
|
||||
}
|
||||
|
||||
hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
|
||||
|
||||
if (getInitParam("is_default_pw")) {
|
||||
console.warn("user password is at default value");
|
||||
|
||||
const dialog = new dijit.Dialog({
|
||||
title: __("Your password is at default value"),
|
||||
href: "backend.php?op=dlg&method=defaultpasswordwarning",
|
||||
id: 'infoBox',
|
||||
style: "width: 600px",
|
||||
onCancel: function() {
|
||||
return true;
|
||||
},
|
||||
onExecute: function() {
|
||||
return true;
|
||||
},
|
||||
onClose: function() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// bw_limit disables timeout() so we request initial counters separately
|
||||
if (getInitParam("bw_limit") == "1") {
|
||||
request_counters(true);
|
||||
} else {
|
||||
setTimeout(timeout, 250);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function request_counters(force) {
|
||||
const date = new Date();
|
||||
const timestamp = Math.round(date.getTime() / 1000);
|
||||
|
||||
if (force || timestamp - counters_last_request > 5) {
|
||||
console.log("scheduling request of counters...");
|
||||
|
||||
counters_last_request = timestamp;
|
||||
|
||||
let query = {op: "rpc", method: "getAllCounters", seq: next_seq()};
|
||||
|
||||
if (!force)
|
||||
query.last_article_id = getInitParam("last_article_id");
|
||||
|
||||
xhrPost("backend.php", query, (transport) => {
|
||||
handle_rpc_json(transport);
|
||||
});
|
||||
|
||||
} else {
|
||||
console.log("request_counters: rate limit reached: " + (timestamp - counters_last_request));
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this implementation is incomplete
|
||||
// for general objects but good enough for counters
|
||||
// http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
|
||||
function counter_is_equal(a, b) {
|
||||
// Create arrays of property names
|
||||
const aProps = Object.getOwnPropertyNames(a);
|
||||
const bProps = Object.getOwnPropertyNames(b);
|
||||
|
||||
// If number of properties is different,
|
||||
// objects are not equivalent
|
||||
if (aProps.length != bProps.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < aProps.length; i++) {
|
||||
const propName = aProps[i];
|
||||
|
||||
// If values of same property are not equal,
|
||||
// objects are not equivalent
|
||||
if (a[propName] !== b[propName]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we made it this far, objects
|
||||
// are considered equivalent
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function parse_counters(elems) {
|
||||
for (let l = 0; l < elems.length; l++) {
|
||||
|
||||
if (_counters_prev[l] && counter_is_equal(elems[l], _counters_prev[l])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const id = elems[l].id;
|
||||
const kind = elems[l].kind;
|
||||
const ctr = parseInt(elems[l].counter);
|
||||
const error = elems[l].error;
|
||||
const has_img = elems[l].has_img;
|
||||
const updated = elems[l].updated;
|
||||
const auxctr = parseInt(elems[l].auxcounter);
|
||||
|
||||
if (id == "global-unread") {
|
||||
global_unread = ctr;
|
||||
updateTitle();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id == "subscribed-feeds") {
|
||||
/* feeds_found = ctr; */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (getFeedUnread(id, (kind == "cat")) != ctr ||
|
||||
(kind == "cat")) {
|
||||
}*/
|
||||
|
||||
setFeedUnread(id, (kind == "cat"), ctr);
|
||||
setFeedValue(id, (kind == "cat"), 'auxcounter', auxctr);
|
||||
|
||||
if (kind != "cat") {
|
||||
setFeedValue(id, false, 'error', error);
|
||||
setFeedValue(id, false, 'updated', updated);
|
||||
|
||||
if (id > 0) {
|
||||
if (has_img) {
|
||||
setFeedIcon(id, false,
|
||||
getInitParam("icons_url") + "/" + id + ".ico?" + has_img);
|
||||
} else {
|
||||
setFeedIcon(id, false, 'images/blank_icon.gif');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
|
||||
|
||||
_counters_prev = elems;
|
||||
}
|
||||
|
||||
function getFeedUnread(feed, is_cat) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedUnread(feed, is_cat);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function getFeedCategory(feed) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.getFeedCategory(feed);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function hideOrShowFeeds(hide) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree)
|
||||
return tree.hideRead(hide, getInitParam("hide_read_shows_special"));
|
||||
}
|
||||
|
||||
function getFeedName(feed, is_cat) {
|
||||
|
||||
if (isNaN(feed)) return feed; // it's a tag
|
||||
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedValue(feed, is_cat, 'name');
|
||||
}
|
||||
|
||||
/* function getFeedValue(feed, is_cat, key) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.getFeedValue(feed, is_cat, key);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
return '';
|
||||
} */
|
||||
|
||||
function setFeedUnread(feed, is_cat, unread) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.setFeedUnread(feed, is_cat, unread);
|
||||
}
|
||||
|
||||
function setFeedValue(feed, is_cat, key, value) {
|
||||
try {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree && tree.model)
|
||||
return tree.model.setFeedValue(feed, is_cat, key, value);
|
||||
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
function selectFeed(feed, is_cat) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.selectFeed(feed, is_cat);
|
||||
}
|
||||
|
||||
function setFeedIcon(feed, is_cat, src) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.setFeedIcon(feed, is_cat, src);
|
||||
}
|
||||
|
||||
function setFeedExpandoIcon(feed, is_cat, src) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
|
||||
if (tree) return tree.setFeedExpandoIcon(feed, is_cat, src);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNextUnreadFeed(feed, is_cat) {
|
||||
const tree = dijit.byId("feedTree");
|
||||
const nuf = tree.model.getNextUnreadFeed(feed, is_cat);
|
||||
|
||||
if (nuf)
|
||||
return tree.model.store.getValue(nuf, 'bare_id');
|
||||
}
|
||||
|
||||
function catchupCurrentFeed(mode) {
|
||||
catchupFeed(getActiveFeedId(), activeFeedIsCat(), mode);
|
||||
}
|
||||
|
||||
function catchupFeedInGroup(id) {
|
||||
const title = getFeedName(id);
|
||||
|
||||
const str = __("Mark all articles in %s as read?").replace("%s", title);
|
||||
|
||||
if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
|
||||
|
||||
const rows = $$("#headlines-frame > div[id*=RROW][data-orig-feed-id='"+id+"']");
|
||||
|
||||
if (rows.length > 0) {
|
||||
|
||||
rows.each(function (row) {
|
||||
row.removeClassName("Unread");
|
||||
|
||||
if (row.getAttribute("data-article-id") != getActiveArticleId()) {
|
||||
new Effect.Fade(row, {duration: 0.5});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const feedTitles = $$("#headlines-frame > div[class='feed-title']");
|
||||
|
||||
for (let i = 0; i < feedTitles.length; i++) {
|
||||
if (feedTitles[i].getAttribute("data-feed-id") == id) {
|
||||
|
||||
if (i < feedTitles.length - 1) {
|
||||
new Effect.Fade(feedTitles[i], {duration: 0.5});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateFloatingTitle(true);
|
||||
}
|
||||
|
||||
notify_progress("Loading, please wait...", true);
|
||||
|
||||
xhrPost("backend.php", { op: "rpc", method: "catchupFeed", feed_id: id, is_cat: false}, (transport) => {
|
||||
handle_rpc_json(transport);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function catchupFeed(feed, is_cat, mode) {
|
||||
if (is_cat == undefined) is_cat = false;
|
||||
|
||||
let str = false;
|
||||
|
||||
switch (mode) {
|
||||
case "1day":
|
||||
str = __("Mark %w in %s older than 1 day as read?");
|
||||
break;
|
||||
case "1week":
|
||||
str = __("Mark %w in %s older than 1 week as read?");
|
||||
break;
|
||||
case "2week":
|
||||
str = __("Mark %w in %s older than 2 weeks as read?");
|
||||
break;
|
||||
default:
|
||||
str = __("Mark %w in %s as read?");
|
||||
}
|
||||
|
||||
const mark_what = last_search_query && last_search_query[0] ? __("search results") : __("all articles");
|
||||
const fn = getFeedName(feed, is_cat);
|
||||
|
||||
str = str.replace("%s", fn)
|
||||
.replace("%w", mark_what);
|
||||
|
||||
if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const catchup_query = {op: 'rpc', method: 'catchupFeed', feed_id: feed,
|
||||
is_cat: is_cat, mode: mode, search_query: last_search_query[0],
|
||||
search_lang: last_search_query[1]};
|
||||
|
||||
notify_progress("Loading, please wait...", true);
|
||||
|
||||
xhrPost("backend.php", catchup_query, (transport) => {
|
||||
handle_rpc_json(transport);
|
||||
|
||||
const show_next_feed = getInitParam("on_catchup_show_next_feed") == "1";
|
||||
|
||||
if (show_next_feed) {
|
||||
const nuf = getNextUnreadFeed(feed, is_cat);
|
||||
|
||||
if (nuf) {
|
||||
viewfeed({feed: nuf, is_cat: is_cat});
|
||||
}
|
||||
} else if (feed == getActiveFeedId() && is_cat == activeFeedIsCat()) {
|
||||
viewCurrentFeed();
|
||||
}
|
||||
|
||||
notify("");
|
||||
});
|
||||
}
|
||||
|
||||
function decrementFeedCounter(feed, is_cat) {
|
||||
let ctr = getFeedUnread(feed, is_cat);
|
||||
|
||||
if (ctr > 0) {
|
||||
setFeedUnread(feed, is_cat, ctr - 1);
|
||||
global_unread = global_unread - 1;
|
||||
updateTitle();
|
||||
|
||||
if (!is_cat) {
|
||||
const cat = parseInt(getFeedCategory(feed));
|
||||
|
||||
if (!isNaN(cat)) {
|
||||
ctr = getFeedUnread(cat, true);
|
||||
|
||||
if (ctr > 0) {
|
||||
setFeedUnread(cat, true, ctr - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
-1521
File diff suppressed because it is too large
Load Diff
+134
-1203
File diff suppressed because it is too large
Load Diff
+530
-883
File diff suppressed because it is too large
Load Diff
-1656
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1686
-1634
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1687
-1632
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1785
-1757
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1672
-1617
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1692
-1654
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1650
-1595
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1692
-1654
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1699
-1652
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1689
-1651
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1686
-1631
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1680
-1625
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1690
-1638
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1693
-1638
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1682
-1630
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1675
-1644
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1699
-1645
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1784
-1756
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1687
-1639
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1680
-1625
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1644
-1589
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1697
-1645
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1675
-1631
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1690
-1639
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1666
-1614
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1745
-1693
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1709
-1662
File diff suppressed because it is too large
Load Diff
+1470
-1453
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
function showTrgmRelated(id) {
|
||||
try {
|
||||
|
||||
const query = "backend.php?op=pluginhandler&plugin=af_psql_trgm&method=showrelated¶m=" + param_escape(id);
|
||||
Plugins.Psql_Trgm = {
|
||||
showRelated: function (id) {
|
||||
const query = "backend.php?op=pluginhandler&plugin=af_psql_trgm&method=showrelated¶m=" + encodeURIComponent(id);
|
||||
|
||||
if (dijit.byId("trgmRelatedDlg"))
|
||||
dijit.byId("trgmRelatedDlg").destroyRecursive();
|
||||
@@ -10,16 +9,13 @@ function showTrgmRelated(id) {
|
||||
id: "trgmRelatedDlg",
|
||||
title: __("Related articles"),
|
||||
style: "width: 600px",
|
||||
execute: function() {
|
||||
execute: function () {
|
||||
|
||||
},
|
||||
href: query,
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
|
||||
} catch (e) {
|
||||
exception_error("showTrgmRelated", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ class Af_Psql_Trgm extends Plugin {
|
||||
print " <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"$article_link\">".
|
||||
$line["title"]."</a>";
|
||||
|
||||
print " (<a href=\"#\" onclick=\"viewfeed({feed:".$line["feed_id"]."})\">".
|
||||
print " (<a href=\"#\" onclick=\"Feeds.open({feed:".$line["feed_id"]."})\">".
|
||||
htmlspecialchars($line["feed_title"])."</a>)";
|
||||
|
||||
print " <span class='insensitive'>($sm)</span>";
|
||||
@@ -115,7 +115,7 @@ class Af_Psql_Trgm extends Plugin {
|
||||
function hook_article_button($line) {
|
||||
return "<img src=\"plugins/af_psql_trgm/button.png\"
|
||||
style=\"cursor : pointer\" style=\"cursor : pointer\"
|
||||
onclick=\"showTrgmRelated(".$line["id"].")\"
|
||||
onclick=\"Plugins.Psql_Trgm.showRelated(".$line["id"].")\"
|
||||
class='tagsPic' title='".__('Show related articles')."'>";
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ class Af_Psql_Trgm extends Plugin {
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify_info(transport.responseText);
|
||||
Notify.info(transport.responseText);
|
||||
}
|
||||
});
|
||||
//this.reset();
|
||||
@@ -202,7 +202,7 @@ class Af_Psql_Trgm extends Plugin {
|
||||
print "<li>" .
|
||||
"<img src='images/pub_set.png'
|
||||
style='vertical-align : middle'> <a href='#'
|
||||
onclick='editFeed($f)'>" .
|
||||
onclick='CommonDialogs.editFeed($f)'>" .
|
||||
Feeds::getFeedTitle($f) . "</a></li>";
|
||||
}
|
||||
print "</ul>";
|
||||
|
||||
@@ -61,7 +61,7 @@ class Af_Readability extends Plugin {
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify_info(transport.responseText);
|
||||
Notify.info(transport.responseText);
|
||||
}
|
||||
});
|
||||
//this.reset();
|
||||
@@ -94,7 +94,7 @@ class Af_Readability extends Plugin {
|
||||
print "<li>" .
|
||||
"<img src='images/pub_set.png'
|
||||
style='vertical-align : middle'> <a href='#'
|
||||
onclick='editFeed($f)'>".
|
||||
onclick='CommonDialogs.editFeed($f)'>".
|
||||
Feeds::getFeedTitle($f) . "</a></li>";
|
||||
}
|
||||
print "</ul>";
|
||||
|
||||
@@ -45,7 +45,7 @@ class Af_RedditImgur extends Plugin {
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify_info(transport.responseText);
|
||||
Notify.info(transport.responseText);
|
||||
}
|
||||
});
|
||||
//this.reset();
|
||||
|
||||
@@ -216,7 +216,7 @@ class Af_Zz_ImgProxy extends Plugin {
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify_info(transport.responseText);
|
||||
Notify.info(transport.responseText);
|
||||
}
|
||||
});
|
||||
//this.reset();
|
||||
|
||||
@@ -21,7 +21,7 @@ class Close_Button extends Plugin {
|
||||
if (!get_pref("COMBINED_DISPLAY_MODE")) {
|
||||
$rv = "<img src=\"plugins/close_button/button.png\"
|
||||
class='tagsPic' style=\"cursor : pointer\"
|
||||
onclick=\"closeArticlePanel()\"
|
||||
onclick=\"Article.close()\"
|
||||
title='".__('Close article')."'>";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,60 +1,56 @@
|
||||
function embedOriginalArticle(id) {
|
||||
try {
|
||||
const hasSandbox = "sandbox" in document.createElement("iframe");
|
||||
const hasSandbox = "sandbox" in document.createElement("iframe");
|
||||
|
||||
if (!hasSandbox) {
|
||||
alert(__("Sorry, your browser does not support sandboxed iframes."));
|
||||
return;
|
||||
}
|
||||
|
||||
let c = false;
|
||||
|
||||
if (App.isCombinedMode()) {
|
||||
c = $$("div#RROW-" + id + " div[class=content-inner]")[0];
|
||||
} else if (id == Article.getActive()) {
|
||||
c = $$(".post .content")[0];
|
||||
}
|
||||
|
||||
if (c) {
|
||||
const iframe = c.parentNode.getElementsByClassName("embeddedContent")[0];
|
||||
|
||||
if (iframe) {
|
||||
Element.show(c);
|
||||
c.parentNode.removeChild(iframe);
|
||||
|
||||
if (App.isCombinedMode()) {
|
||||
Article.cdmScrollToId(id, true);
|
||||
}
|
||||
|
||||
if (!hasSandbox) {
|
||||
alert(__("Sorry, your browser does not support sandboxed iframes."));
|
||||
return;
|
||||
}
|
||||
|
||||
let c = false;
|
||||
|
||||
if (isCombinedMode()) {
|
||||
c = $$("div#RROW-" + id + " div[class=content-inner]")[0];
|
||||
} else if (id == getActiveArticleId()) {
|
||||
c = $$(".post .content")[0];
|
||||
}
|
||||
|
||||
if (c) {
|
||||
const iframe = c.parentNode.getElementsByClassName("embeddedContent")[0];
|
||||
|
||||
if (iframe) {
|
||||
Element.show(c);
|
||||
c.parentNode.removeChild(iframe);
|
||||
|
||||
if (isCombinedMode()) {
|
||||
cdmScrollToArticleId(id, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const query = { op: "pluginhandler", plugin: "embed_original", method: "getUrl", id: id };
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
if (reply) {
|
||||
const iframe = new Element("iframe", {
|
||||
class: "embeddedContent",
|
||||
src: reply.url,
|
||||
width: (c.parentNode.offsetWidth - 5) + 'px',
|
||||
height: (c.parentNode.parentNode.offsetHeight - c.parentNode.firstChild.offsetHeight - 5) + 'px',
|
||||
style: "overflow: auto; border: none; min-height: " + (document.body.clientHeight / 2) + "px;",
|
||||
sandbox: 'allow-scripts',
|
||||
});
|
||||
|
||||
if (c) {
|
||||
Element.hide(c);
|
||||
c.parentNode.insertBefore(iframe, c);
|
||||
|
||||
if (isCombinedMode()) {
|
||||
cdmScrollToArticleId(id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
exception_error("embedOriginalArticle", e);
|
||||
}
|
||||
|
||||
const query = { op: "pluginhandler", plugin: "embed_original", method: "getUrl", id: id };
|
||||
|
||||
xhrJson("backend.php", query, (reply) => {
|
||||
if (reply) {
|
||||
const iframe = new Element("iframe", {
|
||||
class: "embeddedContent",
|
||||
src: reply.url,
|
||||
width: (c.parentNode.offsetWidth - 5) + 'px',
|
||||
height: (c.parentNode.parentNode.offsetHeight - c.parentNode.firstChild.offsetHeight - 5) + 'px',
|
||||
style: "overflow: auto; border: none; min-height: " + (document.body.clientHeight / 2) + "px;",
|
||||
sandbox: 'allow-scripts',
|
||||
});
|
||||
|
||||
if (c) {
|
||||
Element.hide(c);
|
||||
c.parentNode.insertBefore(iframe, c);
|
||||
|
||||
if (App.isCombinedMode()) {
|
||||
Article.cdmScrollToId(id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ function exportData() {
|
||||
style: "width: 600px",
|
||||
prepare: function() {
|
||||
|
||||
notify_progress("Loading, please wait...");
|
||||
Notify.progress("Loading, please wait...");
|
||||
|
||||
new Ajax.Request("backend.php", {
|
||||
parameters: "op=pluginhandler&plugin=import_export&method=exportrun&offset=" + exported,
|
||||
@@ -50,10 +50,10 @@ function exportData() {
|
||||
"Error occured, could not export data.";
|
||||
}
|
||||
} catch (e) {
|
||||
exception_error("exportData", e, transport.responseText);
|
||||
App.Error.report(e);
|
||||
}
|
||||
|
||||
notify('');
|
||||
Notify.close();
|
||||
|
||||
} });
|
||||
|
||||
@@ -71,7 +71,7 @@ function exportData() {
|
||||
|
||||
|
||||
} catch (e) {
|
||||
exception_error("exportData", e);
|
||||
App.Error.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ function dataImportComplete(iframe) {
|
||||
|
||||
Element.hide(iframe);
|
||||
|
||||
notify('');
|
||||
Notify.close();
|
||||
|
||||
if (dijit.byId('dataImportDlg'))
|
||||
dijit.byId('dataImportDlg').destroyRecursive();
|
||||
@@ -100,7 +100,7 @@ function dataImportComplete(iframe) {
|
||||
dialog.show();
|
||||
|
||||
} catch (e) {
|
||||
exception_error("dataImportComplete", e);
|
||||
App.Error.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ function importData() {
|
||||
alert(__("Please choose the file first."));
|
||||
return false;
|
||||
} else {
|
||||
notify_progress("Importing, please wait...", true);
|
||||
Notify.progress("Importing, please wait...", true);
|
||||
|
||||
Element.show("data_upload_iframe");
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class Mail extends Plugin {
|
||||
new Ajax.Request('backend.php', {
|
||||
parameters: dojo.objectToQuery(this.getValues()),
|
||||
onComplete: function(transport) {
|
||||
notify_info(transport.responseText);
|
||||
Notify.info(transport.responseText);
|
||||
}
|
||||
});
|
||||
//this.reset();
|
||||
@@ -72,7 +72,7 @@ class Mail extends Plugin {
|
||||
function hook_article_button($line) {
|
||||
return "<img src=\"plugins/mail/mail.png\"
|
||||
class='tagsPic' style=\"cursor : pointer\"
|
||||
onclick=\"emailArticle(".$line["id"].")\"
|
||||
onclick=\"Plugins.Mail.send(".$line["id"].")\"
|
||||
alt='Zoom' title='".__('Forward by email')."'>";
|
||||
}
|
||||
|
||||
|
||||
+15
-16
@@ -1,10 +1,10 @@
|
||||
function emailArticle(id) {
|
||||
try {
|
||||
Plugins.Mail = {
|
||||
send: function(id) {
|
||||
if (!id) {
|
||||
var ids = getSelectedArticleIds2();
|
||||
let ids = Headlines.getSelected();
|
||||
|
||||
if (ids.length == 0) {
|
||||
alert(__("No articles are selected."));
|
||||
alert(__("No articles selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@ function emailArticle(id) {
|
||||
if (dijit.byId("emailArticleDlg"))
|
||||
dijit.byId("emailArticleDlg").destroyRecursive();
|
||||
|
||||
var query = "backend.php?op=pluginhandler&plugin=mail&method=emailArticle¶m=" + param_escape(id);
|
||||
const query = "backend.php?op=pluginhandler&plugin=mail&method=emailArticle¶m=" + encodeURIComponent(id);
|
||||
|
||||
dialog = new dijit.Dialog({
|
||||
const dialog = new dijit.Dialog({
|
||||
id: "emailArticleDlg",
|
||||
title: __("Forward article by email"),
|
||||
style: "width: 600px",
|
||||
execute: function() {
|
||||
execute: function () {
|
||||
if (this.validate()) {
|
||||
xhrJson("backend.php", this.attr('value'), (reply) => {
|
||||
if (reply) {
|
||||
@@ -29,7 +29,7 @@ function emailArticle(id) {
|
||||
if (error) {
|
||||
alert(__('Error sending email:') + ' ' + error);
|
||||
} else {
|
||||
notify_info('Your message has been sent.');
|
||||
Notify.info('Your message has been sent.');
|
||||
dialog.hide();
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ function emailArticle(id) {
|
||||
});
|
||||
}
|
||||
},
|
||||
href: query});
|
||||
href: query
|
||||
});
|
||||
|
||||
/* var tmph = dojo.connect(dialog, 'onLoad', function() {
|
||||
dojo.disconnect(tmph);
|
||||
dojo.disconnect(tmph);
|
||||
|
||||
new Ajax.Autocompleter('emailArticleDlg_destination', 'emailArticleDlg_dst_choices',
|
||||
"backend.php?op=pluginhandler&plugin=mail&method=completeEmails",
|
||||
@@ -48,10 +49,8 @@ function emailArticle(id) {
|
||||
}); */
|
||||
|
||||
dialog.show();
|
||||
|
||||
} catch (e) {
|
||||
exception_error("emailArticle", e);
|
||||
},
|
||||
onHotkey: function(id) {
|
||||
Plugins.Mail.send(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user