summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig3
-rw-r--r--README.md3
-rw-r--r--backend.php2
-rwxr-xr-xclasses/api.php391
-rw-r--r--classes/config.php132
-rwxr-xr-xclasses/db.php10
-rwxr-xr-xclasses/feeds.php3
-rwxr-xr-xclasses/handler/public.php174
-rwxr-xr-xclasses/logger.php2
-rw-r--r--classes/mailer.php2
-rw-r--r--classes/opml.php6
-rwxr-xr-xclasses/pluginhost.php45
-rwxr-xr-xclasses/pref/feeds.php22
-rw-r--r--classes/pref/prefs.php56
-rw-r--r--classes/pref/system.php4
-rw-r--r--classes/pref/users.php2
-rw-r--r--classes/prefs.php2
-rwxr-xr-xclasses/rpc.php12
-rwxr-xr-xclasses/rssutils.php78
-rw-r--r--classes/urlhelper.php11
-rw-r--r--classes/userhelper.php2
-rw-r--r--gulpfile.js4
-rw-r--r--images/favicon-512px.pngbin0 -> 41316 bytes
-rw-r--r--images/logo_small.pngbin4134 -> 0 bytes
-rw-r--r--images/oval.svg17
-rw-r--r--images/three-dots.svg33
-rw-r--r--include/functions.php2
-rwxr-xr-xinclude/login_form.php4
-rw-r--r--index.php29
-rw-r--r--js/App.js64
-rw-r--r--js/Article.js22
-rw-r--r--js/CommonDialogs.js2
-rw-r--r--js/CommonFilters.js34
-rw-r--r--js/FeedStoreModel.js39
-rwxr-xr-xjs/FeedTree.js158
-rw-r--r--js/Feeds.js72
-rwxr-xr-xjs/Headlines.js99
-rw-r--r--js/PluginHost.js6
-rw-r--r--js/PrefHelpers.js75
-rwxr-xr-xjs/common.js2
-rw-r--r--phpstan.neon3
-rwxr-xr-xplugins/af_redditimgur/init.php138
-rw-r--r--plugins/af_zz_vidmute/init.js22
-rw-r--r--plugins/auth_internal/init.php30
-rw-r--r--plugins/nsfw/init.js18
-rw-r--r--plugins/nsfw/init.php25
-rw-r--r--plugins/share/init.php30
-rw-r--r--plugins/shorten_expanded/init.css3
-rw-r--r--plugins/shorten_expanded/init.js81
-rw-r--r--plugins/shorten_expanded/init.php16
-rw-r--r--prefs.php18
-rw-r--r--sql/mysql/migrations/145.sql2
-rw-r--r--sql/mysql/schema.sql3
-rw-r--r--sql/pgsql/migrations/145.sql2
-rw-r--r--sql/pgsql/schema.sql1
-rw-r--r--themes/compact.css839
-rw-r--r--themes/compact_night.css863
-rw-r--r--themes/light-high-contrast.css2093
-rw-r--r--themes/light-high-contrast.less8
-rw-r--r--themes/light.css839
-rw-r--r--themes/light/cdm.less357
-rw-r--r--themes/light/defines.less19
-rw-r--r--themes/light/dijit_basic.less71
-rw-r--r--themes/light/prefs.less35
-rw-r--r--themes/light/tt-rss.less753
-rw-r--r--themes/light/utility.less6
-rw-r--r--themes/light/zoom.less19
-rw-r--r--themes/night.css863
-rw-r--r--themes/night_base.less57
-rw-r--r--themes/night_blue.css863
-rwxr-xr-xupdate.php221
71 files changed, 6397 insertions, 3525 deletions
diff --git a/.editorconfig b/.editorconfig
index 119b50a10..2b1a9fb1f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,3 +4,6 @@ insert_final_newline = true
[*.php]
indent_style = tab
+
+[*.js]
+indent_style = tab
diff --git a/README.md b/README.md
index 84d576034..71b11cc8b 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,3 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2005 Andrew Dolgov (unless explicitly stated otherwise).
-
-Uses Silk icons by Mark James: http://www.famfamfam.com/lab/icons/silk/
-
diff --git a/backend.php b/backend.php
index 98c8eace6..b2ff46dca 100644
--- a/backend.php
+++ b/backend.php
@@ -2,7 +2,7 @@
set_include_path(__DIR__ ."/include" . PATH_SEPARATOR .
get_include_path());
- $op = $_REQUEST["op"];
+ $op = $_REQUEST['op'] ?? '';
$method = !empty($_REQUEST['subop']) ?
$_REQUEST['subop'] :
$_REQUEST["method"] ?? false;
diff --git a/classes/api.php b/classes/api.php
index a1ed7968c..72d43228f 100755
--- a/classes/api.php
+++ b/classes/api.php
@@ -132,49 +132,48 @@ class API extends Handler {
// TODO do not return empty categories, return Uncategorized and standard virtual cats
- if ($enable_nested)
- $nested_qpart = "parent_cat IS NULL";
- else
- $nested_qpart = "true";
-
- $sth = $this->pdo->prepare("SELECT
- id, title, order_id, (SELECT COUNT(id) FROM
- ttrss_feeds WHERE
- ttrss_feed_categories.id IS NOT NULL AND cat_id = ttrss_feed_categories.id) AS num_feeds,
- (SELECT COUNT(id) FROM
- ttrss_feed_categories AS c2 WHERE
- c2.parent_cat = ttrss_feed_categories.id) AS num_cats
- FROM ttrss_feed_categories
- WHERE $nested_qpart AND owner_uid = ?");
- $sth->execute([$_SESSION['uid']]);
+ $categories = ORM::for_table('ttrss_feed_categories')
+ ->select_many('id', 'title', 'order_id')
+ ->select_many_expr([
+ 'num_feeds' => '(SELECT COUNT(id) FROM ttrss_feeds WHERE ttrss_feed_categories.id IS NOT NULL AND cat_id = ttrss_feed_categories.id)',
+ 'num_cats' => '(SELECT COUNT(id) FROM ttrss_feed_categories AS c2 WHERE c2.parent_cat = ttrss_feed_categories.id)',
+ ])
+ ->where('owner_uid', $_SESSION['uid']);
+
+ if ($enable_nested) {
+ $categories->where_null('parent_cat');
+ }
- $cats = array();
+ $cats = [];
- while ($line = $sth->fetch()) {
- if ($include_empty || $line["num_feeds"] > 0 || $line["num_cats"] > 0) {
- $unread = getFeedUnread($line["id"], true);
+ foreach ($categories->find_many() as $category) {
+ if ($include_empty || $category->num_feeds > 0 || $category->num_cats > 0) {
+ $unread = getFeedUnread($category->id, true);
if ($enable_nested)
- $unread += Feeds::_get_cat_children_unread($line["id"]);
+ $unread += Feeds::_get_cat_children_unread($category->id);
if ($unread || !$unread_only) {
- array_push($cats, array("id" => (int) $line["id"],
- "title" => $line["title"],
- "unread" => (int) $unread,
- "order_id" => (int) $line["order_id"],
- ));
+ array_push($cats, [
+ 'id' => (int) $category->id,
+ 'title' => $category->title,
+ 'unread' => (int) $unread,
+ 'order_id' => (int) $category->order_id,
+ ]);
}
}
}
- foreach (array(-2,-1,0) as $cat_id) {
+ foreach ([-2,-1,0] as $cat_id) {
if ($include_empty || !$this->_is_cat_empty($cat_id)) {
$unread = getFeedUnread($cat_id, true);
if ($unread || !$unread_only) {
- array_push($cats, array("id" => $cat_id,
- "title" => Feeds::_get_cat_title($cat_id),
- "unread" => (int) $unread));
+ array_push($cats, [
+ 'id' => $cat_id,
+ 'title' => Feeds::_get_cat_title($cat_id),
+ 'unread' => (int) $unread,
+ ]);
}
}
}
@@ -300,60 +299,58 @@ class API extends Handler {
}
function getArticle() {
-
- $article_ids = explode(",", clean($_REQUEST["article_id"]));
- $sanitize_content = !isset($_REQUEST["sanitize"]) ||
- self::_param_to_bool($_REQUEST["sanitize"]);
-
- if (count($article_ids) > 0) {
-
- $article_qmarks = arr_qmarks($article_ids);
-
- $sth = $this->pdo->prepare("SELECT id,guid,title,link,content,feed_id,comments,int_id,
- marked,unread,published,score,note,lang,
- ".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
- author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title,
- (SELECT site_url FROM ttrss_feeds WHERE id = feed_id) AS site_url,
- (SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) AS hide_images
- FROM ttrss_entries,ttrss_user_entries
- WHERE id IN ($article_qmarks) AND ref_id = id AND owner_uid = ?");
-
- $sth->execute(array_merge($article_ids, [$_SESSION['uid']]));
-
- $articles = array();
-
- while ($line = $sth->fetch()) {
-
- $article = array(
- "id" => $line["id"],
- "guid" => $line["guid"],
- "title" => $line["title"],
- "link" => $line["link"],
- "labels" => Article::_get_labels($line['id']),
- "unread" => self::_param_to_bool($line["unread"]),
- "marked" => self::_param_to_bool($line["marked"]),
- "published" => self::_param_to_bool($line["published"]),
- "comments" => $line["comments"],
- "author" => $line["author"],
- "updated" => (int) strtotime($line["updated"]),
- "feed_id" => $line["feed_id"],
- "attachments" => Article::_get_enclosures($line['id']),
- "score" => (int)$line["score"],
- "feed_title" => $line["feed_title"],
- "note" => $line["note"],
- "lang" => $line["lang"]
- );
+ $article_ids = explode(',', clean($_REQUEST['article_id'] ?? ''));
+ $sanitize_content = self::_param_to_bool($_REQUEST['sanitize'] ?? true);
+
+ if (count($article_ids)) {
+ $entries = ORM::for_table('ttrss_entries')
+ ->table_alias('e')
+ ->select_many('e.id', 'e.guid', 'e.title', 'e.link', 'e.author', 'e.content', 'e.lang', 'e.comments',
+ 'ue.feed_id', 'ue.int_id', 'ue.marked', 'ue.unread', 'ue.published', 'ue.score', 'ue.note')
+ ->select_many_expr([
+ 'updated' => SUBSTRING_FOR_DATE.'(updated,1,16)',
+ 'feed_title' => '(SELECT title FROM ttrss_feeds WHERE id = ue.feed_id)',
+ 'site_url' => '(SELECT site_url FROM ttrss_feeds WHERE id = ue.feed_id)',
+ 'hide_images' => '(SELECT hide_images FROM ttrss_feeds WHERE id = feed_id)',
+ ])
+ ->join('ttrss_user_entries', [ 'ue.ref_id', '=', 'e.id'], 'ue')
+ ->where_in('e.id', array_map('intval', $article_ids))
+ ->where('ue.owner_uid', $_SESSION['uid'])
+ ->find_many();
+
+ $articles = [];
+
+ foreach ($entries as $entry) {
+ $article = [
+ 'id' => $entry->id,
+ 'guid' => $entry->guid,
+ 'title' => $entry->title,
+ 'link' => $entry->link,
+ 'labels' => Article::_get_labels($entry->id),
+ 'unread' => self::_param_to_bool($entry->unread),
+ 'marked' => self::_param_to_bool($entry->marked),
+ 'published' => self::_param_to_bool($entry->published),
+ 'comments' => $entry->comments,
+ 'author' => $entry->author,
+ 'updated' => (int) strtotime($entry->updated),
+ 'feed_id' => $entry->feed_id,
+ 'attachments' => Article::_get_enclosures($entry->id),
+ 'score' => (int) $entry->score,
+ 'feed_title' => $entry->feed_title,
+ 'note' => $entry->note,
+ 'lang' => $entry->lang,
+ ];
if ($sanitize_content) {
- $article["content"] = Sanitizer::sanitize(
- $line["content"],
- self::_param_to_bool($line['hide_images']),
- false, $line["site_url"], false, $line["id"]);
+ $article['content'] = Sanitizer::sanitize(
+ $entry->content,
+ self::_param_to_bool($entry->hide_images),
+ false, $entry->site_url, false, $entry->id);
} else {
- $article["content"] = $line["content"];
+ $article['content'] = $entry->content;
}
- $hook_object = ["article" => &$article];
+ $hook_object = ['article' => &$article];
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE_API,
function ($result) use (&$article) {
@@ -364,13 +361,12 @@ class API extends Handler {
$article['content'] = DiskCache::rewrite_urls($article['content']);
array_push($articles, $article);
-
}
$this->_wrap(self::STATUS_OK, $articles);
// @phpstan-ignore-next-line
} else {
- $this->_wrap(self::STATUS_ERR, array("error" => self::E_INCORRECT_USAGE));
+ $this->_wrap(self::STATUS_ERR, ['error' => self::E_INCORRECT_USAGE]);
}
}
@@ -382,12 +378,9 @@ class API extends Handler {
$config["daemon_is_running"] = file_is_locked("update_daemon.lock");
- $sth = $this->pdo->prepare("SELECT COUNT(*) AS cf FROM
- ttrss_feeds WHERE owner_uid = ?");
- $sth->execute([$_SESSION['uid']]);
- $row = $sth->fetch();
-
- $config["num_feeds"] = $row["cf"];
+ $config["num_feeds"] = ORM::for_table('ttrss_feeds')
+ ->where('owner_uid', $_SESSION['uid'])
+ ->count();
$this->_wrap(self::STATUS_OK, $config);
}
@@ -422,36 +415,36 @@ class API extends Handler {
}
function getLabels() {
- $article_id = (int)clean($_REQUEST['article_id']);
+ $article_id = (int)clean($_REQUEST['article_id'] ?? -1);
- $rv = array();
+ $rv = [];
- $sth = $this->pdo->prepare("SELECT id, caption, fg_color, bg_color
- FROM ttrss_labels2
- WHERE owner_uid = ? ORDER BY caption");
- $sth->execute([$_SESSION['uid']]);
+ $labels = ORM::for_table('ttrss_labels2')
+ ->where('owner_uid', $_SESSION['uid'])
+ ->order_by_asc('caption')
+ ->find_many();
if ($article_id)
$article_labels = Article::_get_labels($article_id);
else
- $article_labels = array();
-
- while ($line = $sth->fetch()) {
+ $article_labels = [];
+ foreach ($labels as $label) {
$checked = false;
foreach ($article_labels as $al) {
- if (Labels::feed_to_label_id($al[0]) == $line['id']) {
+ if (Labels::feed_to_label_id($al[0]) == $label->id) {
$checked = true;
break;
}
}
- array_push($rv, array(
- "id" => (int)Labels::label_to_feed_id($line['id']),
- "caption" => $line['caption'],
- "fg_color" => $line['fg_color'],
- "bg_color" => $line['bg_color'],
- "checked" => $checked));
+ array_push($rv, [
+ 'id' => (int) Labels::label_to_feed_id($label->id),
+ 'caption' => $label->caption,
+ 'fg_color' => $label->fg_color,
+ 'bg_color' => $label->bg_color,
+ 'checked' => $checked,
+ ]);
}
$this->_wrap(self::STATUS_OK, $rv);
@@ -512,10 +505,7 @@ class API extends Handler {
}
private static function _api_get_feeds($cat_id, $unread_only, $limit, $offset, $include_nested = false) {
-
- $feeds = array();
-
- $pdo = Db::pdo();
+ $feeds = [];
$limit = (int) $limit;
$offset = (int) $offset;
@@ -528,17 +518,15 @@ class API extends Handler {
$counters = Counters::get_labels();
foreach (array_values($counters) as $cv) {
-
- $unread = $cv["counter"];
+ $unread = $cv['counter'];
if ($unread || !$unread_only) {
-
- $row = array(
- "id" => (int) $cv["id"],
- "title" => $cv["description"],
- "unread" => $cv["counter"],
- "cat_id" => -2,
- );
+ $row = [
+ 'id' => (int) $cv['id'],
+ 'title' => $cv['description'],
+ 'unread' => $cv['counter'],
+ 'cat_id' => -2,
+ ];
array_push($feeds, $row);
}
@@ -548,45 +536,45 @@ class API extends Handler {
/* Virtual feeds */
if ($cat_id == -4 || $cat_id == -1) {
- foreach (array(-1, -2, -3, -4, -6, 0) as $i) {
+ foreach ([-1, -2, -3, -4, -6, 0] as $i) {
$unread = getFeedUnread($i);
if ($unread || !$unread_only) {
$title = Feeds::_get_title($i);
- $row = array(
- "id" => $i,
- "title" => $title,
- "unread" => $unread,
- "cat_id" => -1,
- );
+ $row = [
+ 'id' => $i,
+ 'title' => $title,
+ 'unread' => $unread,
+ 'cat_id' => -1,
+ ];
+
array_push($feeds, $row);
}
-
}
}
/* Child cats */
if ($include_nested && $cat_id) {
- $sth = $pdo->prepare("SELECT
- id, title, order_id FROM ttrss_feed_categories
- WHERE parent_cat = ? AND owner_uid = ? ORDER BY order_id, title");
-
- $sth->execute([$cat_id, $_SESSION['uid']]);
+ $categories = ORM::for_table('ttrss_feed_categories')
+ ->where(['parent_cat' => $cat_id, 'owner_uid' => $_SESSION['uid']])
+ ->order_by_asc('order_id')
+ ->order_by_asc('title')
+ ->find_many();
- while ($line = $sth->fetch()) {
- $unread = getFeedUnread($line["id"], true) +
- Feeds::_get_cat_children_unread($line["id"]);
+ foreach ($categories as $category) {
+ $unread = getFeedUnread($category->id, true) +
+ Feeds::_get_cat_children_unread($category->id);
if ($unread || !$unread_only) {
- $row = array(
- "id" => (int) $line["id"],
- "title" => $line["title"],
- "unread" => $unread,
- "is_cat" => true,
- "order_id" => (int) $line["order_id"]
- );
+ $row = [
+ 'id' => (int) $category->id,
+ 'title' => $category->title,
+ 'unread' => $unread,
+ 'is_cat' => true,
+ 'order_id' => (int) $category->order_id,
+ ];
array_push($feeds, $row);
}
}
@@ -594,51 +582,36 @@ class API extends Handler {
/* Real feeds */
- if ($limit) {
- $limit_qpart = "LIMIT $limit OFFSET $offset";
- } else {
- $limit_qpart = "";
- }
-
/* API only: -3 All feeds, excluding virtual feeds (e.g. Labels and such) */
- if ($cat_id == -4 || $cat_id == -3) {
- $sth = $pdo->prepare("SELECT
- id, feed_url, cat_id, title, order_id, ".
- SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
- FROM ttrss_feeds WHERE owner_uid = ?
- ORDER BY order_id, title " . $limit_qpart);
- $sth->execute([$_SESSION['uid']]);
-
- } else {
-
- $sth = $pdo->prepare("SELECT
- id, feed_url, cat_id, title, order_id, ".
- SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
- FROM ttrss_feeds WHERE
- (cat_id = :cat OR (:cat = 0 AND cat_id IS NULL))
- AND owner_uid = :uid
- ORDER BY order_id, title " . $limit_qpart);
- $sth->execute([":uid" => $_SESSION['uid'], ":cat" => $cat_id]);
+ $feeds_obj = ORM::for_table('ttrss_feeds')
+ ->select_many('id', 'feed_url', 'cat_id', 'title', 'order_id')
+ ->select_expr(SUBSTRING_FOR_DATE.'(last_updated,1,19)', 'last_updated')
+ ->where('owner_uid', $_SESSION['uid'])
+ ->order_by_asc('order_id')
+ ->order_by_asc('title');
+
+ if ($limit) $feeds_obj->limit($limit);
+ if ($offset) $feeds_obj->offset($offset);
+
+ if ($cat_id != -3 && $cat_id != -4) {
+ $feeds_obj->where_raw('(cat_id = ? OR (? = 0 AND cat_id IS NULL))', [$cat_id, $cat_id]);
}
- while ($line = $sth->fetch()) {
-
- $unread = getFeedUnread($line["id"]);
-
- $has_icon = Feeds::_has_icon($line['id']);
+ foreach ($feeds_obj->find_many() as $feed) {
+ $unread = getFeedUnread($feed->id);
+ $has_icon = Feeds::_has_icon($feed->id);
if ($unread || !$unread_only) {
-
- $row = array(
- "feed_url" => $line["feed_url"],
- "title" => $line["title"],
- "id" => (int)$line["id"],
- "unread" => (int)$unread,
- "has_icon" => $has_icon,
- "cat_id" => (int)$line["cat_id"],
- "last_updated" => (int) strtotime($line["last_updated"]),
- "order_id" => (int) $line["order_id"],
- );
+ $row = [
+ 'feed_url' => $feed->feed_url,
+ 'title' => $feed->title,
+ 'id' => (int) $feed->id,
+ 'unread' => (int) $unread,
+ 'has_icon' => $has_icon,
+ 'cat_id' => (int) $feed->cat_id,
+ 'last_updated' => (int) strtotime($feed->last_updated),
+ 'order_id' => (int) $feed->order_id,
+ ];
array_push($feeds, $row);
}
@@ -653,26 +626,24 @@ class API extends Handler {
$search = "", $include_nested = false, $sanitize_content = true,
$force_update = false, $excerpt_length = 100, $check_first_id = false, $skip_first_id_check = false) {
- $pdo = Db::pdo();
-
if ($force_update && $feed_id > 0 && is_numeric($feed_id)) {
// Update the feed if required with some basic flood control
- $sth = $pdo->prepare(
- "SELECT cache_images,".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
- FROM ttrss_feeds WHERE id = ?");
- $sth->execute([$feed_id]);
+ $feed = ORM::for_table('ttrss_feeds')
+ ->select_many('id', 'cache_images')
+ ->select_expr(SUBSTRING_FOR_DATE.'(last_updated,1,19)', 'last_updated')
+ ->find_one($feed_id);
- if ($row = $sth->fetch()) {
- $last_updated = strtotime($row["last_updated"]);
- $cache_images = self::_param_to_bool($row["cache_images"]);
+ if ($feed) {
+ $last_updated = strtotime($feed->last_updated);
+ $cache_images = self::_param_to_bool($feed->cache_images);
if (!$cache_images && time() - $last_updated > 120) {
RSSUtils::update_rss_feed($feed_id, true);
} else {
- $sth = $pdo->prepare("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
- WHERE id = ?");
- $sth->execute([$feed_id]);
+ $feed->last_updated = '1970-01-01';
+ $feed->last_update_started = '1970-01-01';
+ $feed->save();
}
}
}
@@ -792,7 +763,7 @@ class API extends Handler {
list ($flavor_image, $flavor_stream, $flavor_kind) = Article::_get_image($enclosures,
$line["content"], // unsanitized
- $line["site_url"],
+ $line["site_url"] ?? "", // could be null if archived article
$headline_row);
$headline_row["flavor_image"] = $flavor_image;
@@ -823,15 +794,15 @@ class API extends Handler {
function unsubscribeFeed() {
$feed_id = (int) clean($_REQUEST["feed_id"]);
- $sth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE
- id = ? AND owner_uid = ?");
- $sth->execute([$feed_id, $_SESSION['uid']]);
+ $feed_exists = ORM::for_table('ttrss_feeds')
+ ->where(['id' => $feed_id, 'owner_uid' => $_SESSION['uid']])
+ ->count();
- if ($row = $sth->fetch()) {
- Pref_Feeds::remove_feed($feed_id, $_SESSION["uid"]);
- $this->_wrap(self::STATUS_OK, array("status" => "OK"));
+ if ($feed_exists) {
+ Pref_Feeds::remove_feed($feed_id, $_SESSION['uid']);
+ $this->_wrap(self::STATUS_OK, ['status' => 'OK']);
} else {
- $this->_wrap(self::STATUS_ERR, array("error" => self::E_OPERATION_FAILED));
+ $this->_wrap(self::STATUS_ERR, ['error' => self::E_OPERATION_FAILED]);
}
}
@@ -864,27 +835,21 @@ class API extends Handler {
// only works for labels or uncategorized for the time being
private function _is_cat_empty($id) {
-
if ($id == -2) {
- $sth = $this->pdo->prepare("SELECT COUNT(id) AS count FROM ttrss_labels2
- WHERE owner_uid = ?");
- $sth->execute([$_SESSION['uid']]);
- $row = $sth->fetch();
-
- return $row["count"] == 0;
+ $label_count = ORM::for_table('ttrss_labels2')
+ ->where('owner_uid', $_SESSION['uid'])
+ ->count();
+ return $label_count == 0;
} else if ($id == 0) {
- $sth = $this->pdo->prepare("SELECT COUNT(id) AS count FROM ttrss_feeds
- WHERE cat_id IS NULL AND owner_uid = ?");
- $sth->execute([$_SESSION['uid']]);
- $row = $sth->fetch();
-
- return $row["count"] == 0;
+ $uncategorized_count = ORM::for_table('ttrss_feeds')
+ ->where_null('cat_id')
+ ->where('owner_uid', $_SESSION['uid'])
+ ->count();
+ return $uncategorized_count == 0;
}
return false;
}
-
-
}
diff --git a/classes/config.php b/classes/config.php
index 567a019c6..6e8d4533f 100644
--- a/classes/config.php
+++ b/classes/config.php
@@ -6,9 +6,22 @@ class Config {
const T_STRING = 2;
const T_INT = 3;
- const SCHEMA_VERSION = 144;
+ const SCHEMA_VERSION = 145;
- // override defaults, defined below in _DEFAULTS[], via environment: DB_TYPE becomes TTRSS_DB_TYPE, etc
+ /* override defaults, defined below in _DEFAULTS[], prefixing with _ENVVAR_PREFIX:
+
+ DB_TYPE becomes:
+
+ .env:
+
+ TTRSS_DB_TYPE=pgsql
+
+ or config.php:
+
+ putenv('TTRSS_DB_TYPE=pgsql');
+
+ etc, etc.
+ */
const DB_TYPE = "DB_TYPE";
const DB_HOST = "DB_HOST";
@@ -16,48 +29,148 @@ class Config {
const DB_NAME = "DB_NAME";
const DB_PASS = "DB_PASS";
const DB_PORT = "DB_PORT";
+ // database credentials
+
const MYSQL_CHARSET = "MYSQL_CHARSET";
+ // connection charset for MySQL. if you have a legacy database and/or experience
+ // garbage unicode characters with this option, try setting it to a blank string.
+
const SELF_URL_PATH = "SELF_URL_PATH";
+ // this should be set to a fully qualified URL used to access
+ // your tt-rss instance over the net, such as: https://example.com/tt-rss/
+ // if your tt-rss instance is behind a reverse proxy, use external URL.
+ // tt-rss will likely help you pick correct value for this on startup
+
const SINGLE_USER_MODE = "SINGLE_USER_MODE";
+ // operate in single user mode, disables all functionality related to
+ // multiple users and authentication. enabling this assumes you have
+ // your tt-rss directory protected by other means (e.g. http auth).
+
const SIMPLE_UPDATE_MODE = "SIMPLE_UPDATE_MODE";
+ // enables fallback update mode where tt-rss tries to update feeds in
+ // background while tt-rss is open in your browser.
+ // if you don't have a lot of feeds and don't want to or can't run
+ // background processes while not running tt-rss, this method is generally
+ // viable to keep your feeds up to date.
+
const PHP_EXECUTABLE = "PHP_EXECUTABLE";
+ // use this PHP CLI executable to start various tasks
+
const LOCK_DIRECTORY = "LOCK_DIRECTORY";
+ // base directory for lockfiles (must be writable)
+
const CACHE_DIR = "CACHE_DIR";
+ // base directory for local cache (must be writable)
+
const ICONS_DIR = "ICONS_DIR";
const ICONS_URL = "ICONS_URL";
+ // directory and URL for feed favicons (directory must be writable)
+
const AUTH_AUTO_CREATE = "AUTH_AUTO_CREATE";
+ // auto create users authenticated via external modules
+
const AUTH_AUTO_LOGIN = "AUTH_AUTO_LOGIN";
+ // auto log in users authenticated via external modules i.e. auth_remote
+
const FORCE_ARTICLE_PURGE = "FORCE_ARTICLE_PURGE";
+ // unconditinally purge all articles older than this amount, in days
+ // overrides user-controlled purge interval
+
const SESSION_COOKIE_LIFETIME = "SESSION_COOKIE_LIFETIME";
+ // default lifetime of a session (e.g. login) cookie. In seconds,
+ // 0 means cookie will be deleted when browser closes.
+
const SMTP_FROM_NAME = "SMTP_FROM_NAME";
const SMTP_FROM_ADDRESS = "SMTP_FROM_ADDRESS";
+ // send email using this name and address
+
const DIGEST_SUBJECT = "DIGEST_SUBJECT";
+ // default subject for email digest
+
const CHECK_FOR_UPDATES = "CHECK_FOR_UPDATES";
+ // enable built-in update checker, both for core code and plugins (using git)
+
const PLUGINS = "PLUGINS";
+ // system plugins enabled for all users, comma separated list, no quotes
+ // keep at least one auth module in there (i.e. auth_internal)
+
const LOG_DESTINATION = "LOG_DESTINATION";
+ // available options: sql (default, event log), syslog, stdout (for debugging)
+
const LOCAL_OVERRIDE_STYLESHEET = "LOCAL_OVERRIDE_STYLESHEET";
+ // link this stylesheet on all pages (if it exists), should be placed in themes.local
+
+ const LOCAL_OVERRIDE_JS = "LOCAL_OVERRIDE_JS";
+ // same but this javascript file (you can use that for polyfills), should be placed in themes.local
+
const DAEMON_MAX_CHILD_RUNTIME = "DAEMON_MAX_CHILD_RUNTIME";
+ // in seconds, terminate update tasks that ran longer than this interval
+
const DAEMON_MAX_JOBS = "DAEMON_MAX_JOBS";
+ // max concurrent update jobs forking update daemon starts
+
const FEED_FETCH_TIMEOUT = "FEED_FETCH_TIMEOUT";
+ // How long to wait for response when requesting feed from a site (seconds)
+
const FEED_FETCH_NO_CACHE_TIMEOUT = "FEED_FETCH_NO_CACHE_TIMEOUT";
+ // Same but not cached
+
const FILE_FETCH_TIMEOUT = "FILE_FETCH_TIMEOUT";
+ // Default timeout when fetching files from remote sites
+
const FILE_FETCH_CONNECT_TIMEOUT = "FILE_FETCH_CONNECT_TIMEOUT";
+ // How long to wait for initial response from website when fetching files from remote sites
+
const DAEMON_UPDATE_LOGIN_LIMIT = "DAEMON_UPDATE_LOGIN_LIMIT";
+ // stop updating feeds if user haven't logged in for X days
+
const DAEMON_FEED_LIMIT = "DAEMON_FEED_LIMIT";
+ // how many feeds to update in one batch
+
const DAEMON_SLEEP_INTERVAL = "DAEMON_SLEEP_INTERVAL";
+ // default sleep interval between feed updates (sec)
+
const MAX_CACHE_FILE_SIZE = "MAX_CACHE_FILE_SIZE";
+ // do not cache files larger than that (bytes)
+
const MAX_DOWNLOAD_FILE_SIZE = "MAX_DOWNLOAD_FILE_SIZE";
+ // do not download files larger than that (bytes)
+
const MAX_FAVICON_FILE_SIZE = "MAX_FAVICON_FILE_SIZE";
+ // max file size for downloaded favicons (bytes)
+
const CACHE_MAX_DAYS = "CACHE_MAX_DAYS";
+ // max age in days for various automatically cached (temporary) files
+
const MAX_CONDITIONAL_INTERVAL = "MAX_CONDITIONAL_INTERVAL";
+ // max interval between forced unconditional updates for servers not complying with http if-modified-since (seconds)
+
const DAEMON_UNSUCCESSFUL_DAYS_LIMIT = "DAEMON_UNSUCCESSFUL_DAYS_LIMIT";
+ // automatically disable updates for feeds which failed to
+ // update for this amount of days; 0 disables
+
const LOG_SENT_MAIL = "LOG_SENT_MAIL";
+ // log all sent emails in the event log
+
const HTTP_PROXY = "HTTP_PROXY";
+ // use HTTP proxy for requests
+
const FORBID_PASSWORD_CHANGES = "FORBID_PASSWORD_CHANGES";
+ // prevent users from changing passwords
+
const SESSION_NAME = "SESSION_NAME";
+ // default session cookie name
+
const CHECK_FOR_PLUGIN_UPDATES = "CHECK_FOR_PLUGIN_UPDATES";
+ // enable plugin update checker (using git)
+
const ENABLE_PLUGIN_INSTALLER = "ENABLE_PLUGIN_INSTALLER";
+ // allow installing first party plugins using plugin installer in prefs
+
+ const AUTH_MIN_INTERVAL = "AUTH_MIN_INTERVAL";
+ // minimum amount of seconds required between authentication attempts
+ // default values for all of the above:
private const _DEFAULTS = [
Config::DB_TYPE => [ "pgsql", Config::T_STRING ],
Config::DB_HOST => [ "db", Config::T_STRING ],
@@ -87,6 +200,8 @@ class Config {
Config::LOG_DESTINATION => [ Logger::LOG_DEST_SQL, Config::T_STRING ],
Config::LOCAL_OVERRIDE_STYLESHEET => [ "local-overrides.css",
Config::T_STRING ],
+ Config::LOCAL_OVERRIDE_JS => [ "local-overrides.js",
+ Config::T_STRING ],
Config::DAEMON_MAX_CHILD_RUNTIME => [ 1800, Config::T_INT ],
Config::DAEMON_MAX_JOBS => [ 2, Config::T_INT ],
Config::FEED_FETCH_TIMEOUT => [ 45, Config::T_INT ],
@@ -108,6 +223,7 @@ class Config {
Config::SESSION_NAME => [ "ttrss_sid", Config::T_STRING ],
Config::CHECK_FOR_PLUGIN_UPDATES => [ "true", Config::T_BOOL ],
Config::ENABLE_PLUGIN_INSTALLER => [ "true", Config::T_BOOL ],
+ Config::AUTH_MIN_INTERVAL => [ 5, Config::T_INT ],
];
private static $instance;
@@ -503,4 +619,16 @@ class Config {
private static function format_error($msg) {
return "<div class=\"alert alert-danger\">$msg</div>";
}
+
+ static function get_override_links() {
+ $rv = "";
+
+ $local_css = get_theme_path(self::get(self::LOCAL_OVERRIDE_STYLESHEET));
+ if ($local_css) $rv .= stylesheet_tag($local_css);
+
+ $local_js = get_theme_path(self::get(self::LOCAL_OVERRIDE_JS));
+ if ($local_js) $rv .= javascript_tag($local_js);
+
+ return $rv;
+ }
}
diff --git a/classes/db.php b/classes/db.php
index 008275bca..a09c44628 100755
--- a/classes/db.php
+++ b/classes/db.php
@@ -14,6 +14,9 @@ class Db
ORM::configure('username', Config::get(Config::DB_USER));
ORM::configure('password', Config::get(Config::DB_PASS));
ORM::configure('return_result_sets', true);
+ if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET)) {
+ ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . Config::get(Config::MYSQL_CHARSET)));
+ }
}
static function NOW() {
@@ -27,8 +30,13 @@ class Db
public static function get_dsn() {
$db_port = Config::get(Config::DB_PORT) ? ';port=' . Config::get(Config::DB_PORT) : '';
$db_host = Config::get(Config::DB_HOST) ? ';host=' . Config::get(Config::DB_HOST) : '';
+ if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET)) {
+ $db_charset = ';charset=' . Config::get(Config::MYSQL_CHARSET);
+ } else {
+ $db_charset = '';
+ }
- return Config::get(Config::DB_TYPE) . ':dbname=' . Config::get(Config::DB_NAME) . $db_host . $db_port;
+ return Config::get(Config::DB_TYPE) . ':dbname=' . Config::get(Config::DB_NAME) . $db_host . $db_port . $db_charset;
}
// this really shouldn't be used unless a separate PDO connection is needed
diff --git a/classes/feeds.php b/classes/feeds.php
index 68d535481..12d6dd65f 100755
--- a/classes/feeds.php
+++ b/classes/feeds.php
@@ -2054,8 +2054,7 @@ class Feeds extends Handler_Protected {
}
private static function _search_to_sql($search, $search_language, $owner_uid) {
-
- $keywords = str_getcsv(trim($search), " ");
+ $keywords = str_getcsv(preg_replace('/(-?\w+)\:"(\w+)/', '"${1}:${2}', trim($search)), ' ');
$query_keywords = array();
$search_words = array();
$search_query_leftover = array();
diff --git a/classes/handler/public.php b/classes/handler/public.php
index 2de073cc2..98042111b 100755
--- a/classes/handler/public.php
+++ b/classes/handler/public.php
@@ -266,19 +266,20 @@ class Handler_Public extends Handler {
$rv = [];
if ($login) {
- $sth = $this->pdo->prepare("SELECT ttrss_settings_profiles.* FROM ttrss_settings_profiles,ttrss_users
- WHERE ttrss_users.id = ttrss_settings_profiles.owner_uid AND LOWER(login) = LOWER(?) ORDER BY title");
- $sth->execute([$login]);
+ $profiles = ORM::for_table('ttrss_settings_profiles')
+ ->table_alias('p')
+ ->select_many('title' , 'p.id')
+ ->join('ttrss_users', ['owner_uid', '=', 'u.id'], 'u')
+ ->where_raw('LOWER(login) = LOWER(?)', [$login])
+ ->order_by_asc('title')
+ ->find_many();
$rv = [ [ "value" => 0, "label" => __("Default profile") ] ];
- while ($line = $sth->fetch()) {
- $id = $line["id"];
- $title = $line["title"];
-
- array_push($rv, [ "label" => $title, "value" => $id ]);
+ foreach ($profiles as $profile) {
+ array_push($rv, [ "label" => $profile->title, "value" => $profile->id ]);
}
- }
+ }
print json_encode($rv);
}
@@ -312,23 +313,20 @@ class Handler_Public extends Handler {
UserHelper::authenticate("admin", null);
}
- $owner_id = false;
-
if ($key) {
- $sth = $this->pdo->prepare("SELECT owner_uid FROM
- ttrss_access_keys WHERE access_key = ? AND feed_id = ?");
- $sth->execute([$key, $feed]);
-
- if ($row = $sth->fetch())
- $owner_id = $row["owner_uid"];
+ $access_key = ORM::for_table('ttrss_access_keys')
+ ->select('owner_uid')
+ ->where(['access_key' => $key, 'feed_id' => $feed])
+ ->find_one();
+
+ if ($access_key) {
+ $this->generate_syndicated_feed($access_key->owner_uid, $feed, $is_cat, $limit,
+ $offset, $search, $view_mode, $format, $order, $orig_guid, $start_ts);
+ return;
+ }
}
- if ($owner_id) {
- $this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
- $offset, $search, $view_mode, $format, $order, $orig_guid, $start_ts);
- } else {
- header('HTTP/1.1 403 Forbidden');
- }
+ header('HTTP/1.1 403 Forbidden');
}
function updateTask() {
@@ -373,18 +371,13 @@ class Handler_Public extends Handler {
$_SESSION["safe_mode"] = $safe_mode;
if (!empty($_POST["profile"])) {
-
$profile = (int) clean($_POST["profile"]);
- $sth = $this->pdo->prepare("SELECT id FROM ttrss_settings_profiles
- WHERE id = ? AND owner_uid = ?");
- $sth->execute([$profile, $_SESSION['uid']]);
+ $profile_obj = ORM::for_table('ttrss_settings_profiles')
+ ->where(['id' => $profile, 'owner_uid' => $_SESSION['uid']])
+ ->find_one();
- if ($sth->fetch()) {
- $_SESSION["profile"] = $profile;
- } else {
- $_SESSION["profile"] = null;
- }
+ $_SESSION["profile"] = $profile_obj ? $profile : null;
}
} else {
@@ -415,7 +408,7 @@ class Handler_Public extends Handler {
startup_gettext();
session_start();
- @$hash = clean($_REQUEST["hash"]);
+ $hash = clean($_REQUEST["hash"] ?? '');
header('Content-Type: text/html; charset=utf-8');
?>
@@ -448,30 +441,27 @@ class Handler_Public extends Handler {
print "<h1>".__("Password recovery")."</h1>";
print "<div class='content'>";
- @$method = clean($_POST['method']);
+ $method = clean($_POST['method'] ?? '');
if ($hash) {
$login = clean($_REQUEST["login"]);
if ($login) {
- $sth = $this->pdo->prepare("SELECT id, resetpass_token FROM ttrss_users
- WHERE LOWER(login) = LOWER(?)");
- $sth->execute([$login]);
+ $user = ORM::for_table('ttrss_users')
+ ->select('id', 'resetpass_token')
+ ->where_raw('LOWER(login) = LOWER(?)', [$login])
+ ->find_one();
- if ($row = $sth->fetch()) {
- $id = $row["id"];
- $resetpass_token_full = $row["resetpass_token"];
- list($timestamp, $resetpass_token) = explode(":", $resetpass_token_full);
+ if ($user) {
+ list($timestamp, $resetpass_token) = explode(":", $user->resetpass_token);
if ($timestamp && $resetpass_token &&
$timestamp >= time() - 15*60*60 &&
$resetpass_token === $hash) {
+ $user->resetpass_token = null;
+ $user->save();
- $sth = $this->pdo->prepare("UPDATE ttrss_users SET resetpass_token = NULL
- WHERE id = ?");
- $sth->execute([$id]);
-
- UserHelper::reset_password($id, true);
+ UserHelper::reset_password($user->id, true);
print "<p>"."Completed."."</p>";
@@ -520,7 +510,6 @@ class Handler_Public extends Handler {
</form>";
} else if ($method == 'do') {
-
$login = clean($_POST["login"]);
$email = clean($_POST["email"]);
$test = clean($_POST["test"]);
@@ -532,64 +521,51 @@ class Handler_Public extends Handler {
<input type='hidden' name='op' value='forgotpass'>
<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>".__("Go back")."</button>
</form>";
-
} else {
-
// prevent submitting this form multiple times
$_SESSION["pwdreset:testvalue1"] = rand(1, 1000);
$_SESSION["pwdreset:testvalue2"] = rand(1, 1000);
- $sth = $this->pdo->prepare("SELECT id FROM ttrss_users
- WHERE LOWER(login) = LOWER(?) AND email = ?");
- $sth->execute([$login, $email]);
+ $user = ORM::for_table('ttrss_users')
+ ->select('id')
+ ->where_raw('LOWER(login) = LOWER(?)', [$login])
+ ->where('email', $email)
+ ->find_one();
- if ($row = $sth->fetch()) {
+ if ($user) {
print_notice("Password reset instructions are being sent to your email address.");
- $id = $row["id"];
-
- if ($id) {
- $resetpass_token = sha1(get_random_bytes(128));
- $resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token .
- "&login=" . urlencode($login);
+ $resetpass_token = sha1(get_random_bytes(128));
+ $resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token .
+ "&login=" . urlencode($login);
- $tpl = new Templator();
+ $tpl = new Templator();
- $tpl->readTemplateFromFile("resetpass_link_template.txt");
+ $tpl->readTemplateFromFile("resetpass_link_template.txt");
- $tpl->setVariable('LOGIN', $login);
- $tpl->setVariable('RESETPASS_LINK', $resetpass_link);
- $tpl->setVariable('TTRSS_HOST', Config::get(Config::SELF_URL_PATH));
+ $tpl->setVariable('LOGIN', $login);
+ $tpl->setVariable('RESETPASS_LINK', $resetpass_link);
+ $tpl->setVariable('TTRSS_HOST', Config::get(Config::SELF_URL_PATH));
- $tpl->addBlock('message');
+ $tpl->addBlock('message');
- $message = "";
+ $message = "";
- $tpl->generateOutputToString($message);
+ $tpl->generateOutputToString($message);
- $mailer = new Mailer();
+ $mailer = new Mailer();
- $rc = $mailer->mail(["to_name" => $login,
- "to_address" => $email,
- "subject" => __("[tt-rss] Password reset request"),
- "message" => $message]);
+ $rc = $mailer->mail(["to_name" => $login,
+ "to_address" => $email,
+ "subject" => __("[tt-rss] Password reset request"),
+ "message" => $message]);
- if (!$rc) print_error($mailer->error());
+ if (!$rc) print_error($mailer->error());
- $resetpass_token_full = time() . ":" . $resetpass_token;
-
- $sth = $this->pdo->prepare("UPDATE ttrss_users
- SET resetpass_token = ?
- WHERE LOWER(login) = LOWER(?) AND email = ?");
-
- $sth->execute([$resetpass_token_full, $login, $email]);
-
- } else {
- print_error("User ID not found.");
- }
+ $user->resetpass_token = time() . ":" . $resetpass_token;
+ $user->save();
print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>";
-
} else {
print_error(__("Sorry, login and email combination not found."));
@@ -597,17 +573,14 @@ class Handler_Public extends Handler {
<input type='hidden' name='op' value='forgotpass'>
<button dojoType='dijit.form.Button' type='submit'>".__("Go back")."</button>
</form>";
-
}
}
-
}
print "</div>";
print "</div>";
print "</body>";
print "</html>";
-
}
function dbupdate() {
@@ -638,9 +611,7 @@ class Handler_Public extends Handler {
} ?>
- <?php if (theme_exists(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))) {
- echo stylesheet_tag(get_theme_path(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET)));
- } ?>
+ <?= Config::get_override_links() ?>
<style type="text/css">
@media (prefers-color-scheme: dark) {
@@ -755,27 +726,6 @@ class Handler_Public extends Handler {
<?php
}
- function publishOpml() {
- $key = clean($_REQUEST["key"]);
- $pdo = Db::pdo();
-
- $sth = $pdo->prepare( "SELECT owner_uid
- FROM ttrss_access_keys WHERE
- access_key = ? AND feed_id = 'OPML:Publish'");
- $sth->execute([$key]);
-
- if ($row = $sth->fetch()) {
- $owner_uid = $row['owner_uid'];
-
- $opml = new OPML($_REQUEST);
- $opml->opml_export("published.opml", $owner_uid, true, false);
-
- } else {
- header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
- echo "File not found.";
- }
- }
-
function cached() {
list ($cache_dir, $filename) = explode("/", $_GET["file"], 2);
diff --git a/classes/logger.php b/classes/logger.php
index f8abb5f84..42ab4452c 100755
--- a/classes/logger.php
+++ b/classes/logger.php
@@ -46,7 +46,7 @@ class Logger {
if ($this->adapter)
return $this->adapter->log_error($errno, $errstr, '', 0, $context);
else
- return false;
+ return user_error($errstr, $errno);
}
private function __clone() {
diff --git a/classes/mailer.php b/classes/mailer.php
index 564338f69..8238904ee 100644
--- a/classes/mailer.php
+++ b/classes/mailer.php
@@ -4,7 +4,7 @@ class Mailer {
function mail($params) {
- $to_name = $params["to_name"];
+ $to_name = $params["to_name"] ?? "";
$to_address = $params["to_address"];
$subject = $params["subject"];
$message = $params["message"];
diff --git a/classes/opml.php b/classes/opml.php
index f8e9f6728..2cfc890fa 100644
--- a/classes/opml.php
+++ b/classes/opml.php
@@ -633,12 +633,6 @@ class OPML extends Handler_Protected {
print "$msg<br/>";
}
- static function get_publish_url(){
- return Config::get_self_url() .
- "/public.php?op=publishOpml&key=" .
- Feeds::_get_access_key('OPML:Publish', false, $_SESSION["uid"]);
- }
-
function get_feed_category($feed_cat, $parent_cat_id = false) {
$parent_cat_id = (int) $parent_cat_id;
diff --git a/classes/pluginhost.php b/classes/pluginhost.php
index 17d1e0c5f..ee4107ae7 100755
--- a/classes/pluginhost.php
+++ b/classes/pluginhost.php
@@ -352,7 +352,7 @@ class PluginHost {
$method = strtolower($method);
if ($this->is_system($sender)) {
- if (!is_array($this->handlers[$handler])) {
+ if (!isset($this->handlers[$handler])) {
$this->handlers[$handler] = array();
}
@@ -469,6 +469,29 @@ class PluginHost {
}
}
+ // same as set(), but sets data to current preference profile
+ function profile_set(Plugin $sender, string $name, $value) {
+ $profile_id = $_SESSION["profile"] ?? null;
+
+ if ($profile_id) {
+ $idx = get_class($sender);
+
+ if (!isset($this->storage[$idx])) {
+ $this->storage[$idx] = [];
+ }
+
+ if (!isset($this->storage[$idx][$profile_id])) {
+ $this->storage[$idx][$profile_id] = [];
+ }
+
+ $this->storage[$idx][$profile_id][$name] = $value;
+
+ $this->save_data(get_class($sender));
+ } else {
+ return $this->set($sender, $name, $value);
+ }
+ }
+
function set(Plugin $sender, string $name, $value) {
$idx = get_class($sender);
@@ -492,6 +515,26 @@ class PluginHost {
$this->save_data(get_class($sender));
}
+ // same as get(), but sets data to current preference profile
+ function profile_get(Plugin $sender, string $name, $default_value = false) {
+ $profile_id = $_SESSION["profile"] ?? null;
+
+ if ($profile_id) {
+ $idx = get_class($sender);
+
+ $this->load_data();
+
+ if (isset($this->storage[$idx][$profile_id][$name])) {
+ return $this->storage[$idx][$profile_id][$name];
+ } else {
+ return $default_value;
+ }
+
+ } else {
+ return $this->get($sender, $name, $default_value);
+ }
+ }
+
function get(Plugin $sender, string $name, $default_value = false) {
$idx = get_class($sender);
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php
index 788104d38..5f7635736 100755
--- a/classes/pref/feeds.php
+++ b/classes/pref/feeds.php
@@ -1012,17 +1012,6 @@ class Pref_Feeds extends Handler_Protected {
</label>
</form>
- <hr/>
-
- <h2><?= __("Published OPML") ?></h2>
-
- <?= format_notice("Your OPML can be published and then subscribed by anyone who knows the URL below. This won't include your settings nor authenticated feeds.") ?>
-
- <button dojoType='dijit.form.Button' class='alt-primary' onclick="return Helpers.OPML.publish()">
- <?= \Controls\icon("share") ?>
- <?= __('Display published OPML URL') ?>
- </button>
-
<?php
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "prefFeedsOPML");
}
@@ -1251,17 +1240,6 @@ class Pref_Feeds extends Handler_Protected {
return Feeds::_clear_access_keys($_SESSION['uid']);
}
- function getOPMLKey() {
- print json_encode(["link" => OPML::get_publish_url()]);
- }
-
- function regenOPMLKey() {
- Feeds::_update_access_key('OPML:Publish',
- false, $_SESSION["uid"]);
-
- print json_encode(["link" => OPML::get_publish_url()]);
- }
-
function regenFeedKey() {
$feed_id = clean($_REQUEST['id']);
$is_cat = clean($_REQUEST['is_cat']);
diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php
index 16c41df9d..1eaa99345 100644
--- a/classes/pref/prefs.php
+++ b/classes/pref/prefs.php
@@ -54,6 +54,7 @@ class Pref_Prefs extends Handler_Protected {
'BLOCK_SEPARATOR',
Prefs::COMBINED_DISPLAY_MODE,
Prefs::CDM_EXPANDED,
+ Prefs::CDM_ENABLE_GRID,
'BLOCK_SEPARATOR',
Prefs::CDM_AUTO_CATCHUP,
Prefs::VFEED_GROUP_BY_FEED,
@@ -117,6 +118,7 @@ class Pref_Prefs extends Handler_Protected {
Prefs::HEADLINES_NO_DISTINCT => array(__("Don't enforce DISTINCT headlines"), __("May produce duplicate entries")),
Prefs::DEBUG_HEADLINE_IDS => array(__("Show article and feed IDs"), __("In the headlines buffer")),
Prefs::DISABLE_CONDITIONAL_COUNTERS => array(__("Disable conditional counter updates"), __("May increase server load")),
+ Prefs::CDM_ENABLE_GRID => array(__("Grid view"), __("On wider screens, if always expanded")),
];
// hidden in the main prefs UI (use to hide things that have description set above)
@@ -229,29 +231,29 @@ class Pref_Prefs extends Handler_Protected {
if ($user) {
$user->full_name = clean($_POST['full_name']);
- if ($user->email != $new_email)
+ if ($user->email != $new_email) {
Logger::log(E_USER_NOTICE, "Email address of user ".$user->login." has been changed to ${new_email}.");
- if ($user->email && $user->email != $new_email) {
+ if ($user->email) {
+ $mailer = new Mailer();
- $mailer = new Mailer();
+ $tpl = new Templator();
- $tpl = new Templator();
+ $tpl->readTemplateFromFile("mail_change_template.txt");
- $tpl->readTemplateFromFile("mail_change_template.txt");
+ $tpl->setVariable('LOGIN', $user->login);
+ $tpl->setVariable('NEWMAIL', $new_email);
+ $tpl->setVariable('TTRSS_HOST', Config::get(Config::SELF_URL_PATH));
- $tpl->setVariable('LOGIN', $user->login);
- $tpl->setVariable('NEWMAIL', $new_email);
- $tpl->setVariable('TTRSS_HOST', Config::get(Config::SELF_URL_PATH));
-
- $tpl->addBlock('message');
+ $tpl->addBlock('message');
- $tpl->generateOutputToString($message);
+ $tpl->generateOutputToString($message);
- $mailer->mail(["to_name" => $user->login,
- "to_address" => $user->email,
- "subject" => "[tt-rss] Email address change notification",
- "message" => $message]);
+ $mailer->mail(["to_name" => $user->login,
+ "to_address" => $user->email,
+ "subject" => "[tt-rss] Email address change notification",
+ "message" => $message]);
+ }
$user->email = $new_email;
}
@@ -467,8 +469,8 @@ class Pref_Prefs extends Handler_Protected {
<?= \Controls\hidden_tag("method", "otpenable") ?>
<fieldset>
- <label><?= __("OTP Key:") ?></label>
- <input dojoType='dijit.form.ValidationTextBox' disabled='disabled' value="<?= $otp_secret ?>" style='width : 215px'>
+ <label><?= __("OTP secret:") ?></label>
+ <code><?= $this->format_otp_secret($otp_secret) ?></code>
</fieldset>
<!-- TODO: return JSON from the backend call -->
@@ -494,7 +496,7 @@ class Pref_Prefs extends Handler_Protected {
</fieldset>
<fieldset>
- <label><?= __("One time password:") ?></label>
+ <label><?= __("Verification code:") ?></label>
<input dojoType='dijit.form.ValidationTextBox' autocomplete='off' required='1' name='otp'>
</fieldset>
@@ -1434,10 +1436,10 @@ class Pref_Prefs extends Handler_Protected {
<div class='panel panel-scrollable'>
<table width='100%' id='app-password-list'>
<tr>
- <th width='2%'> </th>
- <th align='left'><?= __("Description") ?></th>
- <th align='right'><?= __("Created") ?></th>
- <th align='right'><?= __("Last used") ?></th>
+ <th class="checkbox"> </th>
+ <th width='50%'><?= __("Description") ?></th>
+ <th><?= __("Created") ?></th>
+ <th><?= __("Last used") ?></th>
</tr>
<?php
@@ -1448,16 +1450,16 @@ class Pref_Prefs extends Handler_Protected {
foreach ($passwords as $pass) { ?>
<tr data-row-id='<?= $pass['id'] ?>'>
- <td align='center'>
+ <td class="checkbox">
<input onclick='Tables.onRowChecked(this)' dojoType='dijit.form.CheckBox' type='checkbox'>
</td>
<td>
<?= htmlspecialchars($pass["title"]) ?>
</td>
- <td align='right' class='text-muted'>
+ <td class='text-muted'>
<?= TimeHelper::make_local_datetime($pass['created'], false) ?>
</td>
- <td align='right' class='text-muted'>
+ <td class='text-muted'>
<?= TimeHelper::make_local_datetime($pass['last_used'], false) ?>
</td>
</tr>
@@ -1516,4 +1518,8 @@ class Pref_Prefs extends Handler_Protected {
}
return "";
}
+
+ private function format_otp_secret($secret) {
+ return implode(" ", str_split($secret, 4));
+ }
}
diff --git a/classes/pref/system.php b/classes/pref/system.php
index c79b5095d..8bebcc7ce 100644
--- a/classes/pref/system.php
+++ b/classes/pref/system.php
@@ -42,10 +42,10 @@ class Pref_System extends Handler_Administrative {
switch ($severity) {
case E_USER_ERROR:
- $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE ];
+ $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE, E_COMPILE_ERROR ];
break;
case E_USER_WARNING:
- $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE, E_WARNING, E_USER_WARNING, E_DEPRECATED, E_USER_DEPRECATED ];
+ $errno_values = [ E_ERROR, E_USER_ERROR, E_PARSE, E_COMPILE_ERROR, E_WARNING, E_USER_WARNING, E_DEPRECATED, E_USER_DEPRECATED ];
break;
}
diff --git a/classes/pref/users.php b/classes/pref/users.php
index 2e3dc4b67..76a879efd 100644
--- a/classes/pref/users.php
+++ b/classes/pref/users.php
@@ -117,7 +117,7 @@ class Pref_Users extends Handler_Administrative {
$user->login = mb_strtolower($login);
$user->access_level = (int) clean($_REQUEST["access_level"]);
$user->email = clean($_REQUEST["email"]);
- $user->otp_enabled = checkbox_to_sql_bool($_REQUEST["otp_enabled"]);
+ $user->otp_enabled = checkbox_to_sql_bool($_REQUEST["otp_enabled"] ?? "");
// force new OTP secret when next enabled
if (Config::get_schema_version() >= 143 && !$user->otp_enabled) {
diff --git a/classes/prefs.php b/classes/prefs.php
index 24f0f7a80..85e7c34db 100644
--- a/classes/prefs.php
+++ b/classes/prefs.php
@@ -60,6 +60,7 @@ class Prefs {
const DEBUG_HEADLINE_IDS = "DEBUG_HEADLINE_IDS";
const DISABLE_CONDITIONAL_COUNTERS = "DISABLE_CONDITIONAL_COUNTERS";
const WIDESCREEN_MODE = "WIDESCREEN_MODE";
+ const CDM_ENABLE_GRID = "CDM_ENABLE_GRID";
private const _DEFAULTS = [
Prefs::PURGE_OLD_DAYS => [ 60, Config::T_INT ],
@@ -120,6 +121,7 @@ class Prefs {
Prefs::DEBUG_HEADLINE_IDS => [ false, Config::T_BOOL ],
Prefs::DISABLE_CONDITIONAL_COUNTERS => [ false, Config::T_BOOL ],
Prefs::WIDESCREEN_MODE => [ false, Config::T_BOOL ],
+ Prefs::CDM_ENABLE_GRID => [ false, Config::T_BOOL ],
];
const _PROFILE_BLACKLIST = [
diff --git a/classes/rpc.php b/classes/rpc.php
index 35125ae04..94b29ec44 100755
--- a/classes/rpc.php
+++ b/classes/rpc.php
@@ -431,7 +431,7 @@ class RPC extends Handler_Protected {
Prefs::ENABLE_FEED_CATS, Prefs::FEEDS_SORT_BY_UNREAD,
Prefs::CONFIRM_FEED_CATCHUP, Prefs::CDM_AUTO_CATCHUP,
Prefs::FRESH_ARTICLE_MAX_AGE, Prefs::HIDE_READ_SHOWS_SPECIAL,
- Prefs::COMBINED_DISPLAY_MODE, Prefs::DEBUG_HEADLINE_IDS] as $param) {
+ Prefs::COMBINED_DISPLAY_MODE, Prefs::DEBUG_HEADLINE_IDS, Prefs::CDM_ENABLE_GRID] as $param) {
$params[strtolower($param)] = (int) get_pref($param);
}
@@ -472,6 +472,9 @@ class RPC extends Handler_Protected {
$params["widescreen"] = (int) get_pref(Prefs::WIDESCREEN_MODE);
$params['simple_update'] = Config::get(Config::SIMPLE_UPDATE_MODE);
$params["icon_indicator_white"] = $this->image_to_base64("images/indicator_white.gif");
+ $params["icon_oval"] = $this->image_to_base64("images/oval.svg");
+ $params["icon_three_dots"] = $this->image_to_base64("images/three-dots.svg");
+ $params["icon_blank"] = $this->image_to_base64("images/blank_icon.gif");
$params["labels"] = Labels::get_all($_SESSION["uid"]);
return $params;
@@ -481,6 +484,8 @@ class RPC extends Handler_Protected {
if (file_exists($filename)) {
$ext = pathinfo($filename, PATHINFO_EXTENSION);
+ if ($ext == "svg") $ext = "svg+xml";
+
return "data:image/$ext;base64," . base64_encode((string)file_get_contents($filename));
} else {
return "";
@@ -603,6 +608,7 @@ class RPC extends Handler_Protected {
"feed_catchup" => __("Mark as read"),
"feed_reverse" => __("Reverse headlines"),
"feed_toggle_vgroup" => __("Toggle headline grouping"),
+ "feed_toggle_grid" => __("Toggle grid view"),
"feed_debug_update" => __("Debug feed update"),
"feed_debug_viewfeed" => __("Debug viewfeed()"),
"catchup_all" => __("Mark all feeds as read"),
@@ -663,6 +669,7 @@ class RPC extends Handler_Protected {
"a e" => "toggle_full_text",
"e" => "email_article",
"a q" => "close_article",
+ "a s" => "article_span_grid",
"a a" => "select_all",
"a u" => "select_unread",
"a U" => "select_marked",
@@ -676,8 +683,9 @@ class RPC extends Handler_Protected {
"f q" => "feed_catchup",
"f x" => "feed_reverse",
"f g" => "feed_toggle_vgroup",
+ "f G" => "feed_toggle_grid",
"f D" => "feed_debug_update",
- "f G" => "feed_debug_viewfeed",
+ "f %" => "feed_debug_viewfeed",
"f C" => "toggle_combined_mode",
"f c" => "toggle_cdm_expanded",
"Q" => "catchup_all",
diff --git a/classes/rssutils.php b/classes/rssutils.php
index e6bf08ab1..216792a0e 100755
--- a/classes/rssutils.php
+++ b/classes/rssutils.php
@@ -269,40 +269,33 @@ class RSSUtils {
return $nf;
}
- /** this is used when subscribing; TODO: update to ORM */
- static function update_basic_info(int $feed) {
-
- $pdo = Db::pdo();
-
- $sth = $pdo->prepare("SELECT owner_uid,feed_url,auth_pass,auth_login
- FROM ttrss_feeds WHERE id = ?");
- $sth->execute([$feed]);
-
- if ($row = $sth->fetch()) {
-
- $owner_uid = $row["owner_uid"];
- $auth_login = $row["auth_login"];
- $auth_pass = $row["auth_pass"];
- $fetch_url = $row["feed_url"];
+ /** this is used when subscribing */
+ static function update_basic_info(int $feed_id) {
+ $feed = ORM::for_table('ttrss_feeds')
+ ->select_many('id', 'owner_uid', 'feed_url', 'auth_pass', 'auth_login', 'title', 'site_url')
+ ->find_one($feed_id);
+ if ($feed) {
$pluginhost = new PluginHost();
- $user_plugins = get_pref(Prefs::_ENABLED_PLUGINS, $owner_uid);
+ $user_plugins = get_pref(Prefs::_ENABLED_PLUGINS, $feed->owner_uid);
$pluginhost->load(Config::get(Config::PLUGINS), PluginHost::KIND_ALL);
- $pluginhost->load((string)$user_plugins, PluginHost::KIND_USER, $owner_uid);
+ $pluginhost->load((string)$user_plugins, PluginHost::KIND_USER, $feed->owner_uid);
//$pluginhost->load_data();
$basic_info = [];
$pluginhost->run_hooks_callback(PluginHost::HOOK_FEED_BASIC_INFO, function ($result) use (&$basic_info) {
$basic_info = $result;
- }, $basic_info, $fetch_url, $owner_uid, $feed, $auth_login, $auth_pass);
+ }, $basic_info, $feed->feed_url, $feed->owner_uid, $feed_id, $feed->auth_login, $feed->auth_pass);
if (!$basic_info) {
- $feed_data = UrlHelper::fetch($fetch_url, false,
- $auth_login, $auth_pass, false,
- Config::get(Config::FEED_FETCH_TIMEOUT),
- 0);
+ $feed_data = UrlHelper::fetch([
+ 'url' => $feed->feed_url,
+ 'login' => $feed->auth_login,
+ 'pass' => $feed->auth_pass,
+ 'timeout' => Config::get(Config::FEED_FETCH_TIMEOUT),
+ ]);
$feed_data = trim($feed_data);
@@ -310,36 +303,23 @@ class RSSUtils {
$rss->init();
if (!$rss->error()) {
- $basic_info = array(
+ $basic_info = [
'title' => mb_substr(clean($rss->get_title()), 0, 199),
- 'site_url' => mb_substr(rewrite_relative_url($fetch_url, clean($rss->get_link())), 0, 245)
- );
+ 'site_url' => mb_substr(UrlHelper::rewrite_relative($feed->feed_url, clean($rss->get_link())), 0, 245),
+ ];
}
}
if ($basic_info && is_array($basic_info)) {
- $sth = $pdo->prepare("SELECT title, site_url FROM ttrss_feeds WHERE id = ?");
- $sth->execute([$feed]);
-
- if ($row = $sth->fetch()) {
-
- $registered_title = $row["title"];
- $orig_site_url = $row["site_url"];
-
- if ($basic_info['title'] && (!$registered_title || $registered_title == "[Unknown]")) {
-
- $sth = $pdo->prepare("UPDATE ttrss_feeds SET
- title = ? WHERE id = ?");
- $sth->execute([$basic_info['title'], $feed]);
- }
-
- if ($basic_info['site_url'] && $orig_site_url != $basic_info['site_url']) {
- $sth = $pdo->prepare("UPDATE ttrss_feeds SET
- site_url = ? WHERE id = ?");
- $sth->execute([$basic_info['site_url'], $feed]);
- }
+ if (!empty($basic_info['title']) && (!$feed->title || $feed->title == '[Unknown]')) {
+ $feed->title = $basic_info['title'];
+ }
+ if (!empty($basic_info['site_url']) && $feed->site_url != $basic_info['site_url']) {
+ $feed->site_url = $basic_info['site_url'];
}
+
+ $feed->save();
}
}
}
@@ -1422,8 +1402,8 @@ class RSSUtils {
$matches = array();
foreach ($filters as $filter) {
- $match_any_rule = $filter["match_any_rule"];
- $inverse = $filter["inverse"];
+ $match_any_rule = $filter["match_any_rule"] ?? false;
+ $inverse = $filter["inverse"] ?? false;
$filter_match = false;
$last_processed_rule = false;
@@ -1431,7 +1411,7 @@ class RSSUtils {
$match = false;
$reg_exp = str_replace('/', '\/', (string)$rule["reg_exp"]);
$reg_exp = str_replace("\n", "", $reg_exp); // reg_exp may be formatted with CRs now because of textarea, we need to strip those
- $rule_inverse = $rule["inverse"];
+ $rule_inverse = $rule["inverse"] ?? false;
$last_processed_rule = $rule;
if (empty($reg_exp))
@@ -1879,6 +1859,6 @@ class RSSUtils {
static function function_enabled($func) {
return !in_array($func,
- explode(',', (string)ini_get('disable_functions')));
+ explode(',', str_replace(" ", "", ini_get('disable_functions'))));
}
}
diff --git a/classes/urlhelper.php b/classes/urlhelper.php
index 55d5d1e6a..46d80a0e6 100644
--- a/classes/urlhelper.php
+++ b/classes/urlhelper.php
@@ -271,10 +271,15 @@ class UrlHelper {
// holy shit closures in php
// download & upload are *expected* sizes respectively, could be zero
- curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($curl_handle, $download_size, $downloaded, $upload_size, $uploaded) use( &$max_size) {
- Debug::log("[curl progressfunction] $downloaded $max_size", Debug::$LOG_EXTENDED);
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($curl_handle, $download_size, $downloaded, $upload_size, $uploaded) use(&$max_size, $url) {
+ //Debug::log("[curl progressfunction] $downloaded $max_size", Debug::$LOG_EXTENDED);
- return ($downloaded > $max_size) ? 1 : 0; // if max size is set, abort when exceeding it
+ if ($downloaded > $max_size) {
+ Debug::log("curl: reached max size of $max_size bytes requesting $url, aborting.", Debug::LOG_VERBOSE);
+ return 1;
+ }
+
+ return 0;
});
}
diff --git a/classes/userhelper.php b/classes/userhelper.php
index ce26e6c71..0bf67243e 100644
--- a/classes/userhelper.php
+++ b/classes/userhelper.php
@@ -299,7 +299,7 @@ class UserHelper {
if ($user->otp_enabled) {
$user->otp_secret = $salt_based_secret;
} else {
- $user->otp_secret = bin2hex(get_random_bytes(6));
+ $user->otp_secret = bin2hex(get_random_bytes(10));
}
$user->save();
diff --git a/gulpfile.js b/gulpfile.js
index ca766dcce..9d09e984e 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -12,8 +12,8 @@ function swallowError(error) {
gulp.task('less', function(cb) {
gulp
.src(['themes/compact.less', 'themes/compact_night.less',
- 'themes/light.less', 'themes/night_blue.less', 'themes/night.less'])
- .pipe(less())
+ 'themes/light.less', 'themes/light-high-contrast.less', 'themes/night_blue.less', 'themes/night.less'])
+ .pipe(less({javascriptEnabled: true}))
.on('error', swallowError)
.pipe(
gulp.dest(function(f) {
diff --git a/images/favicon-512px.png b/images/favicon-512px.png
new file mode 100644
index 000000000..ac1146be5
--- /dev/null
+++ b/images/favicon-512px.png
Binary files differ
diff --git a/images/logo_small.png b/images/logo_small.png
deleted file mode 100644
index f7f28a687..000000000
--- a/images/logo_small.png
+++ /dev/null
Binary files differ
diff --git a/images/oval.svg b/images/oval.svg
new file mode 100644
index 000000000..e59d5bf18
--- /dev/null
+++ b/images/oval.svg
@@ -0,0 +1,17 @@
+<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
+<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#257aa7">
+ <g fill="none" fill-rule="evenodd">
+ <g stroke-width="8" transform="matrix(0.83009609,0,0,0.83009609,4.0582705,4.0582705)">
+ <circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
+ <path d="M 36,18 C 36,8.06 27.94,0 18,0">
+ <animateTransform
+ attributeName="transform"
+ type="rotate"
+ from="0 18 18"
+ to="360 18 18"
+ dur="1s"
+ repeatCount="indefinite"/>
+ </path>
+ </g>
+ </g>
+</svg>
diff --git a/images/three-dots.svg b/images/three-dots.svg
new file mode 100644
index 000000000..e724ca05e
--- /dev/null
+++ b/images/three-dots.svg
@@ -0,0 +1,33 @@
+<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
+<svg width="120" height="30" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="#257aa7">
+ <circle cx="15" cy="15" r="15">
+ <animate attributeName="r" from="15" to="15"
+ begin="0s" dur="0.8s"
+ values="15;9;15" calcMode="linear"
+ repeatCount="indefinite" />
+ <animate attributeName="fill-opacity" from="1" to="1"
+ begin="0s" dur="0.8s"
+ values="1;.5;1" calcMode="linear"
+ repeatCount="indefinite" />
+ </circle>
+ <circle cx="60" cy="15" r="9" fill-opacity="0.3">
+ <animate attributeName="r" from="9" to="9"
+ begin="0s" dur="0.8s"
+ values="9;15;9" calcMode="linear"
+ repeatCount="indefinite" />
+ <animate attributeName="fill-opacity" from="0.5" to="0.5"
+ begin="0s" dur="0.8s"
+ values=".5;1;.5" calcMode="linear"
+ repeatCount="indefinite" />
+ </circle>
+ <circle cx="105" cy="15" r="15">
+ <animate attributeName="r" from="15" to="15"
+ begin="0s" dur="0.8s"
+ values="15;9;15" calcMode="linear"
+ repeatCount="indefinite" />
+ <animate attributeName="fill-opacity" from="1" to="1"
+ begin="0s" dur="0.8s"
+ values="1;.5;1" calcMode="linear"
+ repeatCount="indefinite" />
+ </circle>
+</svg>
diff --git a/include/functions.php b/include/functions.php
index 73d963803..e8f41d56a 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -420,6 +420,8 @@
$check = "themes.local/$theme";
if (file_exists($check)) return $check;
+
+ return "";
}
function theme_exists($theme) {
diff --git a/include/login_form.php b/include/login_form.php
index 9efe0e238..2e0eb077f 100755
--- a/include/login_form.php
+++ b/include/login_form.php
@@ -15,9 +15,7 @@
} ?>
- <?php if (theme_exists(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))) {
- echo stylesheet_tag(get_theme_path(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET)));
- } ?>
+ <?= Config::get_override_links() ?>
<style type="text/css">
@media (prefers-color-scheme: dark) {
diff --git a/index.php b/index.php
index ba6e03376..b602042bd 100644
--- a/index.php
+++ b/index.php
@@ -35,9 +35,7 @@
}
} ?>
- <?php if (theme_exists(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))) {
- echo stylesheet_tag(get_theme_path(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET)));
- } ?>
+ <?= Config::get_override_links() ?>
<script type="text/javascript">
const __csrf_token = "<?= $_SESSION["csrf_token"]; ?>";
@@ -112,19 +110,31 @@
}
</style>
+ <noscript>
+ <?= stylesheet_tag("themes/light.css") ?>
+
+ <style type="text/css">
+ body.css_loading noscript {
+ display : block;
+ margin : 16px;
+ }
+ </style>
+ </noscript>
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="referrer" content="no-referrer"/>
</head>
<body class="flat ttrss_main ttrss_index css_loading">
-<div id="overlay" style="display : block">
+<noscript class="alert alert-error"><?= ('Javascript is disabled. Please enable it.') ?></noscript>
+
+<div id="overlay">
<div id="overlay_inner">
<?= __("Loading, please wait...") ?>
<div dojoType="dijit.ProgressBar" places="0" style="width : 300px" id="loading_bar"
progress="0" maximum="100">
</div>
- <noscript><br/><?php print_error('Javascript is disabled. Please enable it.') ?></noscript>
</div>
</div>
@@ -133,9 +143,10 @@
<div id="main" dojoType="dijit.layout.BorderContainer">
<div id="feeds-holder" dojoType="dijit.layout.ContentPane" region="leading" style="width : 20%" splitter="true">
- <div id="feedlistLoading">
- <img src='images/indicator_tiny.gif'/>
- <?= __("Loading, please wait..."); ?></div>
+ <div id="feedlistLoading" class="text-center text-muted text-small">
+ <img class="icon-three-dots" src="images/three-dots.svg?2">
+ <?= __("Loading, please wait..."); ?>
+ </div>
<?php
PluginHost::getInstance()->run_hooks_callback(PluginHost::HOOK_FEED_TREE, function ($result) {
echo $result;
@@ -199,7 +210,7 @@
?>
</select>
- <div dojoType="fox.form.ComboButton" onclick="Feeds.catchupCurrent()">
+ <div class="catchup-button" dojoType="fox.form.ComboButton" onclick="Feeds.catchupCurrent()">
<span><?= __('Mark as read') ?></span>
<div dojoType="dijit.DropDownMenu">
<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('1day')">
diff --git a/js/App.js b/js/App.js
index 20498e692..ecf8c46c1 100644
--- a/js/App.js
+++ b/js/App.js
@@ -514,9 +514,12 @@ const App = {
this.LABEL_BASE_INDEX = parseInt(params[k]);
break;
case "cdm_auto_catchup":
- if (params[k] == 1) {
- const hl = App.byId("headlines-frame");
- if (hl) hl.addClassName("auto_catchup");
+ {
+ const headlines = App.byId("headlines-frame");
+
+ // we could be in preferences
+ if (headlines)
+ headlines.setAttribute("data-auto-catchup", params[k] ? "true" : "false");
}
break;
case "hotkeys":
@@ -685,15 +688,16 @@ const App = {
checkBrowserFeatures: function() {
let errorMsg = "";
- ['MutationObserver'].forEach(function(wf) {
- if (!(wf in window)) {
- errorMsg = `Browser feature check failed: <code>window.${wf}</code> not found.`;
+ ['MutationObserver', 'requestIdleCallback'].forEach((t) => {
+ if (!(t in window)) {
+ errorMsg = `Browser check failed: <code>window.${t}</code> not found.`;
throw new Error(errorMsg);
}
});
- if (errorMsg) {
- this.Error.fatal(errorMsg, {info: navigator.userAgent});
+ if (typeof Promise.allSettled == "undefined") {
+ errorMsg = `Browser check failed: <code>Promise.allSettled</code> is not defined.`;
+ throw new Error(errorMsg);
}
return errorMsg == "";
@@ -868,41 +872,44 @@ const App = {
},
setWidescreen: function(wide) {
const article_id = Article.getActive();
+ const headlines_frame = App.byId("headlines-frame");
+ const content_insert = dijit.byId("content-insert");
+
+ // TODO: setStyle stuff should probably be handled by CSS
if (wide) {
dijit.byId("headlines-wrap-inner").attr("design", 'sidebar');
- dijit.byId("content-insert").attr("region", "trailing");
+ content_insert.attr("region", "trailing");
- dijit.byId("content-insert").domNode.setStyle({width: '50%',
+ content_insert.domNode.setStyle({width: '50%',
height: 'auto',
borderTopWidth: '0px' });
if (parseInt(Cookie.get("ttrss_ci_width")) > 0) {
- dijit.byId("content-insert").domNode.setStyle(
+ content_insert.domNode.setStyle(
{width: Cookie.get("ttrss_ci_width") + "px" });
}
- App.byId("headlines-frame").setStyle({ borderBottomWidth: '0px' });
- App.byId("headlines-frame").addClassName("wide");
+ headlines_frame.setStyle({ borderBottomWidth: '0px' });
} else {
- dijit.byId("content-insert").attr("region", "bottom");
+ content_insert.attr("region", "bottom");
- dijit.byId("content-insert").domNode.setStyle({width: 'auto',
+ content_insert.domNode.setStyle({width: 'auto',
height: '50%',
borderTopWidth: '0px'});
if (parseInt(Cookie.get("ttrss_ci_height")) > 0) {
- dijit.byId("content-insert").domNode.setStyle(
+ content_insert.domNode.setStyle(
{height: Cookie.get("ttrss_ci_height") + "px" });
}
- App.byId("headlines-frame").setStyle({ borderBottomWidth: '1px' });
- App.byId("headlines-frame").removeClassName("wide");
-
+ headlines_frame.setStyle({ borderBottomWidth: '1px' });
}
+ headlines_frame.setAttribute("data-is-wide-screen", wide ? "true" : "false");
+
Article.close();
if (article_id) Article.view(article_id);
@@ -931,16 +938,18 @@ const App = {
} else {
this.hotkey_actions["next_feed"] = () => {
- const rv = dijit.byId("feedTree").getNextFeed(
+ const [feed, is_cat] = Feeds.getNextFeed(
Feeds.getActive(), Feeds.activeIsCat());
- if (rv) Feeds.open({feed: rv[0], is_cat: rv[1], delayed: true})
+ if (feed !== false)
+ Feeds.open({feed: feed, is_cat: is_cat, delayed: true})
};
this.hotkey_actions["prev_feed"] = () => {
- const rv = dijit.byId("feedTree").getPreviousFeed(
+ const [feed, is_cat] = Feeds.getPreviousFeed(
Feeds.getActive(), Feeds.activeIsCat());
- if (rv) Feeds.open({feed: rv[0], is_cat: rv[1], delayed: true})
+ if (feed !== false)
+ Feeds.open({feed: feed, is_cat: is_cat, delayed: true})
};
this.hotkey_actions["next_article_or_scroll"] = (event) => {
if (this.isCombinedMode())
@@ -1102,6 +1111,12 @@ const App = {
this.hotkey_actions["feed_reverse"] = () => {
Headlines.reverse();
};
+ this.hotkey_actions["feed_toggle_grid"] = () => {
+ xhr.json("backend.php", {op: "rpc", method: "togglepref", key: "CDM_ENABLE_GRID"}, (reply) => {
+ App.setInitParam("cdm_enable_grid", reply.value);
+ Headlines.renderAgain();
+ })
+ };
this.hotkey_actions["feed_toggle_vgroup"] = () => {
xhr.post("backend.php", {op: "rpc", method: "togglepref", key: "VFEED_GROUP_BY_FEED"}, () => {
Feeds.reloadCurrent();
@@ -1194,6 +1209,9 @@ const App = {
Headlines.renderAgain();
});
};
+ this.hotkey_actions["article_span_grid"] = () => {
+ Article.cdmToggleGridSpan(Article.getActive());
+ };
}
},
openPreferences: function(tab) {
diff --git a/js/Article.js b/js/Article.js
index ed74051a6..16abfbfee 100644
--- a/js/Article.js
+++ b/js/Article.js
@@ -93,6 +93,16 @@ const Article = {
w.opener = null;
w.location = url;
},
+ cdmToggleGridSpan: function(id) {
+ const row = App.byId(`RROW-${id}`);
+
+ if (row) {
+ row.toggleClassName('grid-span-row');
+
+ this.setActive(id);
+ this.cdmMoveToId(id);
+ }
+ },
cdmUnsetActive: function (event) {
const row = App.byId(`RROW-${Article.getActive()}`);
@@ -273,7 +283,9 @@ const Article = {
row.setAttribute("data-content", row.getAttribute("data-content-original"));
row.removeAttribute("data-content-original");
- row.querySelector(".content-inner").innerHTML = "&nbsp;";
+ row.querySelector(".content-inner").innerHTML = `<div class="text-center text-muted">
+ ${__("Loading, please wait...")}
+ </div>`
}
},
view: function (id, no_expand) {
@@ -389,10 +401,12 @@ const Article = {
const ctr = App.byId("headlines-frame");
const row = App.byId(`RROW-${id}`);
- if (!row || !ctr) return;
+ if (ctr && row) {
+ const grid_gap = parseInt(window.getComputedStyle(ctr).gridGap) || 0;
- if (force_to_top || !App.Scrollable.fitsInContainer(row, ctr)) {
- ctr.scrollTop = row.offsetTop;
+ if (force_to_top || !App.Scrollable.fitsInContainer(row, ctr)) {
+ ctr.scrollTop = row.offsetTop - grid_gap;
+ }
}
},
setActive: function (id) {
diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js
index ab8441cac..a68dc8068 100644
--- a/js/CommonDialogs.js
+++ b/js/CommonDialogs.js
@@ -33,7 +33,7 @@ const CommonDialogs = {
<section>
<fieldset>
- <div style='float : right'><img style='display : none' id='feed_add_spinner' src='images/indicator_white.gif'></div>
+ <div class='pull-right'><img style='display : none' id='feed_add_spinner' src='${App.getInitParam('icon_oval')}'></div>
<input style='font-size : 16px; width : 500px;'
placeHolder="${__("Feed or site URL")}"
dojoType='dijit.form.ValidationTextBox'
diff --git a/js/CommonFilters.js b/js/CommonFilters.js
index 1450458f8..8a20480f0 100644
--- a/js/CommonFilters.js
+++ b/js/CommonFilters.js
@@ -38,16 +38,19 @@ const Filters = {
console.log("got results:" + result.length);
- App.byId("prefFilterProgressMsg").innerHTML = __("Looking for articles (%d processed, %f found)...")
- .replace("%f", test_dialog.results)
- .replace("%d", offset);
+ const loading_message = test_dialog.domNode.querySelector(".loading-message");
+ const results_list = test_dialog.domNode.querySelector(".filter-results-list");
+
+ loading_message.innerHTML = __("Looking for articles (%d processed, %f found)...")
+ .replace("%f", test_dialog.results)
+ .replace("%d", offset);
console.log(offset + " " + test_dialog.max_offset);
for (let i = 0; i < result.length; i++) {
- const tmp = dojo.create("table", { innerHTML: result[i]});
+ const tmp = dojo.create("div", { innerHTML: result[i]});
- App.byId("prefFilterTestResultList").innerHTML += tmp.innerHTML;
+ results_list.innerHTML += tmp.innerHTML;
}
if (test_dialog.results < 30 && offset < test_dialog.max_offset) {
@@ -60,14 +63,15 @@ const Filters = {
} else {
// all done
- Element.hide("prefFilterLoadingIndicator");
+ test_dialog.domNode.querySelector(".loading-indicator").hide();
if (test_dialog.results == 0) {
- App.byId("prefFilterTestResultList").innerHTML = `<tr><td align='center'>
- ${__('No recent articles matching this filter have been found.')}</td></tr>`;
- App.byId("prefFilterProgressMsg").innerHTML = "Articles matching this filter:";
+ results_list.innerHTML = `<li class="text-center text-muted">
+ ${__('No recent articles matching this filter have been found.')}</li>`;
+
+ loading_message.innerHTML = __("Articles matching this filter:");
} else {
- App.byId("prefFilterProgressMsg").innerHTML = __("Found %d articles matching this filter:")
+ loading_message.innerHTML = __("Found %d articles matching this filter:")
.replace("%d", test_dialog.results);
}
@@ -75,7 +79,7 @@ const Filters = {
} else if (!result) {
console.log("getTestResults: can't parse results object");
- Element.hide("prefFilterLoadingIndicator");
+ test_dialog.domNode.querySelector(".loading-indicator").hide();
Notify.error("Error while trying to get filter test results.");
} else {
console.log("getTestResults: dialog closed, bailing out.");
@@ -86,12 +90,12 @@ const Filters = {
});
},
content: `
- <div>
- <img id='prefFilterLoadingIndicator' src='images/indicator_tiny.gif'>&nbsp;
- <span id='prefFilterProgressMsg'>Looking for articles...</span>
+ <div class="text-muted">
+ <img class="loading-indicator icon-three-dots" src="${App.getInitParam("icon_three_dots")}">
+ <span class="loading-message">${__("Looking for articles...")}</span>
</div>
- <ul class='panel panel-scrollable list list-unstyled' id='prefFilterTestResultList'></ul>
+ <ul class='panel panel-scrollable list list-unstyled filter-results-list'></ul>
<footer class='text-center'>
<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>${__('Close this window')}</button>
diff --git a/js/FeedStoreModel.js b/js/FeedStoreModel.js
index 736bfbed6..befc441af 100644
--- a/js/FeedStoreModel.js
+++ b/js/FeedStoreModel.js
@@ -54,45 +54,6 @@ define(["dojo/_base/declare", "dijit/tree/ForestStoreModel"], function (declare)
if (treeItem)
return this.store.setValue(treeItem, key, value);
},
- getNextUnreadFeed: function (feed, is_cat) {
- if (!this.store._itemsByIdentity)
- return null;
-
- let treeItem;
-
- if (is_cat) {
- treeItem = this.store._itemsByIdentity['CAT:' + feed];
- } else {
- treeItem = this.store._itemsByIdentity['FEED:' + feed];
- }
-
- const items = this.store._arrayOfAllItems;
-
- for (let i = 0; i < items.length; i++) {
- if (items[i] == treeItem) {
-
- for (let j = i + 1; j < items.length; j++) {
- const unread = this.store.getValue(items[j], 'unread');
- const id = this.store.getValue(items[j], 'id');
-
- if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
- if (!is_cat || !(this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed)) return items[j];
- }
- }
-
- for (let j = 0; j < i; j++) {
- const unread = this.store.getValue(items[j], 'unread');
- const id = this.store.getValue(items[j], 'id');
-
- if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
- if (!is_cat || !(this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed)) return items[j];
- }
- }
- }
- }
-
- return null;
- },
hasCats: function () {
if (this.store && this.store._itemsByIdentity)
return this.store._itemsByIdentity['CAT:-1'] != undefined;
diff --git a/js/FeedTree.js b/js/FeedTree.js
index 17cd3deea..b81638c39 100755
--- a/js/FeedTree.js
+++ b/js/FeedTree.js
@@ -82,6 +82,9 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}
if (id.match("FEED:")) {
+ tnode.rowNode.setAttribute('data-feed-id', bare_id);
+ tnode.rowNode.setAttribute('data-is-cat', "false");
+
const menu = new dijit.Menu();
menu.row_id = bare_id;
@@ -132,10 +135,18 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}
if (id.match("CAT:")) {
- tnode.loadingNode = dojo.create('img', { className: 'loadingNode', src: 'images/blank_icon.gif'});
+ tnode.rowNode.setAttribute('data-feed-id', bare_id);
+ tnode.rowNode.setAttribute('data-is-cat', "true");
+
+ tnode.loadingNode = dojo.create('img', { className: 'loadingNode', src: App.getInitParam('icon_blank')});
domConstruct.place(tnode.loadingNode, tnode.labelNode, 'after');
}
+ if (id.match("FEED:")) {
+ tnode.loadingNode = dojo.create('img', { className: 'loadingNode', src: App.getInitParam('icon_blank')});
+ domConstruct.place(tnode.loadingNode, tnode.expandoNode, 'only');
+ }
+
if (id.match("CAT:") && bare_id == -1) {
const menu = new dijit.Menu();
menu.row_id = bare_id;
@@ -191,10 +202,15 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
return (item.unread <= 0) ? "dijitTreeLabel" : "dijitTreeLabel Unread";
},
getRowClass: function (item/*, opened */) {
- let rc = "dijitTreeRow";
+ let rc = "dijitTreeRow dijitTreeRowFlex";
const is_cat = String(item.id).indexOf('CAT:') != -1;
+ if (is_cat)
+ rc += " Is_Cat";
+ else
+ rc += " Is_Feed";
+
if (!is_cat && item.error != '') rc += " Error";
if (item.unread > 0) rc += " Unread";
if (item.auxcounter > 0) rc += " Has_Aux";
@@ -303,7 +319,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}, 0);
}
},
- setFeedIcon: function(feed, is_cat, src) {
+ setIcon: function(feed, is_cat, src) {
let treeNode;
if (is_cat)
@@ -313,13 +329,19 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
if (treeNode) {
treeNode = treeNode[0];
- const icon = dojo.create('img', { src: src, className: 'icon' });
- domConstruct.place(icon, treeNode.iconNode, 'only');
- return true;
+
+ // could be <i material>
+ const icon = treeNode.iconNode.querySelector('img.icon');
+
+ if (icon) {
+ icon.src = src;
+
+ return true;
+ }
}
return false;
},
- setFeedExpandoIcon: function(feed, is_cat, src) {
+ showLoading: function(feed, is_cat, show) {
let treeNode;
if (is_cat)
@@ -329,14 +351,17 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
if (treeNode) {
treeNode = treeNode[0];
- if (treeNode.loadingNode) {
- treeNode.loadingNode.src = src;
- return true;
+
+ if (show) {
+ treeNode.loadingNode.addClassName("visible");
+ treeNode.loadingNode.setAttribute("src",
+ is_cat ? App.getInitParam("icon_three_dots") : App.getInitParam("icon_oval"));
} else {
- const icon = dojo.create('img', { src: src, className: 'loadingExpando' });
- domConstruct.place(icon, treeNode.expandoNode, 'only');
- return true;
+ treeNode.loadingNode.removeClassName("visible");
+ treeNode.loadingNode.setAttribute("src", App.getInitParam("icon_blank"))
}
+
+ return true
}
return false;
@@ -360,7 +385,28 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}
},
- getNextFeed: function (feed, is_cat) {
+ getNextUnread: function(feed, is_cat) {
+ return this.getNextFeed(feed, is_cat, true);
+ },
+ _nextTreeItemFromIndex: function (start, unread_only) {
+ const items = this.model.store._arrayOfAllItems;
+
+ for (let i = start+1; i < items.length; i++) {
+ const id = String(items[i].id);
+ const box = this._itemNodesMap[id];
+ const unread = parseInt(items[i].unread);
+
+ if (box && (!unread_only || unread > 0)) {
+ const row = box[0].rowNode;
+ const cat = box[0].rowNode.parentNode.parentNode;
+
+ if (Element.visible(cat) && Element.visible(row)) {
+ return items[i];
+ }
+ }
+ }
+ },
+ getNextFeed: function (feed, is_cat, unread_only = false) {
let treeItem;
if (is_cat) {
@@ -370,35 +416,40 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}
const items = this.model.store._arrayOfAllItems;
- let item = items[0];
+ const start = items.indexOf(treeItem);
- for (let i = 0; i < items.length; i++) {
- if (items[i] == treeItem) {
+ if (start != -1) {
+ let item = this._nextTreeItemFromIndex(start, unread_only);
- for (let j = i+1; j < items.length; j++) {
- const id = String(items[j].id);
- const box = this._itemNodesMap[id];
+ // let's try again from the top
+ // 0 (instead of -1) to skip Special category
+ if (!item) {
+ item = this._nextTreeItemFromIndex(0, unread_only);
+ }
- if (box) {
- const row = box[0].rowNode;
- const cat = box[0].rowNode.parentNode.parentNode;
+ if (item)
+ return [this.model.store.getValue(item, 'bare_id'),
+ !this.model.store.getValue(item, 'id').match('FEED:')];
+ }
- if (Element.visible(cat) && Element.visible(row)) {
- item = items[j];
- break;
- }
- }
+ return [false, false];
+ },
+ _prevTreeItemFromIndex: function (start) {
+ const items = this.model.store._arrayOfAllItems;
+
+ for (let i = start-1; i > 0; i--) {
+ const id = String(items[i].id);
+ const box = this._itemNodesMap[id];
+
+ if (box) {
+ const row = box[0].rowNode;
+ const cat = box[0].rowNode.parentNode.parentNode;
+
+ if (Element.visible(cat) && Element.visible(row)) {
+ return items[i];
}
- break;
}
}
-
- if (item) {
- return [this.model.store.getValue(item, 'bare_id'),
- !this.model.store.getValue(item, 'id').match('FEED:')];
- } else {
- return false;
- }
},
getPreviousFeed: function (feed, is_cat) {
let treeItem;
@@ -410,37 +461,22 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co
}
const items = this.model.store._arrayOfAllItems;
- let item = items[0] == treeItem ? items[items.length-1] : items[0];
-
- for (let i = 0; i < items.length; i++) {
- if (items[i] == treeItem) {
-
- for (let j = i-1; j > 0; j--) {
- const id = String(items[j].id);
- const box = this._itemNodesMap[id];
-
- if (box) {
- const row = box[0].rowNode;
- const cat = box[0].rowNode.parentNode.parentNode;
+ const start = items.indexOf(treeItem);
- if (Element.visible(cat) && Element.visible(row)) {
- item = items[j];
- break;
- }
- }
+ if (start != -1) {
+ let item = this._prevTreeItemFromIndex(start);
- }
- break;
+ // wrap from the bottom
+ if (!item) {
+ item = this._prevTreeItemFromIndex(items.length);
}
- }
- if (item) {
- return [this.model.store.getValue(item, 'bare_id'),
- !this.model.store.getValue(item, 'id').match('FEED:')];
- } else {
- return false;
+ if (item)
+ return [this.model.store.getValue(item, 'bare_id'),
+ !this.model.store.getValue(item, 'id').match('FEED:')];
}
+ return [false, false];
},
getFeedCategory: function(feed) {
try {
diff --git a/js/Feeds.js b/js/Feeds.js
index 33a1fa3dc..befd7e46e 100644
--- a/js/Feeds.js
+++ b/js/Feeds.js
@@ -113,7 +113,7 @@ const Feeds = {
this.hideOrShowFeeds(App.getInitParam("hide_read_feeds"));
this._counters_prev = elems;
- PluginHost.run(PluginHost.HOOK_COUNTERS_PROCESSED);
+ PluginHost.run(PluginHost.HOOK_COUNTERS_PROCESSED, elems);
},
reloadCurrent: function(method) {
if (this.getActive() != undefined) {
@@ -133,9 +133,10 @@ const Feeds = {
return Feeds.reloadCurrent('');
},
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});
+ const [feed, is_cat] = this.getNextUnread(this.getActive(), this.activeIsCat());
+
+ if (feed !== false)
+ this.open({feed: feed, is_cat: is_cat});
},
toggle: function() {
Element.toggle("feeds-holder");
@@ -311,18 +312,22 @@ const Feeds = {
setActive: function(id, is_cat) {
console.log('setActive', id, is_cat);
- if ('requestIdleCallback' in window)
- window.requestIdleCallback(() => {
- App.Hash.set({f: id, c: is_cat ? 1 : 0});
- });
- else
+ window.requestIdleCallback(() => {
App.Hash.set({f: id, c: is_cat ? 1 : 0});
+ });
this._active_feed_id = id;
this._active_feed_is_cat = is_cat;
- App.byId("headlines-frame").setAttribute("feed-id", id);
- App.byId("headlines-frame").setAttribute("is-cat", is_cat ? 1 : 0);
+ const container = App.byId("headlines-frame");
+
+ // TODO @deprecated: these two should be removed (replaced with data- attributes below)
+ container.setAttribute("feed-id", id);
+ container.setAttribute("is-cat", is_cat ? 1 : 0);
+ // ^
+
+ container.setAttribute("data-feed-id", id);
+ container.setAttribute("data-is-cat", is_cat ? "true" : "false");
this.select(id, is_cat);
@@ -395,21 +400,20 @@ const Feeds = {
query.m = "ForceUpdate";
}
- 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);
window.clearTimeout(this._viewfeed_wait_timeout);
this._viewfeed_wait_timeout = window.setTimeout(() => {
+
+ this.showLoading(feed, is_cat, true);
+ //Notify.progress("Loading, please wait...", true);*/
+
xhr.json("backend.php", query, (reply) => {
try {
window.clearTimeout(this._infscroll_timeout);
- this.setExpando(feed, is_cat, 'images/blank_icon.gif');
+ this.showLoading(feed, is_cat, false);
Headlines.onLoaded(reply, offset, append);
PluginHost.run(PluginHost.HOOK_FEED_LOADED, [feed, is_cat]);
} catch (e) {
@@ -475,10 +479,10 @@ const Feeds = {
// only select next unread feed if catching up entirely (as opposed to last week etc)
if (show_next_feed && !mode) {
- const nuf = this.getNextUnread(feed, is_cat);
+ const [next_feed, next_is_cat] = this.getNextUnread(feed, is_cat);
- if (nuf) {
- this.open({feed: nuf, is_cat: is_cat});
+ if (next_feed !== false) {
+ this.open({feed: next_feed, is_cat: next_is_cat});
}
} else if (feed == this.getActive() && is_cat == this.activeIsCat()) {
this.reloadCurrent();
@@ -522,7 +526,7 @@ const Feeds = {
const tree = dijit.byId("feedTree");
if (tree && tree.model)
- return tree._cat_of_feed(feed);
+ return tree.getFeedCategory(feed);
} catch (e) {
//
@@ -570,21 +574,35 @@ const Feeds = {
setIcon: function(feed, is_cat, src) {
const tree = dijit.byId("feedTree");
- if (tree) return tree.setFeedIcon(feed, is_cat, src);
+ if (tree) return tree.setIcon(feed, is_cat, src);
},
- setExpando: function(feed, is_cat, src) {
+ showLoading: function(feed, is_cat, show) {
const tree = dijit.byId("feedTree");
- if (tree) return tree.setFeedExpandoIcon(feed, is_cat, src);
+ if (tree) return tree.showLoading(feed, is_cat, show);
return false;
},
+ getNextFeed: function(feed, is_cat) {
+ const tree = dijit.byId("feedTree");
+
+ if (tree) return tree.getNextFeed(feed, is_cat, false);
+
+ return [false, false];
+ },
+ getPreviousFeed: function(feed, is_cat) {
+ const tree = dijit.byId("feedTree");
+
+ if (tree) return tree.getPreviousFeed(feed, is_cat);
+
+ return [false, 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');
+ if (tree) return tree.getNextUnread(feed, is_cat);
+
+ return [false, false];
},
search: function() {
xhr.json("backend.php",
diff --git a/js/Headlines.js b/js/Headlines.js
index 28e43be1f..134bdad6d 100755
--- a/js/Headlines.js
+++ b/js/Headlines.js
@@ -17,17 +17,27 @@ const Headlines = {
sticky_header_observer: new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
- const header = entry.target.nextElementSibling;
+ const header = entry.target.closest('.cdm').querySelector(".header");
- if (entry.intersectionRatio == 0) {
- header.setAttribute("stuck", "1");
-
- } else if (entry.intersectionRatio == 1) {
- header.removeAttribute("stuck");
+ if (entry.isIntersecting) {
+ header.removeAttribute("data-is-stuck");
+ } else {
+ header.setAttribute("data-is-stuck", "true");
}
- //console.log(entry.target, header, entry.intersectionRatio);
+ //console.log(entry.target, entry.intersectionRatio, entry.isIntersecting, entry.boundingClientRect.top);
+ });
+ },
+ {threshold: [0, 1], root: document.querySelector("#headlines-frame")}
+ ),
+ sticky_content_observer: new IntersectionObserver(
+ (entries, observer) => {
+ entries.forEach((entry) => {
+ const header = entry.target.closest('.cdm').querySelector(".header");
+ header.style.position = entry.isIntersecting ? "sticky" : "unset";
+
+ //console.log(entry.target, entry.intersectionRatio, entry.isIntersecting, entry.boundingClientRect.top);
});
},
{threshold: [0, 1], root: document.querySelector("#headlines-frame")}
@@ -72,14 +82,13 @@ const Headlines = {
}
});
+ PluginHost.run(PluginHost.HOOK_HEADLINE_MUTATIONS, mutations);
+
Headlines.updateSelectedPrompt();
- if ('requestIdleCallback' in window)
- window.requestIdleCallback(() => {
- Headlines.syncModified(modified);
- });
- else
+ window.requestIdleCallback(() => {
Headlines.syncModified(modified);
+ });
}),
syncModified: function (modified) {
const ops = {
@@ -173,14 +182,14 @@ const Headlines = {
});
}
- Promise.all(promises).then((results) => {
+ Promise.allSettled(promises).then((results) => {
let feeds = [];
let labels = [];
results.forEach((res) => {
if (res) {
try {
- const obj = JSON.parse(res);
+ const obj = JSON.parse(res.value);
if (obj.feeds)
feeds = feeds.concat(obj.feeds);
@@ -198,6 +207,8 @@ const Headlines = {
console.log('requesting counters for', feeds, labels);
Feeds.requestCounters(feeds, labels);
}
+
+ PluginHost.run(PluginHost.HOOK_HEADLINE_MUTATIONS_SYNCED, results);
});
},
click: function (event, id, in_body) {
@@ -340,8 +351,7 @@ const Headlines = {
// invoke lazy load if last article in buffer is nearly visible OR is active
if (Article.getActive() == last_row.getAttribute("data-article-id") || last_row.offsetTop - 250 <= container.scrollTop + container.offsetHeight) {
- hsp.innerHTML = "<span class='loading'><img src='images/indicator_tiny.gif'> " +
- __("Loading, please wait...") + "</span>";
+ hsp.innerHTML = `<span class='text-muted text-small text-center'><img class="icon-three-dots" src="${App.getInitParam('icon_three_dots')}"> ${__("Loading, please wait...")}</span>`;
Headlines.loadMore();
return;
@@ -371,6 +381,9 @@ const Headlines = {
}
}
}
+
+ PluginHost.run(PluginHost.HOOK_HEADLINES_SCROLL_HANDLER);
+
} catch (e) {
console.warn("scrollHandler", e);
}
@@ -378,11 +391,17 @@ const Headlines = {
objectById: function (id) {
return this.headlines[id];
},
- setCommonClasses: function () {
- App.byId("headlines-frame").removeClassName("cdm");
- App.byId("headlines-frame").removeClassName("normal");
+ setCommonClasses: function (headlines_count) {
+ const container = App.byId("headlines-frame");
- App.byId("headlines-frame").addClassName(App.isCombinedMode() ? "cdm" : "normal");
+ container.removeClassName("cdm");
+ container.removeClassName("normal");
+
+ container.addClassName(App.isCombinedMode() ? "cdm" : "normal");
+ container.setAttribute("data-enable-grid", App.getInitParam("cdm_enable_grid") ? "true" : "false");
+ container.setAttribute("data-headlines-count", parseInt(headlines_count));
+ container.setAttribute("data-is-cdm", App.isCombinedMode() ? "true" : "false");
+ container.setAttribute("data-is-cdm-expanded", App.getInitParam("cdm_expanded"));
// for floating title because it's placed outside of headlines-frame
App.byId("main").removeClassName("expandable");
@@ -393,7 +412,7 @@ const Headlines = {
},
renderAgain: function () {
// TODO: wrap headline elements into a knockoutjs model to prevent all this stuff
- Headlines.setCommonClasses();
+ Headlines.setCommonClasses(this.headlines.filter((h) => h.id).length);
App.findAll("#headlines-frame > div[id*=RROW]").forEach((row) => {
const id = row.getAttribute("data-article-id");
@@ -422,11 +441,18 @@ const Headlines = {
this.sticky_header_observer.observe(e)
});
+ App.findAll(".cdm .content").forEach((e) => {
+ this.sticky_content_observer.observe(e)
+ });
+
if (App.getInitParam("cdm_expanded"))
App.findAll("#headlines-frame > div[id*=RROW].cdm").forEach((e) => {
this.unpack_observer.observe(e)
});
+ dijit.byId('main').resize();
+
+ PluginHost.run(PluginHost.HOOK_HEADLINES_RENDERED);
},
render: function (headlines, hl) {
let row = null;
@@ -494,9 +520,10 @@ const Headlines = {
<span class="updated" title="${hl.imported}">${hl.updated}</span>
<div class="right">
+ <i class="material-icons icon-grid-span" title="${__("Span all columns")}" onclick="Article.cdmToggleGridSpan(${hl.id})">fullscreen</i>
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
- <span style="cursor : pointer" title="${App.escapeHtml(hl.feed_title)}" onclick="Feeds.open({feed:${hl.feed_id}})">
+ <span class="icon-feed" title="${App.escapeHtml(hl.feed_title)}" onclick="Feeds.open({feed:${hl.feed_id}})">
${Feeds.renderIcon(hl.feed_id, hl.has_icon)}
</span>
</div>
@@ -506,7 +533,9 @@ const Headlines = {
<div class="content" onclick="return Headlines.click(event, ${hl.id}, true);">
${Article.renderNote(hl.id, hl.note)}
<div class="content-inner" lang="${hl.lang ? hl.lang : 'en'}">
- <img src="${App.getInitParam('icon_indicator_white')}">
+ <div class="text-center text-muted">
+ ${__("Loading, please wait...")}
+ </div>
</div>
<div class="intermediate">
${Article.renderEnclosures(hl.enclosures)}
@@ -560,7 +589,7 @@ const Headlines = {
</div>
<div class="right">
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
- <span onclick="Feeds.open({feed:${hl.feed_id}})" style="cursor : pointer" title="${App.escapeHtml(hl.feed_title)}">${Feeds.renderIcon(hl.feed_id, hl.has_icon)}</span>
+ <span onclick="Feeds.open({feed:${hl.feed_id}})" class="icon-feed" title="${App.escapeHtml(hl.feed_title)}">${Feeds.renderIcon(hl.feed_id, hl.has_icon)}</span>
</div>
</div>
`;
@@ -614,7 +643,7 @@ const Headlines = {
</span>
<span class='right'>
<span id='selected_prompt'></span>
- <div dojoType='fox.form.DropDownButton' title='"${__('Select articles')}'>
+ <div class='select-articles-dropdown' dojoType='fox.form.DropDownButton' title='"${__('Select articles')}'>
<span>${__("Select...")}</span>
<div dojoType='dijit.Menu' style='display: none;'>
<div dojoType='dijit.MenuItem' onclick='Headlines.select("all")'>${__('All')}</div>
@@ -671,11 +700,15 @@ const Headlines = {
console.log('infscroll_disabled=', Feeds.infscroll_disabled);
// also called in renderAgain() after view mode switch
- Headlines.setCommonClasses();
+ Headlines.setCommonClasses(headlines_count);
+ /** TODO: remove @deprecated */
App.byId("headlines-frame").setAttribute("is-vfeed",
reply['headlines']['is_vfeed'] ? 1 : 0);
+ App.byId("headlines-frame").setAttribute("data-is-vfeed",
+ reply['headlines']['is_vfeed'] ? "true" : "false");
+
Article.setActive(0);
try {
@@ -716,6 +749,9 @@ const Headlines = {
hsp.id = "headlines-spacer";
}
+ // clear out hsp contents in case there's a power-hungry svg icon rotating there
+ hsp.innerHTML = "";
+
dijit.byId('headlines-frame').domNode.appendChild(hsp);
this.initHeadlinesMenu();
@@ -767,6 +803,9 @@ const Headlines = {
hsp.id = "headlines-spacer";
}
+ // clear out hsp contents in case there's a power-hungry svg icon rotating there
+ hsp.innerHTML = "";
+
c.domNode.appendChild(hsp);
this.initHeadlinesMenu();
@@ -799,6 +838,10 @@ const Headlines = {
this.sticky_header_observer.observe(e)
});
+ App.findAll(".cdm .content").forEach((e) => {
+ this.sticky_content_observer.observe(e)
+ });
+
if (App.getInitParam("cdm_expanded"))
App.findAll("#headlines-frame > div[id*=RROW].cdm").forEach((e) => {
this.unpack_observer.observe(e)
@@ -816,6 +859,10 @@ const Headlines = {
// unpack visible articles, fill buffer more, etc
this.scrollHandler();
+ dijit.byId('main').resize();
+
+ PluginHost.run(PluginHost.HOOK_HEADLINES_RENDERED);
+
Notify.close();
},
reverse: function () {
diff --git a/js/PluginHost.js b/js/PluginHost.js
index caee79d58..deb7c0645 100644
--- a/js/PluginHost.js
+++ b/js/PluginHost.js
@@ -17,6 +17,10 @@ const PluginHost = {
HOOK_HEADLINE_RENDERED: 12,
HOOK_COUNTERS_RECEIVED: 13,
HOOK_COUNTERS_PROCESSED: 14,
+ HOOK_HEADLINE_MUTATIONS: 15,
+ HOOK_HEADLINE_MUTATIONS_SYNCED: 16,
+ HOOK_HEADLINES_RENDERED: 17,
+ HOOK_HEADLINES_SCROLL_HANDLER: 18,
hooks: [],
register: function (name, callback) {
if (typeof(this.hooks[name]) == 'undefined')
@@ -25,7 +29,7 @@ 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 (let i = 0; i < this.hooks[name].length; i++) {
diff --git a/js/PrefHelpers.js b/js/PrefHelpers.js
index 3f738aa95..361b653b6 100644
--- a/js/PrefHelpers.js
+++ b/js/PrefHelpers.js
@@ -368,15 +368,16 @@ const Helpers = {
// only user-enabled actually counts in the checkbox when saving because system plugin checkboxes are disabled (see below)
container.innerHTML += `
- <li data-row-value="${App.escapeHtml(plugin.name)}" data-plugin-local="${plugin.is_local}" data-plugin-name="${App.escapeHtml(plugin.name)}" title="${plugin.is_system ? __("System plugins are enabled using global configuration.") : ""}">
+ <li data-row-value="${App.escapeHtml(plugin.name)}" data-plugin-local="${plugin.is_local}"
+ data-plugin-name="${App.escapeHtml(plugin.name)}" title="${plugin.is_system ? __("System plugins are enabled using global configuration.") : ""}">
<label class="checkbox ${plugin.is_system ? "system text-info" : ""}">
${App.FormFields.checkbox_tag("plugins[]", plugin.user_enabled || plugin.system_enabled, plugin.name,
{disabled: plugin.is_system})}</div>
<span class='name'>${plugin.name}:</span>
+ <span class="description ${plugin.is_system ? "text-info" : ""}">
+ ${plugin.description}
+ </span>
</label>
- <div class="description ${plugin.is_system ? "text-info" : ""}">
- ${plugin.description}
- </div>
<div class='actions'>
${plugin.is_system ?
App.FormFields.button_tag(App.FormFields.icon("security"), "",
@@ -510,12 +511,10 @@ const Helpers = {
search: function() {
this.search_query = this.attr('value').search.toLowerCase();
- if ('requestIdleCallback' in window)
- window.requestIdleCallback(() => {
- this.render_contents();
- });
- else
+ window.requestIdleCallback(() => {
this.render_contents();
+ });
+
},
render_contents: function() {
const container = dialog.domNode.querySelector(".contents");
@@ -809,63 +808,5 @@ const Helpers = {
console.log("export");
window.open("backend.php?op=opml&method=export&" + dojo.formToQuery("opmlExportForm"));
},
- publish: function() {
- Notify.progress("Loading, please wait...", true);
-
- xhr.json("backend.php", {op: "pref-feeds", method: "getOPMLKey"}, (reply) => {
- try {
- const dialog = new fox.SingleUseDialog({
- title: __("Public OPML URL"),
- regenOPMLKey: function() {
- if (confirm(__("Replace current OPML publishing address with a new one?"))) {
- Notify.progress("Trying to change address...", true);
-
- xhr.json("backend.php", {op: "pref-feeds", method: "regenOPMLKey"}, (reply) => {
- if (reply) {
- const new_link = reply.link;
- const target = this.domNode.querySelector('.generated_url');
-
- if (new_link && target) {
- target.href = new_link;
- target.innerHTML = new_link;
-
- Notify.close();
-
- } else {
- Notify.error("Could not change feed URL.");
- }
- }
- });
- }
- return false;
- },
- content: `
- <header>${__("Your Public OPML URL is:")}</header>
- <section>
- <div class='panel text-center'>
- <a class='generated_url' href="${App.escapeHtml(reply.link)}" target='_blank'>${App.escapeHtml(reply.link)}</a>
- </div>
- </section>
- <footer class='text-center'>
- <button dojoType='dijit.form.Button' onclick="return App.dialogOf(this).regenOPMLKey()">
- ${App.FormFields.icon("refresh")}
- ${__('Generate new URL')}
- </button>
- <button dojoType='dijit.form.Button' type='submit' class='alt-primary'>
- ${__('Close this window')}
- </button>
- </footer>
- `
- });
-
- dialog.show();
-
- Notify.close();
-
- } catch (e) {
- App.Error.report(e);
- }
- });
- },
}
};
diff --git a/js/common.js b/js/common.js
index 1f8318862..1299a0c64 100755
--- a/js/common.js
+++ b/js/common.js
@@ -432,7 +432,7 @@ const Notify = {
break;
case this.KIND_PROGRESS:
notify.addClassName("notify_progress");
- icon = App.getInitParam("icon_indicator_white")
+ icon = App.getInitParam("icon_oval")
break;
default:
icon = "notifications";
diff --git a/phpstan.neon b/phpstan.neon
index 8fe36c8b4..818f99577 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -5,7 +5,8 @@ parameters:
- '#Constant.*\b(SUBSTRING_FOR_DATE|SCHEMA_VERSION|SELF_USER_AGENT|LABEL_BASE_INDEX|PLUGIN_FEED_BASE_INDEX)\b.*not found#'
- '#Comparison operation ">" between int<1, max> and 0 is always true.#'
- '#Access to an undefined property DOMNode::\$tagName.#'
- - '#Call to an undefined method DOMNode::(get|remove|set)Attribute\(\).#'
+ - '#Call to an undefined method DOMNode::(get|remove|set|has)Attribute\(\).#'
+ - '#Call to an undefined method DOMNode::(getElementsByTagName)\(\).#'
- '#PHPDoc tag @param has invalid value#'
- message: '##'
paths:
diff --git a/plugins/af_redditimgur/init.php b/plugins/af_redditimgur/init.php
index 9fd93dde4..35eb40950 100755
--- a/plugins/af_redditimgur/init.php
+++ b/plugins/af_redditimgur/init.php
@@ -132,7 +132,7 @@ class Af_RedditImgur extends Plugin {
if (!empty($media["s"]["u"])) {
$media_url = htmlspecialchars_decode($media["s"]["u"]);
- Debug::log("found media_metadata (gallery): $media_url", Debug::$LOG_VERBOSE);
+ Debug::log("found media_metadata (gallery): $media_url", Debug::LOG_VERBOSE);
if ($media_url) {
$this->handle_as_image($doc, $anchor, $media_url);
@@ -153,7 +153,7 @@ class Af_RedditImgur extends Plugin {
else
$poster_url = "";
- Debug::log("found stream fallback_url: $stream_url / poster $poster_url", Debug::$LOG_VERBOSE);
+ Debug::log("found stream fallback_url: $stream_url / poster $poster_url", Debug::LOG_VERBOSE);
$this->handle_as_video($doc, $anchor, $stream_url, $poster_url);
}
@@ -172,12 +172,12 @@ class Af_RedditImgur extends Plugin {
else
$poster_url = "";
- Debug::log("found hosted video url: $media_url / poster $poster_url, looking up fallback url...", Debug::$LOG_VERBOSE);
+ Debug::log("found hosted video url: $media_url / poster $poster_url, looking up fallback url...", Debug::LOG_VERBOSE);
$fallback_url = $data["media"]["reddit_video"]["fallback_url"];
if ($fallback_url) {
- Debug::log("found video fallback_url: $fallback_url", Debug::$LOG_VERBOSE);
+ Debug::log("found video fallback_url: $fallback_url", Debug::LOG_VERBOSE);
$this->handle_as_video($doc, $anchor, $fallback_url, $poster_url);
$found = 1;
@@ -192,7 +192,7 @@ class Af_RedditImgur extends Plugin {
else
$poster_url = "";
- Debug::log("found video url: $media_url / poster $poster_url", Debug::$LOG_VERBOSE);
+ Debug::log("found video url: $media_url / poster $poster_url", Debug::LOG_VERBOSE);
$this->handle_as_video($doc, $anchor, $media_url, $poster_url);
$found = 1;
@@ -201,7 +201,7 @@ class Af_RedditImgur extends Plugin {
if (!$found && $post_hint == "image") {
$media_url = $data["url"];
- Debug::log("found image url: $media_url", Debug::$LOG_VERBOSE);
+ Debug::log("found image url: $media_url", Debug::LOG_VERBOSE);
$this->handle_as_image($doc, $anchor, $media_url);
$found = 1;
@@ -215,12 +215,12 @@ class Af_RedditImgur extends Plugin {
if ($media_url) {
if ($post_hint == "self") {
- Debug::log("found preview image url: $media_url (link: $target_url)", Debug::$LOG_VERBOSE);
+ Debug::log("found preview image url: $media_url (link: $target_url)", Debug::LOG_VERBOSE);
$this->handle_as_image($doc, $anchor, $media_url, $target_url);
$found = 1;
} else { // gonna use this later if nothing is found using generic link processing
- Debug::log("found fallback preview image url: $media_url (link: $target_url);", Debug::$LOG_VERBOSE);
+ Debug::log("found fallback preview image url: $media_url (link: $target_url);", Debug::LOG_VERBOSE);
array_push($this->fallback_preview_urls, $media_url);
}
}
@@ -244,14 +244,15 @@ class Af_RedditImgur extends Plugin {
$post_is_nsfw = false;
$num_comments = 0;
$score = 0;
+ $link_flairs = [];
$apply_nsfw_tags = FeedItem_Common::normalize_categories($this->host->get_array($this, "apply_nsfw_tags", []));
- // embed before reddit <table> post layout
+ // embed anchor element, before reddit <table> post layout
$anchor = $xpath->query('//body/*')->item(0);
// deal with json-provided media content first
if ($article["link"] && $anchor) {
- Debug::log("JSON: requesting from URL: " . $article["link"] . "/.json", Debug::$LOG_VERBOSE);
+ Debug::log("JSON: requesting from URL: " . $article["link"] . "/.json", Debug::LOG_VERBOSE);
$tmp = UrlHelper::fetch($article["link"] . "/.json");
@@ -262,7 +263,7 @@ class Af_RedditImgur extends Plugin {
$json = json_decode($tmp, true);
if ($json) {
- Debug::log("JSON: processing media elements...", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: processing media elements...", Debug::LOG_EXTENDED);
if ($this->dump_json_data) print_r($json);
@@ -275,13 +276,17 @@ class Af_RedditImgur extends Plugin {
$score += $data['score'] ?? 0;
$num_comments += $data["num_comments"] ?? 0;
+ if (!empty($data["link_flair_text"])) {
+ array_push($link_flairs, $data["link_flair_text"]);
+ }
+
if ($over_18) {
- Debug::log("JSON: post is NSFW", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: post is NSFW", Debug::LOG_EXTENDED);
$post_is_nsfw = true;
}
if (isset($data["crosspost_parent_list"])) {
- Debug::log("JSON: processing child crosspost_parent_list", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: processing child crosspost_parent_list", Debug::LOG_EXTENDED);
foreach ($data["crosspost_parent_list"] as $parent) {
if ($this->process_post_media($parent, $doc, $xpath, $anchor)) {
@@ -292,7 +297,7 @@ class Af_RedditImgur extends Plugin {
}
}
- Debug::log("JSON: processing child data element...", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: processing child data element...", Debug::LOG_EXTENDED);
if (!$found && $this->process_post_media($data, $doc, $xpath, $anchor)) {
$found = 1;
@@ -302,28 +307,32 @@ class Af_RedditImgur extends Plugin {
}
}
} else {
- Debug::log("JSON: failed to parse received data.", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: failed to parse received data.", Debug::LOG_EXTENDED);
}
} else {
if (!$tmp) {
- Debug::log("JSON: failed to fetch post:" . UrlHelper::$fetch_last_error, Debug::$LOG_EXTENDED);
+ Debug::log("JSON: failed to fetch post:" . UrlHelper::$fetch_last_error, Debug::LOG_EXTENDED);
}
}
} else if (!$anchor) {
- Debug::log("JSON: anchor element not found, unable to embed", Debug::$LOG_EXTENDED);
+ Debug::log("JSON: anchor element not found, unable to embed", Debug::LOG_EXTENDED);
}
if ($post_is_nsfw && count($apply_nsfw_tags) > 0) {
$article["tags"] = array_merge($article["tags"], $apply_nsfw_tags);
}
+ if (count($link_flairs) > 0) {
+ $article["tags"] = array_merge($article["tags"], FeedItem_Common::normalize_categories($link_flairs));
+ }
+
$article["num_comments"] = $num_comments;
if ($import_score && $score > 0)
$article["score_modifier"] = ($article["score_modifier"] ?? 0) + ($score > $max_score ? $max_score : $score);
if ($found) {
- Debug::log("JSON: found media data, skipping further processing of content", Debug::$LOG_VERBOSE);
+ Debug::log("JSON: found media data, skipping further processing of content", Debug::LOG_VERBOSE);
$this->remove_post_thumbnail($doc, $xpath);
return true;
}
@@ -337,14 +346,14 @@ class Af_RedditImgur extends Plugin {
/* skip links going back to reddit (and any other blacklisted stuff) */
if (!$found && $this->is_blacklisted($entry_href, ["reddit.com"])) {
- Debug::log("BODY: domain of $entry_href is blacklisted, skipping", Debug::$LOG_EXTENDED);
+ Debug::log("BODY: domain of $entry_href is blacklisted, skipping", Debug::LOG_EXTENDED);
continue;
}
- Debug::log("BODY: processing URL: " . $entry_href, Debug::$LOG_VERBOSE);
+ Debug::log("BODY: processing URL: " . $entry_href, Debug::LOG_VERBOSE);
if (!$found && preg_match("/^https?:\/\/twitter.com\/(.*?)\/status\/(.*)/", $entry_href, $matches)) {
- Debug::log("handling as twitter: " . $matches[1] . " " . $matches[2], Debug::$LOG_VERBOSE);
+ Debug::log("handling as twitter: " . $matches[1] . " " . $matches[2], Debug::LOG_VERBOSE);
$oembed_result = UrlHelper::fetch("https://publish.twitter.com/oembed?url=" . urlencode($entry_href));
@@ -376,7 +385,7 @@ class Af_RedditImgur extends Plugin {
if (!$found && preg_match("/https?:\/\/(www\.)?gfycat.com\/([a-z]+)$/i", $entry_href, $matches)) {
- Debug::log("Handling as Gfycat", Debug::$LOG_VERBOSE);
+ Debug::log("Handling as Gfycat", Debug::LOG_VERBOSE);
$source_stream = 'https://giant.gfycat.com/' . $matches[2] . '.mp4';
$poster_url = 'https://thumbs.gfycat.com/' . $matches[2] . '-mobile.jpg';
@@ -391,14 +400,14 @@ class Af_RedditImgur extends Plugin {
// imgur .gif -> .gifv
if (!$found && preg_match("/i\.imgur\.com\/(.*?)\.gif$/i", $entry_href)) {
- Debug::log("Handling as imgur gif (->gifv)", Debug::$LOG_VERBOSE);
+ Debug::log("Handling as imgur gif (->gifv)", Debug::LOG_VERBOSE);
$entry->setAttribute("href",
str_replace(".gif", ".gifv", $entry_href));
}
if (!$found && preg_match("/\.(gifv|mp4)$/i", $entry_href)) {
- Debug::log("Handling as imgur gifv", Debug::$LOG_VERBOSE);
+ Debug::log("Handling as imgur gifv", Debug::LOG_VERBOSE);
$source_stream = str_replace(".gifv", ".mp4", $entry_href);
@@ -421,7 +430,7 @@ class Af_RedditImgur extends Plugin {
$vid_id = $matches[1];
- Debug::log("Handling as youtube: $vid_id", Debug::$LOG_VERBOSE);
+ Debug::log("Handling as youtube: $vid_id", Debug::LOG_VERBOSE);
$iframe = $doc->createElement("iframe");
$iframe->setAttribute("class", "youtube-player");
@@ -432,9 +441,15 @@ class Af_RedditImgur extends Plugin {
$iframe->setAttribute("allowfullscreen", "1");
$iframe->setAttribute("frameborder", "0");
- $br = $doc->createElement('br');
- $entry->parentNode->insertBefore($iframe, $entry);
- $entry->parentNode->insertBefore($br, $entry);
+ //$br = $doc->createElement('br');
+ //$entry->parentNode->insertBefore($iframe, $entry);
+ //$entry->parentNode->insertBefore($br, $entry);
+
+ // reparent generated iframe because it doesn't scale well inside <td>
+ if ($anchor)
+ $anchor->parentNode->insertBefore($iframe, $anchor);
+ else
+ $entry->parentNode->insertBefore($iframe, $entry);
$found = true;
}
@@ -443,7 +458,7 @@ class Af_RedditImgur extends Plugin {
/* mb_strpos($entry_href, "i.reddituploads.com") !== false || */
mb_strpos($this->get_content_type($entry_href), "image/") !== false)) {
- Debug::log("Handling as a picture", Debug::$LOG_VERBOSE);
+ Debug::log("Handling as a picture", Debug::LOG_VERBOSE);
$img = $doc->createElement('img');
$img->setAttribute("src", $entry_href);
@@ -458,7 +473,7 @@ class Af_RedditImgur extends Plugin {
// imgur via link rel="image_src" href="..."
if (!$found && preg_match("/imgur/", $entry_href)) {
- Debug::log("handling as imgur page/whatever", Debug::$LOG_VERBOSE);
+ Debug::log("handling as imgur page/whatever", Debug::LOG_VERBOSE);
$content = UrlHelper::fetch(["url" => $entry_href,
"http_accept" => "text/*"]);
@@ -490,7 +505,7 @@ class Af_RedditImgur extends Plugin {
if (!$found && preg_match("/^https?:\/\/gyazo\.com\/([^\.\/]+$)/", $entry_href, $matches)) {
$img_id = $matches[1];
- Debug::log("handling as gyazo: $img_id", Debug::$LOG_VERBOSE);
+ Debug::log("handling as gyazo: $img_id", Debug::LOG_VERBOSE);
$img = $doc->createElement('img');
$img->setAttribute("src", "https://i.gyazo.com/$img_id.jpg");
@@ -504,7 +519,7 @@ class Af_RedditImgur extends Plugin {
// let's try meta properties
if (!$found) {
- Debug::log("looking for meta og:image", Debug::$LOG_VERBOSE);
+ Debug::log("looking for meta og:image", Debug::LOG_VERBOSE);
$content = UrlHelper::fetch(["url" => $entry_href,
"http_accept" => "text/*"]);
@@ -555,7 +570,7 @@ class Af_RedditImgur extends Plugin {
}
if (!$found && $anchor && count($this->fallback_preview_urls) > 0) {
- Debug::log("JSON: processing fallback preview urls...", Debug::$LOG_VERBOSE);
+ Debug::log("JSON: processing fallback preview urls...", Debug::LOG_VERBOSE);
foreach ($this->fallback_preview_urls as $media_url) {
$this->handle_as_image($doc, $anchor, $media_url);
@@ -662,7 +677,7 @@ class Af_RedditImgur extends Plugin {
private function handle_as_video($doc, $entry, $source_stream, $poster_url = false) {
- Debug::log("handle_as_video: $source_stream", Debug::$LOG_VERBOSE);
+ Debug::log("handle_as_video: $source_stream", Debug::LOG_VERBOSE);
$video = $doc->createElement('video');
$video->setAttribute("autoplay", "1");
@@ -694,12 +709,13 @@ class Af_RedditImgur extends Plugin {
function testurl() {
- $url = clean($_POST["url"]);
- $article_url = clean($_POST["article_url"]);
+ $url = clean($_POST["url"] ?? "");
+ $article_url = clean($_POST["article_url"] ?? "");
+ $article_id = clean($_POST["article_id"] ?? "");
$this->dump_json_data = true;
- if (!$url && !$article_url) {
+ if (!$url && !$article_url && !$article_id) {
header("Content-type: text/html");
?>
<style type="text/css">
@@ -711,11 +727,16 @@ class Af_RedditImgur extends Plugin {
<input type="hidden" name="method" value="testurl">
<input type="hidden" name="plugin" value="af_redditimgur">
<fieldset>
- <label>URL:</label>
+ <label>Test URL:</label>
<input name="url" size="100" value="<?= htmlspecialchars($url) ?>"></input>
</fieldset>
+ <hr/>
<fieldset>
- <label>Article URL:</label>
+ <label>Article ID:</label>
+ <input name="article_id" size="10" value="<?= htmlspecialchars($article_id) ?>"></input>
+ </fieldset>
+ <fieldset>
+ <label>or Article URL:</label>
<input name="article_url" size="100" value="<?= htmlspecialchars($article_url) ?>"></input>
</fieldset>
<fieldset>
@@ -729,28 +750,51 @@ class Af_RedditImgur extends Plugin {
header("Content-type: text/plain");
Debug::set_enabled(true);
- Debug::set_loglevel(Debug::$LOG_EXTENDED);
+ Debug::set_loglevel(Debug::LOG_EXTENDED);
+
+ if ($article_id) {
+ $stored_article = ORM::for_table('ttrss_entries')
+ ->table_alias('e')
+ ->join('ttrss_user_entries', [ 'ref_id', '=', 'e.id'], 'ue')
+ ->where('ue.owner_uid', $_SESSION['uid'])
+ ->find_one($article_id);
+
+ if (!$stored_article) {
+ Debug::log("Article not found: $article_id", Debug::LOG_VERBOSE);
+ return;
+ }
+
+ $article = [
+ "link" => $stored_article->link,
+ "content" => $stored_article->content,
+ "tags" => explode(",", $stored_article->tag_cache)
+ ];
- Debug::log("URL: $url", Debug::$LOG_VERBOSE);
+ } else {
+ $article = [
+ "link" => $article_url,
+ "content" => "<html><body><table><tr><td><a href=\"$url\">[link]</a></td></tr></table></body>",
+ "tags" => []];
+ }
$doc = new DOMDocument();
- @$doc->loadHTML("<html><body><table><tr><td><a href=\"$url\">[link]</a></td></tr></table></body>");
+ @$doc->loadHTML($article["content"]);
$xpath = new DOMXPath($doc);
- $article = ["link" => $article_url, "tags" => []];
-
$found = $this->inline_stuff($article, $doc, $xpath);
- Debug::log("Inline result: $found", Debug::$LOG_VERBOSE);
+ Debug::log("Inline result: $found", Debug::LOG_VERBOSE);
+
+ print_r($article);
if (!$found) {
- Debug::log("Readability result:", Debug::$LOG_VERBOSE);
+ Debug::log("Readability result:", Debug::LOG_VERBOSE);
$article = $this->readability([], $url, $doc, $xpath);
print_r($article);
} else {
- Debug::log("Resulting HTML:", Debug::$LOG_VERBOSE);
+ Debug::log("Resulting HTML:", Debug::LOG_VERBOSE);
print $doc->saveHTML();
}
diff --git a/plugins/af_zz_vidmute/init.js b/plugins/af_zz_vidmute/init.js
index b8be8cecd..36914cbf0 100644
--- a/plugins/af_zz_vidmute/init.js
+++ b/plugins/af_zz_vidmute/init.js
@@ -1,24 +1,18 @@
+/* global require, PluginHost */
+
require(['dojo/_base/kernel', 'dojo/ready'], function (dojo, ready) {
+ function mute(row) {
+ [...row.querySelectorAll("video")].forEach((vid) => { vid.muted = true; });
+ }
+
ready(function () {
PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED_CDM, function (row) {
- if (row) {
-
- row.querySelectorAll("video").forEach(function (v) {
- v.muted = true;
- });
- }
-
+ mute(row);
return true;
});
PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED, function (row) {
- if (row) {
-
- row.querySelectorAll("video").forEach(function (v) {
- v.muted = true;
- });
- }
-
+ mute(row);
return true;
});
});
diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php
index 9155f8165..3f5a2e977 100644
--- a/plugins/auth_internal/init.php
+++ b/plugins/auth_internal/init.php
@@ -50,7 +50,7 @@ class Auth_Internal extends Auth_Base {
return false;
} */
- if (UserHelper::check_otp($user_id, $otp))
+ if ($this->check_password($user_id, $password) && UserHelper::check_otp($user_id, $otp))
return $user_id;
else
return false;
@@ -109,7 +109,7 @@ class Auth_Internal extends Auth_Base {
<?= \Controls\hidden_tag("op", "login") ?>
<fieldset>
- <label><?= __("Please enter your one time password:") ?></label>
+ <label><?= __("Please enter verification code (OTP):") ?></label>
<input id="otp" dojoType="dijit.form.ValidationTextBox" required="1" autocomplete="off" size="6" name="otp" value=""/>
<?= \Controls\submit_tag(__("Continue")) ?>
</fieldset>
@@ -150,6 +150,32 @@ class Auth_Internal extends Auth_Base {
if ($user) {
+ // don't throttle app passwords
+ if (!$service && get_schema_version() >= 145) {
+
+ if ($user->last_auth_attempt) {
+ $last_auth_attempt = strtotime($user->last_auth_attempt);
+
+ if ($last_auth_attempt && time() - $last_auth_attempt < Config::get(Config::AUTH_MIN_INTERVAL)) {
+ Logger::log(E_USER_NOTICE, "Too many authentication attempts for {$user->login}, throttled.");
+
+ // start an empty session to deliver login error message
+ if (session_status() != PHP_SESSION_ACTIVE)
+ session_start();
+
+ $_SESSION["login_error_msg"] = __("Too many authentication attempts, throttled.");
+
+ $user->last_auth_attempt = Db::NOW();
+ $user->save();
+
+ return false;
+ }
+ }
+
+ $user->last_auth_attempt = Db::NOW();
+ $user->save();
+ }
+
$salt = $user['salt'] ?? "";
$login = $user['login'];
$pwd_hash = $user['pwd_hash'];
diff --git a/plugins/nsfw/init.js b/plugins/nsfw/init.js
deleted file mode 100644
index 71fe4747b..000000000
--- a/plugins/nsfw/init.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/* global Plugins */
-
-Plugins.NSFW = {
- toggle: function(elem) {
- elem = elem.domNode || elem;
-
- const content = elem.closest(".nsfw-wrapper").querySelector('.nsfw-content');
-
- // we can't use .toggle() here because this script could be invoked by the api client
- // so it's back to vanilla js
-
- if (content.style.display == 'none')
- content.style.display = '';
- else
- content.style.display = 'none';
- }
-}
-
diff --git a/plugins/nsfw/init.php b/plugins/nsfw/init.php
index 8ace94b51..fc38fef71 100644
--- a/plugins/nsfw/init.php
+++ b/plugins/nsfw/init.php
@@ -20,10 +20,6 @@ class NSFW extends Plugin {
}
- function get_js() {
- return file_get_contents(__DIR__ . "/init.js");
- }
-
function hook_article_image($enclosures, $content, $site_url, $article) {
$tags = explode(",", $this->host->get($this, "tags"));
$article_tags = $article["tags"];
@@ -35,27 +31,28 @@ class NSFW extends Plugin {
}
}
- private function rewrite_contents($article, bool $add_api_js = false) {
+ private function rewrite_contents($article) {
$tags = explode(",", $this->host->get($this, "tags"));
$article_tags = $article["tags"];
if (count(array_intersect($tags, $article_tags)) > 0) {
- $article["content"] = "<div class='nsfw-wrapper'>".
- \Controls\button_tag(__("Not work safe (click to toggle)"), '', ['onclick' => 'Plugins.NSFW.toggle(this)']).
- "<div class='nsfw-content' style='display : none'>".$article["content"]."</div>
- </div>";
-
- if ($add_api_js) {
- $article["content"] .= "<script type='text/javascript'>const Plugins = {}; " . $this->get_js() . "</script>";
- }
+ $article["content"] = "<details class='nsfw'><summary>" . __("Not safe for work (click to toggle)") . "</summary>" . $article["content"] . "</details>";
}
return $article;
}
+ function get_css() {
+ return
+ 'details.nsfw {
+ cursor : pointer;
+ user-select : none;
+ }';
+ }
+
function hook_render_article_api($row) {
$article = isset($row['headline']) ? $row['headline'] : $row['article'];
- return $this->rewrite_contents($article, true);
+ return $this->rewrite_contents($article);
}
function hook_render_article($article) {
diff --git a/plugins/share/init.php b/plugins/share/init.php
index 64a9054eb..195f9df2a 100644
--- a/plugins/share/init.php
+++ b/plugins/share/init.php
@@ -149,6 +149,9 @@ class Share extends Plugin {
$line['content'] = DiskCache::rewrite_urls($line['content']);
+ if (!$og_image)
+ $og_image = Config::get_self_url() . "/images/favicon-512px.png";
+
ob_start();
?>
@@ -180,27 +183,28 @@ class Share extends Plugin {
strip_tags($content_decoded)
)
), 500, "...")) ?>">
- </head>
- <?php if ($og_image) { ?>
- <meta property='og:image' content="<?= htmlspecialchars($og_image) ?>">
- <?php } ?>
+ <?php if ($og_image) { ?>
+ <meta property='og:image' content="<?= htmlspecialchars($og_image) ?>">
+ <?php } ?>
+ </head>
<body class='flat ttrss_utility ttrss_zoom css_loading'>
<div class='container'>
- <?php if (!empty($line["link"])) { ?>
- <h1>
- <a target='_blank' rel='noopener noreferrer'
- href="<?= htmlspecialchars($line["link"]) ?>"><?= htmlspecialchars($line["title"]) ?></a>
- </h1>
- <?php } else { ?>
- <h1><?= $line["title"] ?></h1>
- <?php } ?>
-
<div class='content post'>
<div class='header'>
<div class='row'>
+ <?php if (!empty($line["link"])) { ?>
+ <h1>
+ <a rel='noopener noreferrer'
+ href="<?= htmlspecialchars($line["link"]) ?>"><?= htmlspecialchars($line["title"]) ?></a>
+ </h1>
+ <?php } else { ?>
+ <h1><?= $line["title"] ?></h1>
+ <?php } ?>
+ </div>
+ <div class='row'>
<div><?= $line['author'] ?></div>
<div><?= $parsed_updated ?></div>
</div>
diff --git a/plugins/shorten_expanded/init.css b/plugins/shorten_expanded/init.css
index 0966aa1f9..e0a209903 100644
--- a/plugins/shorten_expanded/init.css
+++ b/plugins/shorten_expanded/init.css
@@ -1,7 +1,8 @@
.content-shrink-wrap {
overflow : hidden;
text-overflow: ellipsis;
- height : 800px;
+ height : 80vh;
+ margin-bottom : 8px;
}
.expand-prompt {
diff --git a/plugins/shorten_expanded/init.js b/plugins/shorten_expanded/init.js
index 0abc8c129..85d75d313 100644
--- a/plugins/shorten_expanded/init.js
+++ b/plugins/shorten_expanded/init.js
@@ -1,10 +1,55 @@
-/* global Plugins, __, require, PluginHost */
-
-const _shorten_expanded_threshold = 1.5; //window heights
+/* global Plugins, __, require, PluginHost, App, dojo */
Plugins.Shorten_Expanded = {
+ threshold: 1.5, // of window height
+ observer: new ResizeObserver((entries) => {
+ entries.forEach((entry) => {
+ const row = entry.target;
+
+ Plugins.Shorten_Expanded.shorten_if_needed(row);
+ });
+ }),
+ shorten_if_needed: function(row) {
+
+ const content = row.querySelector(".content");
+ const content_inner = row.querySelector(".content-inner");
+
+ //console.log('shorten_expanded', row.id, content.offsetHeight, 'vs', this.threshold * window.innerHeight);
+
+ if (content && content_inner && !row.hasAttribute('data-already-shortened') && content.offsetHeight >= this.threshold * window.innerHeight) {
+
+ row.setAttribute('data-already-shortened', true);
+
+ const attachments = row.querySelector(".attachments-inline"); // optional
+
+ content_inner.innerHTML = `
+ <div class="content-shrink-wrap">
+ ${content_inner.innerHTML}
+ ${attachments ? attachments.innerHTML : ''}
+ </div>
+ <button dojoType="dijit.form.Button" class="alt-info expand-prompt" onclick="return Plugins.Shorten_Expanded.expand('${row.id}')" href="#">
+ ${App.FormFields.icon('add')}
+ ${__("Expand article")}
+ </button>`;
+
+ if (attachments)
+ attachments.innerHTML = "";
+
+ dojo.parser.parse(content_inner);
+
+ return true;
+ }
+ return false;
+ },
+ process_row: function(row) {
+
+ if (this.shorten_if_needed(row))
+ return;
+
+ this.observer.observe(row);
+ },
expand: function(id) {
- const row = $(id);
+ const row = App.byId(id);
if (row) {
const content = row.querySelector(".content-shrink-wrap");
@@ -21,33 +66,7 @@ Plugins.Shorten_Expanded = {
require(['dojo/_base/kernel', 'dojo/ready'], function (dojo, ready) {
ready(function() {
PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED_CDM, function(row) {
- window.setTimeout(function() {
- if (row) {
-
- const content = row.querySelector(".content-inner");
-
- //console.log('shorten', row.offsetHeight, 'vs', _shorten_expanded_threshold * window.innerHeight);
-
- if (content && row.offsetHeight >= _shorten_expanded_threshold * window.innerHeight) {
-
- const attachments = row.querySelector(".attachments-inline"); // optional
-
- content.innerHTML = `
- <div class="content-shrink-wrap">
- ${content.innerHTML}
- ${attachments ? attachments.innerHTML : ''}
- </div>
- <button dojoType="dijit.form.Button" class="alt-info expand-prompt" onclick="return Plugins.Shorten_Expanded.expand('${row.id}')" href="#">
- ${__("Click to expand article")}</button>`;
-
- if (attachments)
- attachments.innerHTML = "";
-
- dojo.parser.parse(content);
- }
- }
- }, 150);
-
+ Plugins.Shorten_Expanded.process_row(row);
return true;
});
});
diff --git a/plugins/shorten_expanded/init.php b/plugins/shorten_expanded/init.php
index 9673f581b..c097f1a0d 100644
--- a/plugins/shorten_expanded/init.php
+++ b/plugins/shorten_expanded/init.php
@@ -10,22 +10,6 @@ class Shorten_Expanded extends Plugin {
function init($host) {
$this->host = $host;
-
- $host->add_hook($host::HOOK_SANITIZE, $this);
- }
-
- // native lazy loading messes with plugin height calculation because images get loaded
- // after headline is actually rendered (off screen) so we force disable it
- function hook_sanitize($doc) {
- $xpath = new DOMXPath($doc);
-
- $entries = $xpath->query('(//*[@loading="lazy"])');
-
- foreach ($entries as $entry) {
- $entry->removeAttribute("loading");
- }
-
- return $doc;
}
function get_css() {
diff --git a/prefs.php b/prefs.php
index 3f6eb47c6..14820f707 100644
--- a/prefs.php
+++ b/prefs.php
@@ -27,9 +27,7 @@
}
} ?>
- <?php if (theme_exists(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))) {
- echo stylesheet_tag(get_theme_path(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET)));
- } ?>
+ <?= Config::get_override_links() ?>
<script type="text/javascript">
const __csrf_token = "<?= $_SESSION["csrf_token"]; ?>";
@@ -95,11 +93,24 @@
}
</style>
+ <noscript>
+ <style type="text/css">
+ body.css_loading noscript {
+ display : block;
+ margin : 16px;
+ }
+ </style>
+
+ <?= stylesheet_tag("themes/light.css") ?>
+ </noscript>
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body class="flat ttrss_main ttrss_prefs css_loading">
+<noscript class="alert alert-error"><?= ('Javascript is disabled. Please enable it.') ?></noscript>
+
<div id="notify" class="notify"></div>
<div id="cmdline" style="display : none"></div>
@@ -109,7 +120,6 @@
<div dojoType="dijit.ProgressBar" places="0" style="width : 300px" id="loading_bar"
progress="0" maximum="100">
</div>
- <noscript><br/><?php print_error('Javascript is disabled. Please enable it.') ?></noscript>
</div>
</div>
diff --git a/sql/mysql/migrations/145.sql b/sql/mysql/migrations/145.sql
new file mode 100644
index 000000000..b49eccafc
--- /dev/null
+++ b/sql/mysql/migrations/145.sql
@@ -0,0 +1,2 @@
+alter table ttrss_users add column last_auth_attempt datetime;
+alter table ttrss_users alter column last_auth_attempt set default null;
diff --git a/sql/mysql/schema.sql b/sql/mysql/schema.sql
index 7ecaff32b..d8e6e270a 100644
--- a/sql/mysql/schema.sql
+++ b/sql/mysql/schema.sql
@@ -54,7 +54,8 @@ create table ttrss_users (id integer primary key not null auto_increment,
twitter_oauth longtext default null,
otp_enabled boolean not null default false,
otp_secret varchar(250) default null,
- resetpass_token varchar(250) default null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
+ resetpass_token varchar(250) default null,
+ last_auth_attempt datetime default null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
insert into ttrss_users (login,pwd_hash,access_level) values ('admin',
'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', 10);
diff --git a/sql/pgsql/migrations/145.sql b/sql/pgsql/migrations/145.sql
new file mode 100644
index 000000000..754d06963
--- /dev/null
+++ b/sql/pgsql/migrations/145.sql
@@ -0,0 +1,2 @@
+alter table ttrss_users add column last_auth_attempt timestamp;
+alter table ttrss_users alter column last_auth_attempt set default null;
diff --git a/sql/pgsql/schema.sql b/sql/pgsql/schema.sql
index 6130b633c..50bf375f2 100644
--- a/sql/pgsql/schema.sql
+++ b/sql/pgsql/schema.sql
@@ -52,6 +52,7 @@ create table ttrss_users (id serial not null primary key,
otp_enabled boolean not null default false,
otp_secret varchar(250) default null,
resetpass_token varchar(250) default null,
+ last_auth_attempt timestamp default null,
created timestamp default null);
insert into ttrss_users (login,pwd_hash,access_level) values ('admin',
diff --git a/themes/compact.css b/themes/compact.css
index 5a3a00cfe..f6adece87 100644
--- a/themes/compact.css
+++ b/themes/compact.css
@@ -11,71 +11,81 @@ body.ttrss_prefs,
}
body.ttrss_main {
background: white;
- color: black;
+ color: #555;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
}
body.ttrss_main :focus {
outline: none;
}
-body.ttrss_main div.post {
- padding: 0px;
+body.ttrss_main .post {
+ padding: 0;
font-size: 13px;
}
-body.ttrss_main div.post div.header {
+body.ttrss_main .post .header {
padding: 5px;
- color: #909090;
- border: 0px solid #ddd;
+ color: #555;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
background: #f5f5f5;
}
-body.ttrss_main div.post div.header .left,
-body.ttrss_main div.post div.header .right {
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
display: flex;
}
-body.ttrss_main div.post div.header .row {
+body.ttrss_main .post .header .row {
display: flex;
margin-bottom: 4px;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
}
-body.ttrss_main div.post div.header .comments {
+body.ttrss_main .post .header .comments {
flex-grow: 2;
}
-body.ttrss_main div.post div.header .date {
+body.ttrss_main .post .header .date {
white-space: nowrap;
}
-body.ttrss_main div.post div.header img,
-body.ttrss_main div.post div.header i.material-icons {
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
margin: 0px 4px;
vertical-align: middle;
color: #777;
}
-body.ttrss_main div.post div.header .title {
+body.ttrss_main .post .header .title {
flex-grow: 2;
font-size: 15px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main div.post div.content {
+body.ttrss_main .post div.content {
padding: 10px;
font-size: 16px;
}
-body.ttrss_main div.post div.content img,
-body.ttrss_main div.post div.content video {
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
border-width: 0px;
max-width: 98%;
height: auto;
}
-body.ttrss_main div.post div.content div.embed-responsive {
+body.ttrss_main .post div.content div.embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-body.ttrss_main div.post div.content div.embed-responsive iframe {
+body.ttrss_main .post div.content div.embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -172,6 +182,11 @@ body.ttrss_main .notify.notify_progress {
border-color: #d7c47a;
background-color: #fff7d5;
}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
body.ttrss_main .notify.notify_info {
border-color: #257aa7;
background-color: #d5ebf6;
@@ -217,6 +232,10 @@ body.ttrss_main .hl .right {
display: flex;
align-items: center;
}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
body.ttrss_main .hl .left i.material-icons,
body.ttrss_main .hl .right i.material-icons {
margin-left: 2px;
@@ -225,25 +244,28 @@ body.ttrss_main .hl .right i.material-icons {
user-select: none;
font-size: 21px;
}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
body.ttrss_main .hl .right i.material-icons {
color: #777;
}
-body.ttrss_main .hl div.title {
+body.ttrss_main .hl .title {
cursor: pointer;
flex-grow: 2;
overflow: hidden;
text-overflow: ellipsis;
}
-body.ttrss_main .hl span.author {
+body.ttrss_main .hl .author {
white-space: nowrap;
color: #555;
font-size: 11px;
font-weight: normal;
}
-body.ttrss_main .hl div.right {
- text-align: right;
-}
-body.ttrss_main .hl span.feed a {
+body.ttrss_main .hl .feed a {
border-radius: 4px;
display: inline-block;
padding: 1px 4px;
@@ -252,29 +274,22 @@ body.ttrss_main .hl span.feed a {
font-weight: normal;
color: #555;
}
-body.ttrss_main .hl span.feed a:hover {
+body.ttrss_main .hl .feed a:hover {
color: #257aa7;
}
-body.ttrss_main .hl span.updated {
+body.ttrss_main .hl .updated {
color: #555;
text-align: right;
font-size: 11px;
padding-left: 10px;
}
-body.ttrss_main .hl span.updated div {
+body.ttrss_main .hl .updated div {
display: inline-block;
}
-body.ttrss_main .hl div.left input {
- margin: 0px 4px;
-}
-body.ttrss_main .hl div.left img,
-body.ttrss_main .hl div.right img {
- margin: 0px 4px;
-}
body.ttrss_main .hl div.title a {
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #555;
}
body.ttrss_main .hl a.title.high,
@@ -287,10 +302,10 @@ body.ttrss_main .hl.vgrlf .feed {
body.ttrss_main .hl.Unread {
background: white;
}
-body.ttrss_main .hl.Unread div.title a {
+body.ttrss_main .hl.Unread .title a {
color: black;
}
-body.ttrss_main .hl.active div.title a {
+body.ttrss_main .hl.active .title a {
color: #257aa7;
/* text-shadow : 1px 1px 2px #fff; */
}
@@ -312,9 +327,6 @@ body.ttrss_main .hl.active span,
body.ttrss_main .hl.Selected span {
color: white;
}
-body.ttrss_main .hl.Grayed {
- color: #909090;
-}
body.ttrss_main #content-insert blockquote,
body.ttrss_main #headlines-frame blockquote,
body.ttrss_main .dijitContentPane blockquote {
@@ -360,7 +372,7 @@ body.ttrss_main .label {
vertical-align: middle;
background-color: #fff7d5;
font-size: 9px;
- color: black;
+ color: #555;
font-weight: normal;
margin-left: 2px;
padding: 2px 4px;
@@ -371,45 +383,6 @@ body.ttrss_main i.pub-pic {
cursor: pointer;
color: #ccc;
}
-body.ttrss_main div.errorExplained {
- border: 1px solid #ddd;
- margin: 5px 0px 5px 0px;
- padding: 5px;
-}
-body.ttrss_main ul.browseFeedList {
- height: 300px;
- width: 100%;
- overflow: auto;
- border-width: 0px 1px 1px 1px;
- border-color: #ddd;
- border-style: solid;
- margin: 0px 0px 5px 0px;
- background-color: white;
- list-style-type: none;
- padding: 0px;
-}
-body.ttrss_main ul.browseFeedList li {
- display: flex;
- align-items: center;
-}
-body.ttrss_main ul.browseFeedList li > * {
- margin: 2px;
-}
-body.ttrss_main .browseFeedList span.subscribers {
- color: #808080;
-}
-body.ttrss_main ul.compact {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main ul.compact li {
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main .noborder {
- border-width: 0px;
-}
body.ttrss_main #overlay {
background: white;
left: 0;
@@ -423,11 +396,6 @@ body.ttrss_main #overlay_inner {
font-weight: bold;
margin: 1em;
}
-body.ttrss_main div.loadingPrompt {
- padding: 1em;
- text-align: center;
- font-weight: bold;
-}
body.ttrss_main div.whiteBox {
margin-left: 1px;
text-align: center;
@@ -436,20 +404,13 @@ body.ttrss_main div.whiteBox {
border: 0px solid #ddd;
border-bottom-width: 1px;
}
-body.ttrss_main div#headlines-frame.wide .title {
- overflow: visible;
- white-space: normal;
-}
-body.ttrss_main div#headlines-frame.wide .hl .feed {
- display: none;
-}
body.ttrss_main .dijitDialog header,
body.ttrss_main .dijitDialog .dlgSec,
body.ttrss_main .dijitDialog .dlgSecHoriz {
font-size: 16px;
font-weight: 600;
color: #555;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_main .dijitDialog section,
body.ttrss_main .dijitDialog .dlgSecCont {
@@ -527,11 +488,6 @@ body.ttrss_main div#cmdline {
padding: 3px 5px 3px 5px;
z-index: 5;
}
-body.ttrss_main #feed_browser_spinner {
- vertical-align: middle;
- height: 18px;
- width: 18px;
-}
body.ttrss_main .exception-contents h3 {
color: red;
}
@@ -540,14 +496,15 @@ body.ttrss_main .exception-contents textarea {
height: 200px;
font-size: 11px;
}
+body.ttrss_main #headlines-wrap-inner,
body.ttrss_main #content-wrap {
- padding: 0px;
- border-width: 0px;
- margin: 0px;
+ padding: 0;
+ border: 0;
+ margin: 0;
}
body.ttrss_main #feeds-holder {
- padding: 0px;
- border: 0px solid #ddd;
+ padding: 0;
+ border: 0 solid #ddd;
overflow: hidden;
background: #f5f5f5;
box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
@@ -557,19 +514,26 @@ body.ttrss_main #feeds-holder #feedTree {
height: 100%;
overflow-x: hidden;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- background: #f5f5f5;
- color: #6f6f6f;
- border-color: #dcdcdc;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- border-color: #257aa7;
- background: #ffffff;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
font-weight: bold;
display: none;
font-size: 9px;
@@ -578,111 +542,215 @@ body.ttrss_main #feeds-holder #feedTree .counterNode {
color: white;
background: #2a89bc;
border-radius: 4px;
- vertical-align: middle;
- float: right;
- position: relative;
line-height: 14px;
margin-right: 8px;
- margin-top: 2px;
min-width: 23px;
height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #f5f5f5;
+ color: #6f6f6f;
+ border-color: #dcdcdc;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #257aa7;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .loadingExpando {
- left: -3px;
- height: 22px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
position: relative;
- top: -3px;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeLabel.Unread {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
font-weight: bold;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow.Error .dijitTreeLabel {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
color: red;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
- border: 1px solid transparent;
-}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRowSelected {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
border-color: #ddd transparent;
background: white;
- color: #333;
+ color: #555;
}
-body.ttrss_main #feeds-holder #feedTree .dijitIcon.feed-icon {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
margin-right: 2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
- color: #555;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #888888;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-archive {
- color: #c77b2e;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-star {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
position: relative;
color: #ffc069;
font-size: 21px;
left: -2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-rss_feed {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
color: #ff7c4b;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-whatshot {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
color: #69C671;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-restore {
- position: relative;
- top: -1px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
font-weight: bold;
color: #257aa7;
}
-body.ttrss_main #headlines-wrap-inner {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #f5f5f5;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: white;
+ border: 1px solid #ddd;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
}
-body.ttrss_main #headlines-frame[is-vfeed="0"] .header .feed {
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
display: none;
}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
body.ttrss_main #headlines-frame {
- padding: 0px;
- border: 0px #ddd;
- margin-top: 0px;
+ padding: 0;
+ border: 0;
+ margin-top: 0;
-webkit-overflow-scrolling: touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: #555;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: #555;
+ padding: 10px;
+ display: block;
}
-body.ttrss_main #headlines-frame div.feed-title {
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 8px;
}
-body.ttrss_main #headlines-frame div.feed-title a.title {
+body.ttrss_main #headlines-frame .feed-title a.title {
color: #555;
font-weight: bold;
}
-body.ttrss_main #headlines-frame div.feed-title a {
+body.ttrss_main #headlines-frame .feed-title a {
color: #555;
}
-body.ttrss_main #headlines-frame div.feed-title a:hover {
+body.ttrss_main #headlines-frame .feed-title a:hover {
color: #257aa7;
}
body.ttrss_main #headlines-frame span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
body.ttrss_main #toolbar-frame_splitter {
display: none;
}
body.ttrss_main #toolbar-frame {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+ padding: 0;
+ margin: 0;
+ border: 0;
white-space: nowrap;
- font-size: 12px;
+ font-size: 13px;
}
body.ttrss_main #toolbar-frame #toolbar {
background: white;
- border: 0px solid #ddd;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
padding-left: 4px;
height: 32px;
@@ -690,13 +758,13 @@ body.ttrss_main #toolbar-frame #toolbar {
flex-direction: row;
flex-wrap: nowrap;
color: #555;
- font-size: 12px;
+ font-size: 13px;
align-items: center;
}
body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
- border: 0px;
+ border: 0;
}
body.ttrss_main #toolbar-frame #toolbar i.net-alert,
body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
@@ -710,7 +778,7 @@ body.ttrss_main #toolbar-frame #toolbar i {
margin: 0 4px;
}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
- font-size: 12px;
+ font-size: 13px;
background: transparent;
padding-right: 4px;
flex-grow: 2;
@@ -725,6 +793,12 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
margin-left: 4px;
}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
display: flex;
align-items: center;
@@ -739,20 +813,26 @@ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
margin-right: 4px;
color: #257aa7;
}
-@media (max-width: 992px) {
+@media (max-width: 768px) {
body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
display: none;
}
}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
body.ttrss_main #header {
- border-width: 0px;
text-align: right;
color: #555;
- padding: 5px 5px 0px 0px;
- margin: 0px;
+ padding: 5px 5px 0 0px;
position: absolute;
- right: 0px;
- top: 0px;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
z-index: 5;
}
body.ttrss_main #header i.net-alert,
@@ -771,9 +851,8 @@ body.ttrss_main #header i {
margin: 0 4px;
}
body.ttrss_main #content-insert {
- padding: 0px;
- border-color: #ddd;
- border-width: 0px;
+ padding: 0;
+ border: 0;
line-height: 1.5;
overflow: auto;
-webkit-overflow-scrolling: touch;
@@ -786,59 +865,11 @@ body.ttrss_main img.icon {
vertical-align: middle;
display: inline-block;
}
-body.ttrss_main .player {
- display: inline-block;
- color: #555;
- font-size: 11px;
- font-family: sans-serif;
- border: 1px solid #555;
- padding: 0px 4px 0px 4px;
- margin: 0px 2px 0px 2px;
- width: 50px;
- text-align: center;
- background: white;
-}
-body.ttrss_main .player.playing {
- color: #00c000;
- border-color: #00c000;
-}
-body.ttrss_main .player:hover {
- background: #f5f5f5;
- cursor: pointer;
-}
-body.ttrss_main #headlines-frame.auto_catchup #headlines-spacer {
- height: 100%;
-}
-body.ttrss_main #headlines-spacer {
- margin-left: 1px;
- text-align: center;
- color: #555;
- font-size: 11px;
- font-style: italic;
-}
-body.ttrss_main #headlines-spacer a,
-body.ttrss_main #headlines-spacer span {
- color: #555;
- padding: 10px;
- display: block;
-}
-body.ttrss_main #headlines-spacer a:hover {
- color: #257aa7;
-}
body.ttrss_main ul#filterDlg_Matches,
body.ttrss_main ul#filterDlg_Actions {
list-style-type: none;
margin: 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
body.ttrss_main ul#filterDlg_Matches li,
body.ttrss_main ul#filterDlg_Actions li {
@@ -874,9 +905,6 @@ body.ttrss_main span.highlight {
background-color: #ffff00;
color: #cc90cc;
}
-body.ttrss_main #headlines-frame .dijitCheckBox {
- margin-right: 4px;
-}
body.ttrss_main #feedEditDlg img.feedIcon {
border: 1px solid #ccc;
padding: 5px;
@@ -934,6 +962,11 @@ body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-show
body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
display: none;
}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
body.ttrss_main #toolbar-headlines i.icon-syndicate {
color: #ff7c4b;
margin-right: 8px;
@@ -970,10 +1003,15 @@ body.ttrss_main .score-high i.icon-score {
body.ttrss_main .score-low i.icon-score {
color: #500;
}
-body.ttrss_main .score-neutral i.icon-score {
- opacity: 0.5;
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #777;
}
-body.ttrss_main i.icon-score {
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
cursor: pointer;
}
body.ttrss_main .panel {
@@ -1004,20 +1042,62 @@ body.ttrss_main ul.list-unstyled {
body.ttrss_main .text-center {
text-align: center;
}
-body.ttrss_main #prefFilterTestResultList .preview {
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
margin: 8px;
}
-body.ttrss_main #prefFilterTestResultList .title {
+body.ttrss_main .dijitDialog .filter-results-list .title {
font-weight: bold;
}
-body.ttrss_main #prefFilterTestResultList .feed {
- color: #257aa7;
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
}
body.ttrss_main .alert,
body.ttrss_utility .alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1058,6 +1138,16 @@ body.ttrss_main .text-warning,
body.ttrss_utility .text-warning {
color: #a47e3c;
}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: #555;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
body.ttrss_main .alert,
body.ttrss_utility .alert,
body.ttrss_main .alert h4,
@@ -1107,41 +1197,6 @@ body.ttrss_utility hr {
border: 0px solid #ccc;
border-bottom-width: 1px;
}
-body.ttrss_main .text-muted,
-body.ttrss_utility .text-muted {
- color: #555;
-}
-body.ttrss_main .small,
-body.ttrss_utility .small {
- font-size: 11px;
-}
-body.ttrss_main div.autocomplete,
-body.ttrss_utility div.autocomplete {
- position: absolute;
- width: 250px;
- background-color: white;
- border: 1px solid #ddd;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul,
-body.ttrss_utility div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul li.selected,
-body.ttrss_utility div.autocomplete ul li.selected {
- background-color: #e6e6e6;
-}
-body.ttrss_main div.autocomplete ul li,
-body.ttrss_utility div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
- cursor: pointer;
-}
::selection {
background: #257aa7;
color: white;
@@ -1155,16 +1210,13 @@ body.ttrss_utility div.autocomplete ul li {
::-webkit-scrollbar-track {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
- display: none;
-}
-.cdm i.material-icons {
- color: #777;
-}
-.cdm .header {
- position: sticky;
- top: 0;
- z-index: 3;
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
}
.cdm .header,
.cdm .footer {
@@ -1175,13 +1227,16 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header img,
.cdm .footer img,
.cdm .footer i.material-icons {
- margin: 0px 4px;
+ margin: 0 4px;
vertical-align: middle;
}
.cdm .header-sticky-guard {
height: 0;
}
.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
align-items: center;
}
.cdm .header > * {
@@ -1204,7 +1259,7 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header .titleWrap {
flex-grow: 2;
}
-.cdm .header span.updated {
+.cdm .header .updated {
color: #555;
font-weight: normal;
font-size: 11px;
@@ -1213,6 +1268,30 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header input {
margin: 0px 4px;
}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: #555;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: #555;
+ font-size: 11px;
+ font-weight: normal;
+}
.cdm .footer {
height: 30px;
padding-left: 5px;
@@ -1221,30 +1300,37 @@ video::-webkit-media-controls-overlay-play-button {
clear: both;
align-items: center;
}
+.cdm .footer i.material-icons {
+ color: #777;
+}
.cdm .footer .left {
flex-grow: 2;
}
.cdm .intermediate {
margin-top: 10px;
margin-left: 10px;
+ line-height: 1.5;
}
.cdm .content-inner {
margin: 10px;
line-height: 1.5;
font-size: 16px;
}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
.cdm .intermediate img,
.cdm .intermediate video,
.cdm .content-inner img,
.cdm .content-inner video {
border-width: 0px;
max-width: 98%;
+ width: auto;
height: auto;
}
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-}
.cdm.expanded .collapse,
.cdm.expanded .excerpt {
display: none;
@@ -1257,72 +1343,54 @@ video::-webkit-media-controls-overlay-play-button {
border-bottom-width: 1px;
}
.cdm.expanded > hr {
- margin-top: 0px;
- margin-bottom: 0px;
+ margin-top: 0;
+ margin-bottom: 0;
}
-div.cdm.expanded div.header a.title {
+.cdm.expanded .header a.title {
font-size: 16px;
color: #999;
font-weight: 600;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expanded.active {
- background: white;
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
}
-div.cdm.expanded.active div.header a.title {
+.cdm.expanded.active .header .title {
color: #257aa7;
}
-div.cdm.expanded.Unread div.header a.title {
+.cdm.expanded.Unread .header .title {
color: black;
}
-div.cdm.expanded div.content {
+.cdm.expanded .content {
color: #555;
}
-div.cdm.expanded.Unread div.content {
- color: black;
-}
-div.cdm.active div.content {
- color: black;
-}
-div.cdm.vgrlf .feed {
+.cdm.vgrlf .feed {
display: none;
}
-.cdm div.feed-title {
+.cdm .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 3px 5px 5px;
}
-.cdm div.feed-title a.title {
+.cdm .feed-title a.title {
color: #555;
font-weight: bold;
}
-.cdm div.feed-title a {
+.cdm .feed-title a {
color: #555;
}
-.cdm div.feed-title a:hover {
+.cdm .feed-title a:hover {
color: #257aa7;
}
-.cdm div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
-}
-.cdm div.header div.feed,
-.cdm div.header div.feed a {
- vertical-align: middle;
- color: #555;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
-}
-.cdm div.content-inner div.embed-responsive {
+.cdm .content-inner .embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-.cdm div.content-inner div.embed-responsive iframe {
+.cdm .content-inner .embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -1331,17 +1399,6 @@ div.cdm.vgrlf .feed {
top: 0;
width: 100%;
}
-.cdm div.header span.author {
- white-space: nowrap;
- color: #555;
- font-size: 11px;
- font-weight: normal;
-}
-.cdm .feed a {
- border-radius: 4px;
- display: inline-block;
- padding: 1px 4px 1px 4px;
-}
.cdm.expandable {
background-color: #f5f5f5;
border: 0px solid #ddd;
@@ -1379,43 +1436,43 @@ div.cdm.vgrlf .feed {
.cdm.expandable.active {
background: white ! important;
}
-div.cdm.expandable.active div.header span.titleWrap {
+.cdm.expandable.active div.header span.titleWrap {
white-space: normal;
}
-div.cdm.expandable div.header a.title {
+.cdm.expandable .header a.title {
font-weight: 600;
color: #555;
font-size: 14px;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable.Unread div.header a.title {
+.cdm.expandable.Unread div.header a.title {
color: black;
}
-div.cdm.expandable.active .collapse i.material-icons {
+.cdm.expandable.active .collapse i.material-icons {
color: #257aa7;
cursor: pointer;
}
-div.cdm.expandable.active .excerpt {
+.cdm.expandable.active .excerpt {
display: none;
}
-div.cdm.expandable.active div.header a.title {
+.cdm.expandable.active div.header a.title {
color: #257aa7;
font-size: 16px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable:not(.active) {
+.cdm.expandable:not(.active) {
cursor: pointer;
}
-div.cdm.expandable:not(.active) .content,
-div.cdm.expandable:not(.active) .collapse {
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
display: none;
}
-div.cdm.expandable.active .header[stuck],
-div.cdm.expanded .header[stuck] {
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
border: 0 solid #ddd;
border-bottom-width: 1px;
@@ -1432,7 +1489,7 @@ body.ttrss_prefs h1,
body.ttrss_prefs h2,
body.ttrss_prefs h3,
body.ttrss_prefs h4 {
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 600;
color: #555;
}
@@ -1503,14 +1560,6 @@ body.ttrss_prefs fieldset.prefs .help-text {
body.ttrss_prefs fieldset.prefs .help-text-bottom {
margin-top: 10px;
}
-body.ttrss_prefs fieldset.plugin label.description {
- width: 550px;
- margin-right: 150px;
- display: inline-block;
-}
-body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox {
- margin-right: 10px;
-}
body.ttrss_prefs table th {
text-align: left;
}
@@ -1538,17 +1587,26 @@ body.ttrss_prefs ul.prefs-plugin-list li > * {
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
display: flex;
align-items: center;
- min-width: 300px;
cursor: pointer;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
cursor: auto;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
}
body.ttrss_prefs ul.prefs-plugin-list li .actions {
flex-grow: 2;
@@ -1602,6 +1660,11 @@ body.ttrss_prefs .event-log tr .errno {
body.ttrss_prefs .event-log tr .errstr {
word-break: break-all;
white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
}
body.ttrss_prefs .event-log tr .filename,
body.ttrss_prefs .event-log tr .login,
@@ -1665,7 +1728,7 @@ body.ttrss_utility.sanity_failed {
}
body.ttrss_utility {
background: #f5f5f5;
- color: black;
+ color: #555;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
margin: 4em;
@@ -1683,7 +1746,7 @@ body.ttrss_utility .content h2,
body.ttrss_utility .content h3,
body.ttrss_utility .content h4 {
color: #257aa7;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_utility .content h2 {
font-size: 18px;
@@ -1702,7 +1765,7 @@ body.ttrss_utility a:focus {
}
body.ttrss_utility h1 {
color: gray;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
margin: 10px 0 0 0;
}
@@ -1758,12 +1821,16 @@ body.ttrss_utility.share_popup .content {
border-width: 0;
box-shadow: none;
}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
.flat li {
padding: 2px;
}
-.flat #feedTree .dijitTreeContent .dijitInline {
- vertical-align: baseline;
-}
.flat .dijitButton i.material-icons {
position: relative;
top: -1px;
@@ -1787,7 +1854,8 @@ body.ttrss_utility.share_popup .content {
}
.flat .dijitToolbar {
font-size: 13px;
- padding: 0px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
}
.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
line-height: 10px;
@@ -1810,12 +1878,13 @@ body.ttrss_utility.share_popup .content {
.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
padding: 4px 8px;
font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
color: #2e99d1;
}
.flat .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ padding: 0;
}
.flat .dijitCheckBox {
margin: 1px;
@@ -1825,10 +1894,33 @@ body.ttrss_utility.share_popup .content {
content: "\f00c";
color: white;
}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
.flat .dijitTab i.material-icons,
.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
color: #257aa7;
}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
.flat .dijitTree .dijitFolderClosed,
.flat .dijitTree .dijitFolderOpened {
display: none;
@@ -1842,10 +1934,6 @@ body.ttrss_utility.share_popup .content {
.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
color: white;
}
-.flat .dijitTree .dijitTreeRow .dijitTreeExpando {
- position: relative;
- top: -2px;
-}
.flat .dijitTree .labelParam {
float: right;
margin-right: 16px;
@@ -1874,6 +1962,7 @@ body.ttrss_utility.share_popup .content {
.flat .dijitTree .dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
.flat label.dijitButton {
@@ -1948,11 +2037,11 @@ body.ttrss_zoom div.post .attachments {
display: none;
}
body.ttrss_zoom div.post div.header {
- padding-bottom: 10px;
- border: 0px solid #ddd;
+ padding-bottom: 8px;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
background: white;
- font-size: 12px;
+ font-size: 13px;
color: #555;
}
body.ttrss_zoom div.post div.header .row {
@@ -1962,32 +2051,36 @@ body.ttrss_zoom div.post div.header .row {
align-items: center;
justify-content: space-between;
}
-body.ttrss_zoom div.post div.content {
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
font-size: 15px;
line-height: 1.5;
border-width: 0;
padding: 0;
+ padding-top: 8px;
}
-body.ttrss_zoom div.post div.content img,
-body.ttrss_zoom div.post div.content video {
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
max-width: 760px;
height: auto;
}
-body.ttrss_zoom div.post div.content blockquote {
+body.ttrss_zoom div.post .content blockquote {
margin: 5px 0px 5px 0px;
color: #555;
- padding-left: 10px;
+ padding-left: 8px;
border: 0px solid #ddd;
border-left-width: 4px;
}
-body.ttrss_zoom div.post div.content code {
+body.ttrss_zoom div.post .content code {
color: #009900;
font-family: monospace;
font-size: 12px;
}
-body.ttrss_zoom div.post div.content pre {
- margin: 5px 0px 5px 0px;
- padding: 10px;
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
color: #555;
font-family: monospace;
font-size: 12px;
diff --git a/themes/compact_night.css b/themes/compact_night.css
index c9f9b12a8..2436dd911 100644
--- a/themes/compact_night.css
+++ b/themes/compact_night.css
@@ -15,67 +15,77 @@ body.ttrss_main {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
}
body.ttrss_main :focus {
outline: none;
}
-body.ttrss_main div.post {
- padding: 0px;
+body.ttrss_main .post {
+ padding: 0;
font-size: 13px;
}
-body.ttrss_main div.post div.header {
+body.ttrss_main .post .header {
padding: 5px;
- color: #909090;
- border: 0px solid #222;
+ color: #ccc;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #222;
}
-body.ttrss_main div.post div.header .left,
-body.ttrss_main div.post div.header .right {
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
display: flex;
}
-body.ttrss_main div.post div.header .row {
+body.ttrss_main .post .header .row {
display: flex;
margin-bottom: 4px;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
}
-body.ttrss_main div.post div.header .comments {
+body.ttrss_main .post .header .comments {
flex-grow: 2;
}
-body.ttrss_main div.post div.header .date {
+body.ttrss_main .post .header .date {
white-space: nowrap;
}
-body.ttrss_main div.post div.header img,
-body.ttrss_main div.post div.header i.material-icons {
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
margin: 0px 4px;
vertical-align: middle;
- color: #777;
+ color: #999;
}
-body.ttrss_main div.post div.header .title {
+body.ttrss_main .post .header .title {
flex-grow: 2;
font-size: 15px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main div.post div.content {
+body.ttrss_main .post div.content {
padding: 10px;
font-size: 16px;
}
-body.ttrss_main div.post div.content img,
-body.ttrss_main div.post div.content video {
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
border-width: 0px;
max-width: 98%;
height: auto;
}
-body.ttrss_main div.post div.content div.embed-responsive {
+body.ttrss_main .post div.content div.embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-body.ttrss_main div.post div.content div.embed-responsive iframe {
+body.ttrss_main .post div.content div.embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -172,6 +182,11 @@ body.ttrss_main .notify.notify_progress {
border-color: #d7c47a;
background-color: #fff7d5;
}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
body.ttrss_main .notify.notify_info {
border-color: #b87d2c;
background-color: #faf3e9;
@@ -217,6 +232,10 @@ body.ttrss_main .hl .right {
display: flex;
align-items: center;
}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
body.ttrss_main .hl .left i.material-icons,
body.ttrss_main .hl .right i.material-icons {
margin-left: 2px;
@@ -225,25 +244,28 @@ body.ttrss_main .hl .right i.material-icons {
user-select: none;
font-size: 21px;
}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
body.ttrss_main .hl .right i.material-icons {
- color: #777;
+ color: #999;
}
-body.ttrss_main .hl div.title {
+body.ttrss_main .hl .title {
cursor: pointer;
flex-grow: 2;
overflow: hidden;
text-overflow: ellipsis;
}
-body.ttrss_main .hl span.author {
+body.ttrss_main .hl .author {
white-space: nowrap;
color: #ccc;
font-size: 11px;
font-weight: normal;
}
-body.ttrss_main .hl div.right {
- text-align: right;
-}
-body.ttrss_main .hl span.feed a {
+body.ttrss_main .hl .feed a {
border-radius: 4px;
display: inline-block;
padding: 1px 4px;
@@ -252,29 +274,22 @@ body.ttrss_main .hl span.feed a {
font-weight: normal;
color: #ccc;
}
-body.ttrss_main .hl span.feed a:hover {
+body.ttrss_main .hl .feed a:hover {
color: #b87d2c;
}
-body.ttrss_main .hl span.updated {
+body.ttrss_main .hl .updated {
color: #ccc;
text-align: right;
font-size: 11px;
padding-left: 10px;
}
-body.ttrss_main .hl span.updated div {
+body.ttrss_main .hl .updated div {
display: inline-block;
}
-body.ttrss_main .hl div.left input {
- margin: 0px 4px;
-}
-body.ttrss_main .hl div.left img,
-body.ttrss_main .hl div.right img {
- margin: 0px 4px;
-}
body.ttrss_main .hl div.title a {
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #555;
}
body.ttrss_main .hl a.title.high,
@@ -287,10 +302,10 @@ body.ttrss_main .hl.vgrlf .feed {
body.ttrss_main .hl.Unread {
background: white;
}
-body.ttrss_main .hl.Unread div.title a {
+body.ttrss_main .hl.Unread .title a {
color: black;
}
-body.ttrss_main .hl.active div.title a {
+body.ttrss_main .hl.active .title a {
color: #b87d2c;
/* text-shadow : 1px 1px 2px #fff; */
}
@@ -312,9 +327,6 @@ body.ttrss_main .hl.active span,
body.ttrss_main .hl.Selected span {
color: white;
}
-body.ttrss_main .hl.Grayed {
- color: #909090;
-}
body.ttrss_main #content-insert blockquote,
body.ttrss_main #headlines-frame blockquote,
body.ttrss_main .dijitContentPane blockquote {
@@ -371,45 +383,6 @@ body.ttrss_main i.pub-pic {
cursor: pointer;
color: #ccc;
}
-body.ttrss_main div.errorExplained {
- border: 1px solid #222;
- margin: 5px 0px 5px 0px;
- padding: 5px;
-}
-body.ttrss_main ul.browseFeedList {
- height: 300px;
- width: 100%;
- overflow: auto;
- border-width: 0px 1px 1px 1px;
- border-color: #222;
- border-style: solid;
- margin: 0px 0px 5px 0px;
- background-color: white;
- list-style-type: none;
- padding: 0px;
-}
-body.ttrss_main ul.browseFeedList li {
- display: flex;
- align-items: center;
-}
-body.ttrss_main ul.browseFeedList li > * {
- margin: 2px;
-}
-body.ttrss_main .browseFeedList span.subscribers {
- color: #808080;
-}
-body.ttrss_main ul.compact {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main ul.compact li {
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main .noborder {
- border-width: 0px;
-}
body.ttrss_main #overlay {
background: #333;
left: 0;
@@ -423,11 +396,6 @@ body.ttrss_main #overlay_inner {
font-weight: bold;
margin: 1em;
}
-body.ttrss_main div.loadingPrompt {
- padding: 1em;
- text-align: center;
- font-weight: bold;
-}
body.ttrss_main div.whiteBox {
margin-left: 1px;
text-align: center;
@@ -436,20 +404,13 @@ body.ttrss_main div.whiteBox {
border: 0px solid #222;
border-bottom-width: 1px;
}
-body.ttrss_main div#headlines-frame.wide .title {
- overflow: visible;
- white-space: normal;
-}
-body.ttrss_main div#headlines-frame.wide .hl .feed {
- display: none;
-}
body.ttrss_main .dijitDialog header,
body.ttrss_main .dijitDialog .dlgSec,
body.ttrss_main .dijitDialog .dlgSecHoriz {
font-size: 16px;
font-weight: 600;
color: #ccc;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_main .dijitDialog section,
body.ttrss_main .dijitDialog .dlgSecCont {
@@ -527,11 +488,6 @@ body.ttrss_main div#cmdline {
padding: 3px 5px 3px 5px;
z-index: 5;
}
-body.ttrss_main #feed_browser_spinner {
- vertical-align: middle;
- height: 18px;
- width: 18px;
-}
body.ttrss_main .exception-contents h3 {
color: red;
}
@@ -540,14 +496,15 @@ body.ttrss_main .exception-contents textarea {
height: 200px;
font-size: 11px;
}
+body.ttrss_main #headlines-wrap-inner,
body.ttrss_main #content-wrap {
- padding: 0px;
- border-width: 0px;
- margin: 0px;
+ padding: 0;
+ border: 0;
+ margin: 0;
}
body.ttrss_main #feeds-holder {
- padding: 0px;
- border: 0px solid #222;
+ padding: 0;
+ border: 0 solid #222;
overflow: hidden;
background: #222;
box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
@@ -557,19 +514,26 @@ body.ttrss_main #feeds-holder #feedTree {
height: 100%;
overflow-x: hidden;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- background: #222;
- color: #e6e6e6;
- border-color: #080808;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- border-color: #b87d2c;
- background: #ffffff;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
font-weight: bold;
display: none;
font-size: 9px;
@@ -578,111 +542,215 @@ body.ttrss_main #feeds-holder #feedTree .counterNode {
color: white;
background: #cd8b31;
border-radius: 4px;
- vertical-align: middle;
- float: right;
- position: relative;
line-height: 14px;
margin-right: 8px;
- margin-top: 2px;
min-width: 23px;
height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #222;
+ color: #e6e6e6;
+ border-color: #080808;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #b87d2c;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .loadingExpando {
- left: -3px;
- height: 22px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
position: relative;
- top: -3px;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeLabel.Unread {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
font-weight: bold;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow.Error .dijitTreeLabel {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
color: red;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
- border: 1px solid transparent;
-}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRowSelected {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
border-color: #222 transparent;
background: #333;
- color: #333;
+ color: #ccc;
}
-body.ttrss_main #feeds-holder #feedTree .dijitIcon.feed-icon {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
margin-right: 2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
- color: #555;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #ffffff;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-archive {
- color: #c77b2e;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-star {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
position: relative;
color: #ffc069;
font-size: 21px;
left: -2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-rss_feed {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
color: #ff7c4b;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-whatshot {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
color: #69C671;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-restore {
- position: relative;
- top: -1px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
font-weight: bold;
color: #b87d2c;
}
-body.ttrss_main #headlines-wrap-inner {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #222;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: #333;
+ border: 1px solid #222;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
}
-body.ttrss_main #headlines-frame[is-vfeed="0"] .header .feed {
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
display: none;
}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
body.ttrss_main #headlines-frame {
- padding: 0px;
- border: 0px #222;
- margin-top: 0px;
+ padding: 0;
+ border: 0;
+ margin-top: 0;
-webkit-overflow-scrolling: touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
}
-body.ttrss_main #headlines-frame div.feed-title {
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: #ccc;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: #ccc;
+ padding: 10px;
+ display: block;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #b87d2c;
+}
+body.ttrss_main #headlines-frame .feed-title {
border: 0px solid #b87d2c;
border-bottom-width: 1px;
padding: 5px 8px;
}
-body.ttrss_main #headlines-frame div.feed-title a.title {
+body.ttrss_main #headlines-frame .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-body.ttrss_main #headlines-frame div.feed-title a {
+body.ttrss_main #headlines-frame .feed-title a {
color: #ccc;
}
-body.ttrss_main #headlines-frame div.feed-title a:hover {
+body.ttrss_main #headlines-frame .feed-title a:hover {
color: #b87d2c;
}
body.ttrss_main #headlines-frame span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
body.ttrss_main #toolbar-frame_splitter {
display: none;
}
body.ttrss_main #toolbar-frame {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+ padding: 0;
+ margin: 0;
+ border: 0;
white-space: nowrap;
- font-size: 12px;
+ font-size: 13px;
}
body.ttrss_main #toolbar-frame #toolbar {
background: white;
- border: 0px solid #222;
+ border: 0 solid #222;
border-bottom-width: 1px;
padding-left: 4px;
height: 32px;
@@ -690,13 +758,13 @@ body.ttrss_main #toolbar-frame #toolbar {
flex-direction: row;
flex-wrap: nowrap;
color: #ccc;
- font-size: 12px;
+ font-size: 13px;
align-items: center;
}
body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
- border: 0px;
+ border: 0;
}
body.ttrss_main #toolbar-frame #toolbar i.net-alert,
body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
@@ -710,7 +778,7 @@ body.ttrss_main #toolbar-frame #toolbar i {
margin: 0 4px;
}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
- font-size: 12px;
+ font-size: 13px;
background: transparent;
padding-right: 4px;
flex-grow: 2;
@@ -725,6 +793,12 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
margin-left: 4px;
}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
display: flex;
align-items: center;
@@ -739,20 +813,26 @@ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
margin-right: 4px;
color: #b87d2c;
}
-@media (max-width: 992px) {
+@media (max-width: 768px) {
body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
display: none;
}
}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
body.ttrss_main #header {
- border-width: 0px;
text-align: right;
color: #ccc;
- padding: 5px 5px 0px 0px;
- margin: 0px;
+ padding: 5px 5px 0 0px;
position: absolute;
- right: 0px;
- top: 0px;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
z-index: 5;
}
body.ttrss_main #header i.net-alert,
@@ -771,9 +851,8 @@ body.ttrss_main #header i {
margin: 0 4px;
}
body.ttrss_main #content-insert {
- padding: 0px;
- border-color: #222;
- border-width: 0px;
+ padding: 0;
+ border: 0;
line-height: 1.5;
overflow: auto;
-webkit-overflow-scrolling: touch;
@@ -786,59 +865,11 @@ body.ttrss_main img.icon {
vertical-align: middle;
display: inline-block;
}
-body.ttrss_main .player {
- display: inline-block;
- color: #ccc;
- font-size: 11px;
- font-family: sans-serif;
- border: 1px solid #ccc;
- padding: 0px 4px 0px 4px;
- margin: 0px 2px 0px 2px;
- width: 50px;
- text-align: center;
- background: #333;
-}
-body.ttrss_main .player.playing {
- color: #00c000;
- border-color: #00c000;
-}
-body.ttrss_main .player:hover {
- background: #222;
- cursor: pointer;
-}
-body.ttrss_main #headlines-frame.auto_catchup #headlines-spacer {
- height: 100%;
-}
-body.ttrss_main #headlines-spacer {
- margin-left: 1px;
- text-align: center;
- color: #ccc;
- font-size: 11px;
- font-style: italic;
-}
-body.ttrss_main #headlines-spacer a,
-body.ttrss_main #headlines-spacer span {
- color: #ccc;
- padding: 10px;
- display: block;
-}
-body.ttrss_main #headlines-spacer a:hover {
- color: #b87d2c;
-}
body.ttrss_main ul#filterDlg_Matches,
body.ttrss_main ul#filterDlg_Actions {
list-style-type: none;
margin: 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
body.ttrss_main ul#filterDlg_Matches li,
body.ttrss_main ul#filterDlg_Actions li {
@@ -874,9 +905,6 @@ body.ttrss_main span.highlight {
background-color: #ffff00;
color: #cc90cc;
}
-body.ttrss_main #headlines-frame .dijitCheckBox {
- margin-right: 4px;
-}
body.ttrss_main #feedEditDlg img.feedIcon {
border: 1px solid #ccc;
padding: 5px;
@@ -934,6 +962,11 @@ body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-show
body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
display: none;
}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
body.ttrss_main #toolbar-headlines i.icon-syndicate {
color: #ff7c4b;
margin-right: 8px;
@@ -970,10 +1003,15 @@ body.ttrss_main .score-high i.icon-score {
body.ttrss_main .score-low i.icon-score {
color: #500;
}
-body.ttrss_main .score-neutral i.icon-score {
- opacity: 0.5;
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #999;
}
-body.ttrss_main i.icon-score {
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
cursor: pointer;
}
body.ttrss_main .panel {
@@ -1004,20 +1042,62 @@ body.ttrss_main ul.list-unstyled {
body.ttrss_main .text-center {
text-align: center;
}
-body.ttrss_main #prefFilterTestResultList .preview {
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
margin: 8px;
}
-body.ttrss_main #prefFilterTestResultList .title {
+body.ttrss_main .dijitDialog .filter-results-list .title {
font-weight: bold;
}
-body.ttrss_main #prefFilterTestResultList .feed {
- color: #b87d2c;
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
}
body.ttrss_main .alert,
body.ttrss_utility .alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1058,6 +1138,16 @@ body.ttrss_main .text-warning,
body.ttrss_utility .text-warning {
color: #a47e3c;
}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: #ccc;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
body.ttrss_main .alert,
body.ttrss_utility .alert,
body.ttrss_main .alert h4,
@@ -1107,41 +1197,6 @@ body.ttrss_utility hr {
border: 0px solid #ccc;
border-bottom-width: 1px;
}
-body.ttrss_main .text-muted,
-body.ttrss_utility .text-muted {
- color: #ccc;
-}
-body.ttrss_main .small,
-body.ttrss_utility .small {
- font-size: 11px;
-}
-body.ttrss_main div.autocomplete,
-body.ttrss_utility div.autocomplete {
- position: absolute;
- width: 250px;
- background-color: #333;
- border: 1px solid #222;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul,
-body.ttrss_utility div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul li.selected,
-body.ttrss_utility div.autocomplete ul li.selected {
- background-color: #1a1a1a;
-}
-body.ttrss_main div.autocomplete ul li,
-body.ttrss_utility div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
- cursor: pointer;
-}
::selection {
background: #b87d2c;
color: #333;
@@ -1155,16 +1210,13 @@ body.ttrss_utility div.autocomplete ul li {
::-webkit-scrollbar-track {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
- display: none;
-}
-.cdm i.material-icons {
- color: #777;
-}
-.cdm .header {
- position: sticky;
- top: 0;
- z-index: 3;
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
}
.cdm .header,
.cdm .footer {
@@ -1175,13 +1227,16 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header img,
.cdm .footer img,
.cdm .footer i.material-icons {
- margin: 0px 4px;
+ margin: 0 4px;
vertical-align: middle;
}
.cdm .header-sticky-guard {
height: 0;
}
.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
align-items: center;
}
.cdm .header > * {
@@ -1204,7 +1259,7 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header .titleWrap {
flex-grow: 2;
}
-.cdm .header span.updated {
+.cdm .header .updated {
color: #ccc;
font-weight: normal;
font-size: 11px;
@@ -1213,6 +1268,30 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header input {
margin: 0px 4px;
}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: #ccc;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: #ccc;
+ font-size: 11px;
+ font-weight: normal;
+}
.cdm .footer {
height: 30px;
padding-left: 5px;
@@ -1221,30 +1300,37 @@ video::-webkit-media-controls-overlay-play-button {
clear: both;
align-items: center;
}
+.cdm .footer i.material-icons {
+ color: #999;
+}
.cdm .footer .left {
flex-grow: 2;
}
.cdm .intermediate {
margin-top: 10px;
margin-left: 10px;
+ line-height: 1.5;
}
.cdm .content-inner {
margin: 10px;
line-height: 1.5;
font-size: 16px;
}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
.cdm .intermediate img,
.cdm .intermediate video,
.cdm .content-inner img,
.cdm .content-inner video {
border-width: 0px;
max-width: 98%;
+ width: auto;
height: auto;
}
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-}
.cdm.expanded .collapse,
.cdm.expanded .excerpt {
display: none;
@@ -1257,72 +1343,54 @@ video::-webkit-media-controls-overlay-play-button {
border-bottom-width: 1px;
}
.cdm.expanded > hr {
- margin-top: 0px;
- margin-bottom: 0px;
+ margin-top: 0;
+ margin-bottom: 0;
}
-div.cdm.expanded div.header a.title {
+.cdm.expanded .header a.title {
font-size: 16px;
color: #999;
font-weight: 600;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expanded.active {
- background: white;
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
}
-div.cdm.expanded.active div.header a.title {
+.cdm.expanded.active .header .title {
color: #b87d2c;
}
-div.cdm.expanded.Unread div.header a.title {
+.cdm.expanded.Unread .header .title {
color: black;
}
-div.cdm.expanded div.content {
+.cdm.expanded .content {
color: #ccc;
}
-div.cdm.expanded.Unread div.content {
- color: black;
-}
-div.cdm.active div.content {
- color: black;
-}
-div.cdm.vgrlf .feed {
+.cdm.vgrlf .feed {
display: none;
}
-.cdm div.feed-title {
+.cdm .feed-title {
border: 0px solid #b87d2c;
border-bottom-width: 1px;
padding: 5px 3px 5px 5px;
}
-.cdm div.feed-title a.title {
+.cdm .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-.cdm div.feed-title a {
+.cdm .feed-title a {
color: #ccc;
}
-.cdm div.feed-title a:hover {
+.cdm .feed-title a:hover {
color: #b87d2c;
}
-.cdm div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
-}
-.cdm div.header div.feed,
-.cdm div.header div.feed a {
- vertical-align: middle;
- color: #ccc;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
-}
-.cdm div.content-inner div.embed-responsive {
+.cdm .content-inner .embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-.cdm div.content-inner div.embed-responsive iframe {
+.cdm .content-inner .embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -1331,17 +1399,6 @@ div.cdm.vgrlf .feed {
top: 0;
width: 100%;
}
-.cdm div.header span.author {
- white-space: nowrap;
- color: #ccc;
- font-size: 11px;
- font-weight: normal;
-}
-.cdm .feed a {
- border-radius: 4px;
- display: inline-block;
- padding: 1px 4px 1px 4px;
-}
.cdm.expandable {
background-color: #222;
border: 0px solid #222;
@@ -1379,43 +1436,43 @@ div.cdm.vgrlf .feed {
.cdm.expandable.active {
background: white ! important;
}
-div.cdm.expandable.active div.header span.titleWrap {
+.cdm.expandable.active div.header span.titleWrap {
white-space: normal;
}
-div.cdm.expandable div.header a.title {
+.cdm.expandable .header a.title {
font-weight: 600;
color: #ccc;
font-size: 14px;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable.Unread div.header a.title {
+.cdm.expandable.Unread div.header a.title {
color: black;
}
-div.cdm.expandable.active .collapse i.material-icons {
+.cdm.expandable.active .collapse i.material-icons {
color: #b87d2c;
cursor: pointer;
}
-div.cdm.expandable.active .excerpt {
+.cdm.expandable.active .excerpt {
display: none;
}
-div.cdm.expandable.active div.header a.title {
+.cdm.expandable.active div.header a.title {
color: #b87d2c;
font-size: 16px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable:not(.active) {
+.cdm.expandable:not(.active) {
cursor: pointer;
}
-div.cdm.expandable:not(.active) .content,
-div.cdm.expandable:not(.active) .collapse {
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
display: none;
}
-div.cdm.expandable.active .header[stuck],
-div.cdm.expanded .header[stuck] {
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
border: 0 solid #222;
border-bottom-width: 1px;
@@ -1432,7 +1489,7 @@ body.ttrss_prefs h1,
body.ttrss_prefs h2,
body.ttrss_prefs h3,
body.ttrss_prefs h4 {
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 600;
color: #ccc;
}
@@ -1503,14 +1560,6 @@ body.ttrss_prefs fieldset.prefs .help-text {
body.ttrss_prefs fieldset.prefs .help-text-bottom {
margin-top: 10px;
}
-body.ttrss_prefs fieldset.plugin label.description {
- width: 550px;
- margin-right: 150px;
- display: inline-block;
-}
-body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox {
- margin-right: 10px;
-}
body.ttrss_prefs table th {
text-align: left;
}
@@ -1538,17 +1587,26 @@ body.ttrss_prefs ul.prefs-plugin-list li > * {
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
display: flex;
align-items: center;
- min-width: 300px;
cursor: pointer;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
cursor: auto;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
}
body.ttrss_prefs ul.prefs-plugin-list li .actions {
flex-grow: 2;
@@ -1602,6 +1660,11 @@ body.ttrss_prefs .event-log tr .errno {
body.ttrss_prefs .event-log tr .errstr {
word-break: break-all;
white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
}
body.ttrss_prefs .event-log tr .filename,
body.ttrss_prefs .event-log tr .login,
@@ -1660,12 +1723,16 @@ body.ttrss_utility fieldset > label.checkbox {
display: inline;
font-weight: normal;
}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
.flat li {
padding: 2px;
}
-.flat #feedTree .dijitTreeContent .dijitInline {
- vertical-align: baseline;
-}
.flat .dijitButton i.material-icons {
position: relative;
top: -1px;
@@ -1689,7 +1756,8 @@ body.ttrss_utility fieldset > label.checkbox {
}
.flat .dijitToolbar {
font-size: 13px;
- padding: 0px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
}
.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
line-height: 10px;
@@ -1712,12 +1780,13 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
padding: 4px 8px;
font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
color: #d29745;
}
.flat .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ padding: 0;
}
.flat .dijitCheckBox {
margin: 1px;
@@ -1727,10 +1796,33 @@ body.ttrss_utility fieldset > label.checkbox {
content: "\f00c";
color: white;
}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
.flat .dijitTab i.material-icons,
.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
color: #b87d2c;
}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
.flat .dijitTree .dijitFolderClosed,
.flat .dijitTree .dijitFolderOpened {
display: none;
@@ -1744,10 +1836,6 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
color: white;
}
-.flat .dijitTree .dijitTreeRow .dijitTreeExpando {
- position: relative;
- top: -2px;
-}
.flat .dijitTree .labelParam {
float: right;
margin-right: 16px;
@@ -1776,6 +1864,7 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
.flat label.dijitButton {
@@ -1851,7 +1940,7 @@ body.ttrss_utility .content h2,
body.ttrss_utility .content h3,
body.ttrss_utility .content h4 {
color: #b87d2c;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_utility .content h2 {
font-size: 18px;
@@ -1870,7 +1959,7 @@ body.ttrss_utility a:focus {
}
body.ttrss_utility h1 {
color: gray;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
margin: 10px 0 0 0;
}
@@ -1939,11 +2028,11 @@ body.ttrss_zoom div.post .attachments {
display: none;
}
body.ttrss_zoom div.post div.header {
- padding-bottom: 10px;
- border: 0px solid #222;
+ padding-bottom: 8px;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #333;
- font-size: 12px;
+ font-size: 13px;
color: #ccc;
}
body.ttrss_zoom div.post div.header .row {
@@ -1953,32 +2042,36 @@ body.ttrss_zoom div.post div.header .row {
align-items: center;
justify-content: space-between;
}
-body.ttrss_zoom div.post div.content {
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
font-size: 15px;
line-height: 1.5;
border-width: 0;
padding: 0;
+ padding-top: 8px;
}
-body.ttrss_zoom div.post div.content img,
-body.ttrss_zoom div.post div.content video {
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
max-width: 760px;
height: auto;
}
-body.ttrss_zoom div.post div.content blockquote {
+body.ttrss_zoom div.post .content blockquote {
margin: 5px 0px 5px 0px;
color: #ccc;
- padding-left: 10px;
+ padding-left: 8px;
border: 0px solid #222;
border-left-width: 4px;
}
-body.ttrss_zoom div.post div.content code {
+body.ttrss_zoom div.post .content code {
color: #009900;
font-family: monospace;
font-size: 12px;
}
-body.ttrss_zoom div.post div.content pre {
- margin: 5px 0px 5px 0px;
- padding: 10px;
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
color: #ccc;
font-family: monospace;
font-size: 12px;
@@ -2022,26 +2115,34 @@ body.flat.ttrss_main #feeds-holder {
background: #222;
box-shadow: inset -1px 0px 2px -1px #666;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.aux,
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
background: #222;
color: #ccc;
border-color: #333;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
border-color: #b87d2c;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected {
background: #333;
border-color: #333 transparent;
color: #e6e6e6;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLabel {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected .dijitTreeLabel {
text-shadow: none;
}
-body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow i.icon.icon-inbox {
color: #999999;
}
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .loadingNode {
+ filter: invert(1);
+}
+body.flat.ttrss_main #headlines-frame {
+ /*.cdm.expanded {
+ background: @default-bg;
+ }*/
+}
body.flat.ttrss_main #headlines-frame .hl:not(.active):not(.Selected):not(.Unread),
body.flat.ttrss_main #headlines-frame .cdm.expandable:not(.active):not(.Selected):not(.Unread) {
background: #333;
@@ -2050,9 +2151,6 @@ body.flat.ttrss_main #headlines-frame .hl.Unread:not(.active):not(.Selected),
body.flat.ttrss_main #headlines-frame .cdm.expandable.Unread:not(.active):not(.Selected) {
background: #222;
}
-body.flat.ttrss_main #headlines-frame .cdm.expanded {
- background: #333;
-}
body.flat.ttrss_main #headlines-frame .hl.Unread .title,
body.flat.ttrss_main #headlines-frame .cdm.Unread .title {
color: #e6e6e6;
@@ -2225,6 +2323,9 @@ body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextAreaError {
body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextArea:not(.dijitValidationTextAreaError) {
background: #305030;
}
+body.flat.ttrss_main .dijitDialog #feed_add_spinner {
+ filter: invert(1);
+}
/* rules specific to compact.css */
body.ttrss_main.ttrss_index.flat #feedTree.dijitTree .dijitTreeLabel {
font-size: 13px ! important;
diff --git a/themes/light-high-contrast.css b/themes/light-high-contrast.css
new file mode 100644
index 000000000..16ac51035
--- /dev/null
+++ b/themes/light-high-contrast.css
@@ -0,0 +1,2093 @@
+@import "../lib/flat-ttrss/flat_combined.css";
+body.ttrss_main,
+body.ttrss_prefs,
+#main {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ border: 0;
+ padding: 0;
+ margin: 0;
+}
+body.ttrss_main {
+ background: white;
+ color: black;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
+}
+body.ttrss_main :focus {
+ outline: none;
+}
+body.ttrss_main .post {
+ padding: 0;
+ font-size: 13px;
+}
+body.ttrss_main .post .header {
+ padding: 5px;
+ color: black;
+ border: 0 solid #ddd;
+ border-bottom-width: 1px;
+ background: #f5f5f5;
+}
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
+ display: flex;
+}
+body.ttrss_main .post .header .row {
+ display: flex;
+ margin-bottom: 4px;
+ flex-wrap: nowrap;
+ align-items: center;
+ justify-content: space-between;
+}
+body.ttrss_main .post .header .comments {
+ flex-grow: 2;
+}
+body.ttrss_main .post .header .date {
+ white-space: nowrap;
+}
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
+ margin: 0px 4px;
+ vertical-align: middle;
+ color: #777;
+}
+body.ttrss_main .post .header .title {
+ flex-grow: 2;
+ font-size: 15px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+body.ttrss_main .post div.content {
+ padding: 10px;
+ font-size: 16px;
+}
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
+ border-width: 0px;
+ max-width: 98%;
+ height: auto;
+}
+body.ttrss_main .post div.content div.embed-responsive {
+ overflow: hidden;
+ padding-bottom: 56.25%;
+ position: relative;
+}
+body.ttrss_main .post div.content div.embed-responsive iframe {
+ border: 0;
+ bottom: 0;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+body.ttrss_main .inline-player {
+ display: flex;
+ align-items: center;
+}
+body.ttrss_main .inline-player audio {
+ margin-right: 8px;
+}
+body.ttrss_main .article-note {
+ background-color: #fff7d5;
+ margin: 5px;
+ border: 1px solid #e7d796;
+ color: #9a8c59;
+ display: flex;
+ align-items: center;
+}
+body.ttrss_main .article-note > * {
+ padding: 5px;
+}
+body.ttrss_main .article-note.editable {
+ cursor: pointer;
+}
+body.ttrss_main h1 {
+ font-size: 18px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+}
+body.ttrss_main h2 {
+ font-size: 16px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+}
+body.ttrss_main h3 {
+ font-size: 16px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+}
+body.ttrss_main h4 {
+ font-size: 14px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+}
+body.ttrss_main a {
+ color: #257aa7;
+ text-decoration: none;
+}
+body.ttrss_main a:hover {
+ color: #133d54;
+ text-decoration: underline;
+}
+body.ttrss_main #notify.visible {
+ opacity: 100;
+}
+body.ttrss_main #notify {
+ bottom: 20px;
+ right: 20px;
+ min-width: 200px;
+ max-width: 350px;
+ border-width: 1px;
+ border-style: solid;
+ position: fixed;
+ font-size: 14px;
+ z-index: 99;
+ display: flex;
+ opacity: 0;
+ align-items: center;
+ padding: 10px;
+ transition: opacity 0.2s linear;
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
+}
+body.ttrss_main #notify img {
+ vertical-align: middle;
+}
+body.ttrss_main #notify .msg {
+ flex-grow: 2;
+ padding: 0 10px;
+ line-height: 20px;
+}
+body.ttrss_main #notify .icon-close {
+ cursor: pointer;
+}
+body.ttrss_main .notify {
+ border-color: #d7c47a;
+ background-color: #fff7d5;
+}
+body.ttrss_main .notify.notify_progress {
+ border-color: #d7c47a;
+ background-color: #fff7d5;
+}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
+body.ttrss_main .notify.notify_info {
+ border-color: #257aa7;
+ background-color: #d5ebf6;
+}
+body.ttrss_main .notify.notify_info i.icon-notify {
+ color: #257aa7;
+}
+body.ttrss_main .notify.notify_error {
+ background-color: #c00;
+ border-color: #900;
+ color: white;
+}
+body.ttrss_main .notify.notify_error i.icon-notify,
+body.ttrss_main .notify.notify_error i.icon-close {
+ color: white;
+}
+body.ttrss_main .action-chooser .action-button .dijitButtonText {
+ vertical-align: unset;
+}
+body.ttrss_main .action-chooser .action-button .dijitArrowButtonInner {
+ display: none;
+}
+body.ttrss_main .hl {
+ border: 0px solid #ddd;
+ border-bottom-width: 1px;
+ transition: color 0.2s, background 0.2s;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ background: #f5f5f5;
+ align-items: center;
+ user-select: none;
+}
+body.ttrss_main .hl > * {
+ white-space: nowrap;
+ padding: 4px;
+}
+body.ttrss_main .hl img {
+ vertical-align: middle;
+}
+body.ttrss_main .hl .left,
+body.ttrss_main .hl .right {
+ display: flex;
+ align-items: center;
+}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .left i.material-icons,
+body.ttrss_main .hl .right i.material-icons {
+ margin-left: 2px;
+ padding: 2px;
+ transition: color 0.2s linear;
+ user-select: none;
+ font-size: 21px;
+}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
+body.ttrss_main .hl .right i.material-icons {
+ color: #777;
+}
+body.ttrss_main .hl .title {
+ cursor: pointer;
+ flex-grow: 2;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main .hl .author {
+ white-space: nowrap;
+ color: black;
+ font-size: 11px;
+ font-weight: normal;
+}
+body.ttrss_main .hl .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px;
+ font-size: 11px;
+ font-style: italic;
+ font-weight: normal;
+ color: black;
+}
+body.ttrss_main .hl .feed a:hover {
+ color: #257aa7;
+}
+body.ttrss_main .hl .updated {
+ color: black;
+ text-align: right;
+ font-size: 11px;
+ padding-left: 10px;
+}
+body.ttrss_main .hl .updated div {
+ display: inline-block;
+}
+body.ttrss_main .hl div.title a {
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #555;
+}
+body.ttrss_main .hl a.title.high,
+body.ttrss_main .hl span.hl-content.high .preview {
+ color: #00aa00;
+}
+body.ttrss_main .hl.vgrlf .feed {
+ display: none;
+}
+body.ttrss_main .hl.Unread {
+ background: white;
+}
+body.ttrss_main .hl.Unread .title a {
+ color: black;
+}
+body.ttrss_main .hl.active .title a {
+ color: #257aa7;
+ /* text-shadow : 1px 1px 2px #fff; */
+}
+body.ttrss_main .hl.active {
+ background: #257aa7 ! important;
+}
+body.ttrss_main .hl.active,
+body.ttrss_main .hl.Selected {
+ color: white;
+ background: #3f728e;
+}
+body.ttrss_main .hl.active a,
+body.ttrss_main .hl.Selected a,
+body.ttrss_main .hl.active .feed a,
+body.ttrss_main .hl.Selected .feed a,
+body.ttrss_main .hl.active .hl-content a.title,
+body.ttrss_main .hl.Selected .hl-content a.title,
+body.ttrss_main .hl.active span,
+body.ttrss_main .hl.Selected span {
+ color: white;
+}
+body.ttrss_main #content-insert blockquote,
+body.ttrss_main #headlines-frame blockquote,
+body.ttrss_main .dijitContentPane blockquote {
+ margin: 5px 0px 5px 0px;
+ color: black;
+ padding-left: 10px;
+ border: 0px solid #ccc;
+ border-left-width: 4px;
+}
+body.ttrss_main #content-insert code,
+body.ttrss_main #headlines-frame code,
+body.ttrss_main .dijitContentPane code {
+ color: #009900;
+ font-family: monospace;
+}
+body.ttrss_main #content-insert pre,
+body.ttrss_main #headlines-frame pre,
+body.ttrss_main .dijitContentPane pre {
+ margin: 5px 0px 5px 0px;
+ padding: 10px;
+ color: black;
+ font-family: monospace;
+ font-size: 12px;
+ border: 0px solid #ccc;
+ background: #f5f5f5;
+ display: block;
+ max-width: 98%;
+ overflow: auto;
+ white-space: pre-wrap;
+}
+body.ttrss_main div.prefHelp {
+ color: black;
+ padding: 5px;
+}
+body.ttrss_main span.preview {
+ color: #999;
+ font-weight: normal;
+ font-size: 12px;
+ padding-left: 4px;
+}
+body.ttrss_main .label {
+ display: inline-block;
+ vertical-align: middle;
+ background-color: #fff7d5;
+ font-size: 9px;
+ color: black;
+ font-weight: normal;
+ margin-left: 2px;
+ padding: 2px 4px;
+ white-space: nowrap;
+}
+body.ttrss_main i.marked-pic,
+body.ttrss_main i.pub-pic {
+ cursor: pointer;
+ color: #ccc;
+}
+body.ttrss_main #overlay {
+ background: white;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 100%;
+ z-index: 100;
+ position: absolute;
+}
+body.ttrss_main #overlay_inner {
+ font-weight: bold;
+ margin: 1em;
+}
+body.ttrss_main div.whiteBox {
+ margin-left: 1px;
+ text-align: center;
+ padding: 1em 1em 0px 1em;
+ font-size: 11px;
+ border: 0px solid #ddd;
+ border-bottom-width: 1px;
+}
+body.ttrss_main .dijitDialog header,
+body.ttrss_main .dijitDialog .dlgSec,
+body.ttrss_main .dijitDialog .dlgSecHoriz {
+ font-size: 16px;
+ font-weight: 600;
+ color: black;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+body.ttrss_main .dijitDialog section,
+body.ttrss_main .dijitDialog .dlgSecCont {
+ margin: 10px 20px;
+}
+body.ttrss_main .dijitDialog header.horizontal + section,
+body.ttrss_main .dijitDialog section.horizontal,
+body.ttrss_main .dijitDialog .dlgSecHoriz + .dlgSecCont {
+ margin: 10px 0;
+}
+body.ttrss_main .dijitDialog section.narrow {
+ margin: 0;
+}
+body.ttrss_main .dijitDialog section fieldset > label,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset > label,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset > label {
+ font-weight: bold;
+ margin-right: 10px;
+ display: inline-block;
+ min-width: 140px;
+ text-align: right;
+}
+body.ttrss_main .dijitDialog section fieldset > label.checkbox,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset > label.checkbox,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset > label.checkbox {
+ font-weight: normal;
+ display: inline;
+}
+body.ttrss_main .dijitDialog section fieldset > label.inline,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset > label.inline,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset > label.inline {
+ display: inline;
+}
+body.ttrss_main .dijitDialog section fieldset,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset {
+ border-width: 0px;
+ padding: 5px 0px;
+}
+body.ttrss_main .dijitDialog section fieldset.narrow,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset.narrow,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset.narrow {
+ padding: 2px 0px;
+}
+body.ttrss_main .dijitDialog section fieldset.align-right,
+body.ttrss_main .dijitDialog div.dlgSecCont fieldset.align-right,
+body.ttrss_main .dijitDialog div.dlgSecSimple fieldset.align-right {
+ text-align: right;
+}
+body.ttrss_main .dijitDialog footer,
+body.ttrss_main .dijitDialog .dlgButtons {
+ margin-top: 5px;
+ text-align: right;
+}
+body.ttrss_main .dijitDialog footer.text-center {
+ text-align: center;
+}
+body.ttrss_main .dijitDialog textarea#tags_str {
+ height: 100px;
+ font-size: 12px;
+ width: 98%;
+}
+body.ttrss_main i.icon-label {
+ color: #fff7d5;
+}
+body.ttrss_main div#cmdline {
+ position: absolute;
+ left: 5px;
+ bottom: 5px;
+ font-size: 11px;
+ color: black;
+ font-weight: bold;
+ background-color: white;
+ border: 1px solid #257aa7;
+ padding: 3px 5px 3px 5px;
+ z-index: 5;
+}
+body.ttrss_main .exception-contents h3 {
+ color: red;
+}
+body.ttrss_main .exception-contents textarea {
+ width: 99%;
+ height: 200px;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-wrap-inner,
+body.ttrss_main #content-wrap {
+ padding: 0;
+ border: 0;
+ margin: 0;
+}
+body.ttrss_main #feeds-holder {
+ padding: 0;
+ border: 0 solid #ddd;
+ overflow: hidden;
+ background: #f5f5f5;
+ box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
+ -webkit-overflow-scrolling: touch;
+}
+body.ttrss_main #feeds-holder #feedTree {
+ height: 100%;
+ overflow-x: hidden;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
+ font-weight: bold;
+ display: none;
+ font-size: 9px;
+ text-align: center;
+ border: 1px solid #2a89bc;
+ color: white;
+ background: #2a89bc;
+ border-radius: 4px;
+ line-height: 14px;
+ margin-right: 8px;
+ min-width: 23px;
+ height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #f5f5f5;
+ color: #1a1a1a;
+ border-color: #dcdcdc;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #257aa7;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
+ font-weight: bold;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
+ color: red;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
+ box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
+ border-color: #ddd transparent;
+ background: white;
+ color: black;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
+ margin-right: 2px;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #333333;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
+ position: relative;
+ color: #ffc069;
+ font-size: 21px;
+ left: -2px;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
+ color: #ff7c4b;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
+ color: #69C671;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
+ font-weight: bold;
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #f5f5f5;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: white;
+ border: 1px solid #ddd;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
+body.ttrss_main #headlines-frame {
+ padding: 0;
+ border: 0;
+ margin-top: 0;
+ -webkit-overflow-scrolling: touch;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: black;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: black;
+ padding: 10px;
+ display: block;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame .feed-title {
+ border: 0px solid #257aa7;
+ border-bottom-width: 1px;
+ padding: 5px 8px;
+}
+body.ttrss_main #headlines-frame .feed-title a.title {
+ color: black;
+ font-weight: bold;
+}
+body.ttrss_main #headlines-frame .feed-title a {
+ color: black;
+}
+body.ttrss_main #headlines-frame .feed-title a:hover {
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame span.hlMenuAttach {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ user-select: none;
+}
+body.ttrss_main #toolbar-frame_splitter {
+ display: none;
+}
+body.ttrss_main #toolbar-frame {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ white-space: nowrap;
+ font-size: 13px;
+}
+body.ttrss_main #toolbar-frame #toolbar {
+ background: white;
+ border: 0 solid #ddd;
+ border-bottom-width: 1px;
+ padding-left: 4px;
+ height: 32px;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ color: black;
+ font-size: 13px;
+ align-items: center;
+}
+body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
+body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
+body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
+ border: 0;
+}
+body.ttrss_main #toolbar-frame #toolbar i.net-alert,
+body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
+ color: red;
+}
+body.ttrss_main #toolbar-frame #toolbar i.log-alert {
+ color: #ddba1c;
+ cursor: pointer;
+}
+body.ttrss_main #toolbar-frame #toolbar i {
+ margin: 0 4px;
+}
+body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
+ font-size: 13px;
+ background: transparent;
+ padding-right: 4px;
+ flex-grow: 2;
+ display: flex;
+}
+body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left {
+ flex-grow: 2;
+ display: flex;
+ align-items: center;
+}
+body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
+ margin-left: 4px;
+}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
+body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
+ display: flex;
+ align-items: center;
+}
+body.ttrss_main #toolbar-frame #toolbar #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
+body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
+ font-style: italic;
+ text-align: right;
+ margin-right: 4px;
+ color: #257aa7;
+}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
+ display: none;
+ }
+}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
+body.ttrss_main #header {
+ text-align: right;
+ color: black;
+ padding: 5px 5px 0 0px;
+ position: absolute;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
+ z-index: 5;
+}
+body.ttrss_main #header i.net-alert,
+body.ttrss_main #header .left i.icon-error {
+ color: red;
+}
+body.ttrss_main #header i.log-alert {
+ color: #ddba1c;
+ cursor: pointer;
+}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
+body.ttrss_main #header i {
+ margin: 0 4px;
+}
+body.ttrss_main #content-insert {
+ padding: 0;
+ border: 0;
+ line-height: 1.5;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+body.ttrss_main img.feed-icon,
+body.ttrss_main img.icon {
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ vertical-align: middle;
+ display: inline-block;
+}
+body.ttrss_main ul#filterDlg_Matches,
+body.ttrss_main ul#filterDlg_Actions {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+body.ttrss_main ul#filterDlg_Matches li,
+body.ttrss_main ul#filterDlg_Actions li {
+ cursor: pointer;
+}
+body.ttrss_main ul#filterDlg_Matches li .dijitCheckBox,
+body.ttrss_main ul#filterDlg_Actions li .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main ul.hotkeys-help li {
+ display: flex;
+}
+body.ttrss_main ul.hotkeys-help li.desc {
+ flex-grow: 2;
+}
+body.ttrss_main ul.hotkeys-help .hk {
+ color: #257aa7;
+ width: 100px;
+}
+body.ttrss_main ul.hotkeys-help h3 {
+ margin: 8px 0px;
+}
+body.ttrss_main select.attachments {
+ display: block;
+ margin-top: 10px;
+ max-width: 120px;
+}
+body.ttrss_main #filterDlg_feeds select {
+ height: 150px;
+ width: 410px;
+}
+body.ttrss_main span.highlight {
+ background-color: #ffff00;
+ color: #cc90cc;
+}
+body.ttrss_main #feedEditDlg img.feedIcon {
+ border: 1px solid #ccc;
+ padding: 5px;
+ margin: 5px;
+ max-width: 20px;
+ max-height: 20px;
+ height: auto;
+ width: auto;
+}
+body.ttrss_main .dijitTooltipContents {
+ background: #1c5c7d;
+ color: #f5f5f5;
+}
+body.ttrss_main .dijitTooltipRight .dijitTooltipConnector {
+ border-right-color: #1c5c7d;
+}
+body.ttrss_main .dijitTooltipLeft .dijitTooltipConnector {
+ border-left-color: #1c5c7d;
+}
+body.ttrss_main .dijitTooltipBelow .dijitTooltipConnector {
+ border-bottom-color: #1c5c7d;
+}
+body.ttrss_main .dijitTooltipAbove .dijitTooltipConnector {
+ border-top-color: #1c5c7d;
+}
+/*body.ttrss_main .dijitDialog {
+ h1:first-of-type,
+ h2:first-of-type,
+ h3:first-of-type,
+ h4:first-of-type {
+ margin-top: 0px;
+ }
+}*/
+body.ttrss_main[view-mode="marked"] #feeds-holder #feedTree .dijitTreeRow.Has_Marked .dijitTreeLabel {
+ color: #257aa7;
+}
+body.ttrss_main[view-mode="marked"] #feeds-holder #feedTree .dijitTreeRow.Has_Marked .counterNode.marked {
+ display: inline-block;
+}
+body.ttrss_main[view-mode="marked"][hide-read-feeds="true"][hide-read-shows-special="true"] #feeds-holder #feedTree .dijitTreeRow:not(.AlwaysVisible):not(.Special):not(.Has_Marked) {
+ display: none;
+}
+body.ttrss_main[view-mode="marked"][hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.AlwaysVisible):not(.Has_Marked) {
+ display: none;
+}
+body.ttrss_main:not([view-mode="marked"]) #feeds-holder #feedTree .dijitTreeRow.Unread .counterNode.unread {
+ display: inline-block;
+}
+body.ttrss_main:not([view-mode="marked"]) #feeds-holder #feedTree .dijitTreeRow.Has_Aux:not(.Unread) .counterNode.aux {
+ display: inline-block;
+}
+body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="true"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible):not(.Special) {
+ display: none;
+}
+body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
+ display: none;
+}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
+body.ttrss_main #toolbar-headlines i.icon-syndicate {
+ color: #ff7c4b;
+ margin-right: 8px;
+ border: 1px solid #ff7c4b;
+ border-radius: 4px;
+}
+body.ttrss_main #toolbar-headlines #feed_current_unread {
+ margin-left: 8px;
+ font-weight: bold;
+ text-align: center;
+ border: 1px solid #2a89bc;
+ color: white;
+ background: #2a89bc;
+ border-radius: 4px;
+ min-width: 23px;
+}
+body.ttrss_main i.icon-no-feed {
+ opacity: 0.2;
+}
+body.ttrss_main .dijitTreeRow.UpdatesDisabled .dijitTreeLabel {
+ opacity: 0.5;
+}
+body.ttrss_main .cdm.marked .left i.marked-pic,
+body.ttrss_main .hl.marked .left i.marked-pic {
+ color: #ffc069;
+}
+body.ttrss_main .cdm.published .left i.pub-pic,
+body.ttrss_main .hl.published .left i.pub-pic {
+ color: #ff7c4b;
+}
+body.ttrss_main .score-high i.icon-score {
+ color: #69C671;
+}
+body.ttrss_main .score-low i.icon-score {
+ color: #500;
+}
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #777;
+}
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
+ cursor: pointer;
+}
+body.ttrss_main .panel {
+ border: 1px solid #ddd;
+ background: #f5f5f5;
+ padding: 4px;
+}
+body.ttrss_main .dijitDialog .panel {
+ background: white;
+}
+body.ttrss_main .panel-scrollable {
+ overflow: auto;
+ height: 200px;
+}
+body.ttrss_main .panel-scrollable-400px {
+ overflow: auto;
+ height: 400px;
+}
+body.ttrss_main ul.list li {
+ padding: 2px;
+}
+body.ttrss_main ul.list {
+ padding: 4px;
+}
+body.ttrss_main ul.list-unstyled {
+ list-style-type: none;
+}
+body.ttrss_main .text-center {
+ text-align: center;
+}
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
+ margin: 8px;
+}
+body.ttrss_main .dijitDialog .filter-results-list .title {
+ font-weight: bold;
+}
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
+}
+body.ttrss_main .alert,
+body.ttrss_utility .alert {
+ padding: 8px 35px 8px 14px;
+ margin-bottom: 10px;
+ background-color: #fcf8e3;
+ border: 1px solid #fbeed5;
+ border-radius: 4px;
+}
+body.ttrss_main .alert .close,
+body.ttrss_utility .alert .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ line-height: 20px;
+ cursor: pointer;
+}
+body.ttrss_main .pull-right,
+body.ttrss_utility .pull-right {
+ float: right;
+}
+body.ttrss_main .pull-left,
+body.ttrss_utility .pull-left {
+ float: left;
+}
+body.ttrss_main .pre-wrap,
+body.ttrss_utility .pre-wrap {
+ white-space: pre-wrap;
+}
+body.ttrss_main .text-error,
+body.ttrss_utility .text-error {
+ color: #b94a48;
+}
+body.ttrss_main .text-info,
+body.ttrss_utility .text-info {
+ color: #3a87ad;
+}
+body.ttrss_main .text-success,
+body.ttrss_utility .text-success {
+ color: #468847;
+}
+body.ttrss_main .text-warning,
+body.ttrss_utility .text-warning {
+ color: #a47e3c;
+}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: black;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
+body.ttrss_main .alert,
+body.ttrss_utility .alert,
+body.ttrss_main .alert h4,
+body.ttrss_utility .alert h4 {
+ color: #c09853;
+}
+body.ttrss_main .alert h4,
+body.ttrss_utility .alert h4 {
+ margin: 0;
+}
+body.ttrss_main .alert-success,
+body.ttrss_utility .alert-success {
+ color: #468847;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+body.ttrss_main .alert-success h4,
+body.ttrss_utility .alert-success h4 {
+ color: #468847;
+}
+body.ttrss_main .alert-danger,
+body.ttrss_utility .alert-danger,
+body.ttrss_main .alert-error,
+body.ttrss_utility .alert-error {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #eed3d7;
+}
+body.ttrss_main .alert-danger h4,
+body.ttrss_utility .alert-danger h4,
+body.ttrss_main .alert-error h4,
+body.ttrss_utility .alert-error h4 {
+ color: #b94a48;
+}
+body.ttrss_main .alert-info,
+body.ttrss_utility .alert-info {
+ color: #3a87ad;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+body.ttrss_main .alert-info h4,
+body.ttrss_utility .alert-info h4 {
+ color: #3a87ad;
+}
+body.ttrss_main hr,
+body.ttrss_utility hr {
+ border: 0px solid #ccc;
+ border-bottom-width: 1px;
+}
+::selection {
+ background: #257aa7;
+ color: white;
+}
+::-webkit-scrollbar {
+ width: 4px;
+}
+::-webkit-scrollbar-thumb {
+ background-color: #257aa7;
+}
+::-webkit-scrollbar-track {
+ background-color: #eee;
+}
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
+}
+.cdm .header,
+.cdm .footer {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+}
+.cdm .header img,
+.cdm .footer img,
+.cdm .footer i.material-icons {
+ margin: 0 4px;
+ vertical-align: middle;
+}
+.cdm .header-sticky-guard {
+ height: 0;
+}
+.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
+ align-items: center;
+}
+.cdm .header > * {
+ padding: 4px;
+ white-space: nowrap;
+}
+.cdm .header .left,
+.cdm .header .right {
+ display: flex;
+ align-items: center;
+}
+.cdm .header .left i.material-icons,
+.cdm .header .right i.material-icons {
+ margin-left: 2px;
+ padding: 2px;
+ transition: color 0.2s linear;
+ user-select: none;
+ font-size: 21px;
+}
+.cdm .header .titleWrap {
+ flex-grow: 2;
+}
+.cdm .header .updated {
+ color: black;
+ font-weight: normal;
+ font-size: 11px;
+ white-space: nowrap;
+}
+.cdm .header input {
+ margin: 0px 4px;
+}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: black;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: black;
+ font-size: 11px;
+ font-weight: normal;
+}
+.cdm .footer {
+ height: 30px;
+ padding-left: 5px;
+ font-weight: normal;
+ color: black;
+ clear: both;
+ align-items: center;
+}
+.cdm .footer i.material-icons {
+ color: #777;
+}
+.cdm .footer .left {
+ flex-grow: 2;
+}
+.cdm .intermediate {
+ margin-top: 10px;
+ margin-left: 10px;
+ line-height: 1.5;
+}
+.cdm .content-inner {
+ margin: 10px;
+ line-height: 1.5;
+ font-size: 16px;
+}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
+.cdm .intermediate img,
+.cdm .intermediate video,
+.cdm .content-inner img,
+.cdm .content-inner video {
+ border-width: 0px;
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
+.cdm.expanded .collapse,
+.cdm.expanded .excerpt {
+ display: none;
+}
+.cdm.expanded .titleWrap {
+ white-space: normal;
+}
+.cdm.expanded .footer {
+ border: 0px solid #ddd;
+ border-bottom-width: 1px;
+}
+.cdm.expanded > hr {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+.cdm.expanded .header a.title {
+ font-size: 16px;
+ color: #999;
+ font-weight: 600;
+ transition: color 0.2s, background 0.2s;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
+}
+.cdm.expanded.active .header .title {
+ color: #257aa7;
+}
+.cdm.expanded.Unread .header .title {
+ color: black;
+}
+.cdm.expanded .content {
+ color: black;
+}
+.cdm.vgrlf .feed {
+ display: none;
+}
+.cdm .feed-title {
+ border: 0px solid #257aa7;
+ border-bottom-width: 1px;
+ padding: 5px 3px 5px 5px;
+}
+.cdm .feed-title a.title {
+ color: black;
+ font-weight: bold;
+}
+.cdm .feed-title a {
+ color: black;
+}
+.cdm .feed-title a:hover {
+ color: #257aa7;
+}
+.cdm .content-inner .embed-responsive {
+ overflow: hidden;
+ padding-bottom: 56.25%;
+ position: relative;
+}
+.cdm .content-inner .embed-responsive iframe {
+ border: 0;
+ bottom: 0;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+.cdm.expandable {
+ background-color: #f5f5f5;
+ border: 0px solid #ddd;
+ border-bottom-width: 1px;
+}
+.cdm.expandable > hr {
+ display: none;
+}
+.cdm.expandable div.header span.titleWrap {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.cdm.expandable .excerpt {
+ white-space: nowrap;
+ font-size: 11px;
+ color: #999;
+ font-weight: normal;
+ cursor: pointer;
+}
+.cdm.expandable:not(.active) {
+ user-select: none;
+}
+.cdm.expandable.Unread {
+ background: white;
+}
+.cdm.expandable.Selected:not(.active) {
+ background: #3f728e;
+}
+.cdm.expandable.Selected:not(.active) a,
+.cdm.expandable.Selected:not(.active) .header a.title,
+.cdm.expandable.Selected:not(.active) span {
+ color: white;
+}
+.cdm.expandable.active {
+ background: white ! important;
+}
+.cdm.expandable.active div.header span.titleWrap {
+ white-space: normal;
+}
+.cdm.expandable .header a.title {
+ font-weight: 600;
+ color: black;
+ font-size: 14px;
+ transition: color 0.2s, background 0.2s;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.cdm.expandable.Unread div.header a.title {
+ color: black;
+}
+.cdm.expandable.active .collapse i.material-icons {
+ color: #257aa7;
+ cursor: pointer;
+}
+.cdm.expandable.active .excerpt {
+ display: none;
+}
+.cdm.expandable.active div.header a.title {
+ color: #257aa7;
+ font-size: 16px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.cdm.expandable:not(.active) {
+ cursor: pointer;
+}
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
+ display: none;
+}
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
+ box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
+ border: 0 solid #ddd;
+ border-bottom-width: 1px;
+ background: white ! important;
+ opacity: 0.9;
+ backdrop-filter: blur(6px);
+}
+body.ttrss_prefs {
+ background-color: #f5f5f5;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+}
+body.ttrss_prefs h1,
+body.ttrss_prefs h2,
+body.ttrss_prefs h3,
+body.ttrss_prefs h4 {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 600;
+ color: black;
+}
+body.ttrss_prefs .dijitContentPane > h1:first-of-type,
+body.ttrss_prefs .dijitContentPane > h2:first-of-type,
+body.ttrss_prefs .dijitContentPane > h3:first-of-type {
+ margin-top: 0;
+}
+body.ttrss_prefs #footer,
+body.ttrss_prefs #header {
+ padding: 8px;
+ font-size: 13px;
+}
+body.ttrss_prefs #header {
+ float: right;
+}
+body.ttrss_prefs #footer_splitter {
+ display: none;
+}
+body.ttrss_prefs #footer {
+ background-color: #f5f5f5;
+ font-size: 13px;
+ border: 0px;
+ text-align: center;
+}
+body.ttrss_prefs #header img {
+ vertical-align: middle;
+ cursor: pointer;
+}
+body.ttrss_prefs .dijitTree#filterTree .dijitTreeIcon,
+body.ttrss_prefs .dijitTree#labelTree .dijitTreeIcon,
+body.ttrss_prefs .dijitTree#filterTree .dijitTreeIcon {
+ display: none;
+}
+body.ttrss_prefs .dijitAccordionTitle i.material-icons {
+ top: -1px;
+ position: relative;
+}
+body.ttrss_prefs .dijitAccordionTitleSelected i.material-icons {
+ color: white;
+}
+body.ttrss_prefs #feedsTab {
+ background: #f5f5f5;
+}
+body.ttrss_prefs .dijitDialog #pref-profiles-list .dijitInlineEditBoxDisplayMode {
+ padding: 0px;
+}
+body.ttrss_prefs #pref_feeds_errors_btn {
+ color: red;
+}
+body.ttrss_prefs .user-css-editor {
+ height: 300px;
+ width: 575px;
+}
+body.ttrss_prefs fieldset.prefs {
+ min-height: 30px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+body.ttrss_prefs fieldset.prefs label:first-of-type {
+ min-width: 300px;
+}
+body.ttrss_prefs fieldset.prefs .help-text {
+ display: inline-block;
+ margin-left: 10px;
+}
+body.ttrss_prefs fieldset.prefs .help-text-bottom {
+ margin-top: 10px;
+}
+body.ttrss_prefs table th {
+ text-align: left;
+}
+body.ttrss_prefs table td.checkbox {
+ text-align: center;
+ width: 32px;
+}
+body.ttrss_prefs ul.prefs-plugin-list {
+ margin: 0;
+ padding: 0;
+}
+body.ttrss_prefs ul.prefs-plugin-list li {
+ display: flex;
+ align-items: center;
+ border-bottom: #ddd 1px solid;
+ line-height: 30px;
+}
+body.ttrss_prefs ul.prefs-plugin-list li.text-center {
+ border: 0;
+ display: block;
+}
+body.ttrss_prefs ul.prefs-plugin-list li > * {
+ padding: 8px;
+}
+body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+}
+body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
+ cursor: auto;
+}
+body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
+ flex-grow: 2;
+ display: inline-block;
+ text-align: right;
+ font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
+}
+body.ttrss_prefs ul.prefs-plugin-list li .actions {
+ flex-grow: 2;
+ text-align: right;
+}
+body.ttrss_prefs ul.prefs-plugin-list li .version {
+ min-width: 200px;
+ text-align: right;
+}
+body.ttrss_prefs .plugin-installer-list li,
+body.ttrss_prefs .plugin-updater-list li {
+ border-bottom: #ddd 1px solid;
+}
+body.ttrss_prefs .plugin-installer-list li > *,
+body.ttrss_prefs .plugin-updater-list li > * {
+ padding: 8px 4px;
+}
+body.ttrss_prefs .plugin-installer-list li > pre,
+body.ttrss_prefs .plugin-updater-list li > pre {
+ margin: 0;
+}
+body.ttrss_prefs .plugin-installer-list li h3,
+body.ttrss_prefs .plugin-updater-list li h3 {
+ margin: 0;
+}
+body.ttrss_prefs .plugin-installer-list li.text-center,
+body.ttrss_prefs .plugin-updater-list li.text-center {
+ border: 0;
+}
+body.ttrss_prefs .plugin-installer-list .plugin-installed > *,
+body.ttrss_prefs .plugin-updater-list .plugin-installed > * {
+ opacity: 0.5;
+}
+body.ttrss_prefs .users-list td,
+body.ttrss_prefs .event-log td,
+body.ttrss_prefs .users-list th,
+body.ttrss_prefs .event-log th {
+ cursor: pointer;
+ padding: 8px;
+ border-bottom: #ddd 1px solid;
+}
+body.ttrss_prefs .event-log tr td,
+body.ttrss_prefs .event-log tr th {
+ vertical-align: top;
+}
+body.ttrss_prefs .event-log tr .errno {
+ font-style: italic;
+ font-weight: bold;
+ white-space: nowrap;
+}
+body.ttrss_prefs .event-log tr .errstr {
+ word-break: break-all;
+ white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
+}
+body.ttrss_prefs .event-log tr .filename,
+body.ttrss_prefs .event-log tr .login,
+body.ttrss_prefs .event-log tr .timestamp {
+ color: black;
+}
+body.ttrss_prefs hr {
+ border-color: #ddd;
+ max-width: 100%;
+}
+body.ttrss_prefs .phpinfo table {
+ border-collapse: collapse;
+}
+body.ttrss_prefs .phpinfo td.e,
+body.ttrss_prefs .phpinfo td.v {
+ border: 1px solid #ccc;
+}
+body.ttrss_prefs .phpinfo td.e {
+ font-weight: bold;
+}
+body.ttrss_prefs .phpinfo td.v {
+ font-family: monospace;
+ word-break: break-all;
+}
+body.ttrss_prefs #filterNewRuleDlg .dijitValidationTextAreaError,
+body.ttrss_main #filterNewRuleDlg .dijitValidationTextAreaError {
+ background: #ffc0c0;
+}
+body.ttrss_prefs #filterNewRuleDlg .dijitValidationTextArea:not(.dijitValidationTextAreaError),
+body.ttrss_main #filterNewRuleDlg .dijitValidationTextArea:not(.dijitValidationTextAreaError) {
+ background: #c0ffc0;
+}
+body.ttrss_prefs fieldset,
+body.ttrss_utility fieldset {
+ border-width: 0px;
+ padding: 5px 0px;
+}
+body.ttrss_prefs fieldset.narrow,
+body.ttrss_utility fieldset.narrow {
+ padding: 2px 0px;
+}
+body.ttrss_prefs fieldset.align-right,
+body.ttrss_utility fieldset.align-right {
+ text-align: right;
+}
+body.ttrss_prefs fieldset > label:first-of-type,
+body.ttrss_utility fieldset > label:first-of-type {
+ min-width: 140px;
+ margin-right: 20px;
+ display: inline-block;
+ text-align: right;
+ font-weight: bold;
+}
+body.ttrss_prefs fieldset > label.checkbox,
+body.ttrss_utility fieldset > label.checkbox {
+ display: inline;
+ font-weight: normal;
+}
+body.ttrss_utility.sanity_failed {
+ background: #900;
+}
+body.ttrss_utility {
+ background: #f5f5f5;
+ color: black;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ margin: 4em;
+}
+body.ttrss_utility .content {
+ background: white;
+ border: 1px solid #ddd;
+ padding: 20px;
+ box-shadow: 0px 1px 1px -1px rgba(0, 0, 0, 0.1);
+}
+body.ttrss_utility .content h2:first-of-type {
+ margin-top: 0;
+}
+body.ttrss_utility .content h2,
+body.ttrss_utility .content h3,
+body.ttrss_utility .content h4 {
+ color: #257aa7;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+body.ttrss_utility .content h2 {
+ font-size: 18px;
+}
+body.ttrss_utility .content h3 {
+ font-size: 16px;
+}
+body.ttrss_utility a {
+ color: #257aa7;
+ text-decoration: none;
+}
+body.ttrss_utility a:hover,
+body.ttrss_utility a:focus {
+ color: #133d54;
+ text-decoration: underline;
+}
+body.ttrss_utility h1 {
+ color: gray;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ margin: 10px 0 0 0;
+}
+body.ttrss_utility .footer {
+ text-align: center;
+ padding-top: 10px;
+}
+body.ttrss_utility .footer a {
+ color: gray;
+}
+body.ttrss_utility .footer a:hover {
+ color: #257aa7;
+}
+body.ttrss_utility form {
+ margin: 0;
+}
+body.ttrss_utility.otp .content fieldset > label {
+ display: inline;
+}
+body.ttrss_utility.ttrss_login {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+body.ttrss_utility.ttrss_login .container {
+ max-width: 600px;
+ margin-left: auto;
+ margin-right: auto;
+}
+body.ttrss_utility.ttrss_login .container .content {
+ padding: 40px;
+}
+body.ttrss_utility.installer,
+body.ttrss_utility.feed_debugger {
+ margin: 2em;
+}
+body.ttrss_utility.installer pre,
+body.ttrss_utility.feed_debugger pre {
+ white-space: pre-wrap;
+}
+body.ttrss_utility.share_popup {
+ margin: 0;
+ padding: 0;
+ background: white;
+}
+body.ttrss_utility.share_popup .content {
+ padding: 15px;
+ border-width: 0;
+ box-shadow: none;
+}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
+.flat li {
+ padding: 2px;
+}
+.flat .dijitButton i.material-icons {
+ position: relative;
+ top: -1px;
+}
+.flat .tabLabel > i.material-icons {
+ position: relative;
+ top: -1px;
+}
+.flat #filterDlg_Matches .filterRule {
+ color: green;
+ word-break: break-all;
+}
+.flat #filterDlg_Matches .filterRule .field,
+.flat #filterDlg_Matches .filterRule .feed {
+ word-break: break-word;
+ font-style: italic;
+}
+.flat #filterTree .filterRules li.inverse,
+.flat #filterDlg_Matches span.filterRule.inverse {
+ color: red;
+}
+.flat .dijitToolbar {
+ font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
+}
+.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
+ line-height: 10px;
+}
+.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitPlaceHolder {
+ line-height: 15px;
+ margin-left: 0;
+}
+.flat .dijitToolbar label {
+ position: relative;
+ top: 2px;
+}
+.flat .dijitAccordionContainer {
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
+}
+.flat .dijitCheckBox.dijitCheckBoxChecked {
+ background-color: #69C671;
+ border-color: #45b74f;
+}
+.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
+ padding: 4px 8px;
+ font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
+ color: #2e99d1;
+}
+.flat .dijitMenu .dijitMenuItem td {
+ padding: 0;
+}
+.flat .dijitCheckBox {
+ margin: 1px;
+}
+.flat .dijitCheckBox:before {
+ font-family: "flat-icon";
+ content: "\f00c";
+ color: white;
+}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.flat .dijitTab i.material-icons,
+.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
+ color: #257aa7;
+}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
+.flat .dijitTree .dijitFolderClosed,
+.flat .dijitTree .dijitFolderOpened {
+ display: none;
+}
+.flat .dijitTree .dijitTreeRowSelected .filterRules li {
+ color: white;
+}
+.flat .dijitTree .dijitTreeRowSelected .dijitTreeExpando {
+ color: #257aa7;
+}
+.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
+ color: white;
+}
+.flat .dijitTree .labelParam {
+ float: right;
+ margin-right: 16px;
+}
+.flat .dijitTree .dijitTreeRow.filterDisabled {
+ opacity: 0.5;
+}
+.flat .dijitTree .dijitTreeRow.filterDisabled .filterRules {
+ filter: saturate(0%);
+}
+.flat .dijitTree .feedParam {
+ float: right;
+}
+.flat .dijitTree .filterRules {
+ font-size: 12px;
+ line-height: normal;
+ white-space: normal;
+ margin-left: 28px;
+}
+.flat .dijitTree .filterRules li {
+ color: green;
+}
+.flat .dijitTree .dijitTreeContainer {
+ max-width: 100%;
+}
+.flat .dijitTree .dijitTreeRow {
+ overflow: hidden;
+ -moz-user-select: none;
+ user-select: none;
+ text-overflow: ellipsis;
+}
+.flat label.dijitButton {
+ border: 1px solid #ccc;
+ padding: 6px;
+ border-radius: 4px;
+ cursor: pointer;
+ position: relative;
+ top: 1px;
+}
+.flat label.dijitButton:hover {
+ background-color: #f5f5f5;
+}
+.flat .dijitTree .dijitTreeNode .dijitTreeRow {
+ padding: 4px 0px 4px;
+ border-width: 1px;
+ color: black;
+}
+.flat .dijitDialog {
+ width: 600px;
+}
+@font-face {
+ font-family: 'Material Icons';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../vendor/mervick/material-design-icons/fonts/MaterialIcons-Regular.eot);
+ /* For IE6-8 */
+ src: local('Material Icons'), local('MaterialIcons-Regular'), url(../vendor/mervick/material-design-icons/fonts/MaterialIcons-Regular.woff2) format('woff2'), url(../vendor/mervick/material-design-icons/fonts/MaterialIcons-Regular.woff) format('woff'), url(../vendor/mervick/material-design-icons/fonts/MaterialIcons-Regular.ttf) format('truetype');
+}
+.material-icons {
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 18px;
+ /* Preferred icon size */
+ display: inline-block;
+ line-height: 1;
+ text-transform: none;
+ letter-spacing: normal;
+ word-wrap: normal;
+ white-space: nowrap;
+ direction: ltr;
+ vertical-align: middle;
+ /* Support for all WebKit browsers. */
+ -webkit-font-smoothing: antialiased;
+ /* Support for Safari and Chrome. */
+ text-rendering: optimizeLegibility;
+ /* Support for Firefox. */
+ -moz-osx-font-smoothing: grayscale;
+ /* Support for IE. */
+ font-feature-settings: 'liga';
+}
+.flat .dijitDialog .dijitDialogPaneContent {
+ background: #f5f5f5;
+}
+.flat .dijitTab:not(.dijitTabChecked) {
+ background: #f5f5f5;
+}
+.flat .dijitCheckBox {
+ background: #ccc;
+}
+body.ttrss_zoom {
+ max-width: 900px;
+ margin: 2em auto;
+}
+body.ttrss_zoom div.post {
+ border: 1px solid #ddd;
+ background: white;
+ box-shadow: 0px 1px 1px -1px rgba(0, 0, 0, 0.1);
+}
+body.ttrss_zoom div.post .attachments {
+ display: none;
+}
+body.ttrss_zoom div.post div.header {
+ padding-bottom: 8px;
+ border: 0 solid #ddd;
+ border-bottom-width: 1px;
+ background: white;
+ font-size: 13px;
+ color: black;
+}
+body.ttrss_zoom div.post div.header .row {
+ display: flex;
+ margin-bottom: 4px;
+ flex-wrap: nowrap;
+ align-items: center;
+ justify-content: space-between;
+}
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
+ font-size: 15px;
+ line-height: 1.5;
+ border-width: 0;
+ padding: 0;
+ padding-top: 8px;
+}
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
+ max-width: 760px;
+ height: auto;
+}
+body.ttrss_zoom div.post .content blockquote {
+ margin: 5px 0px 5px 0px;
+ color: black;
+ padding-left: 8px;
+ border: 0px solid #ddd;
+ border-left-width: 4px;
+}
+body.ttrss_zoom div.post .content code {
+ color: #009900;
+ font-family: monospace;
+ font-size: 12px;
+}
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
+ color: black;
+ font-family: monospace;
+ font-size: 12px;
+ border: 0px solid #ccc;
+ background: #f5f5f5;
+ display: block;
+ max-width: 98%;
+ overflow: auto;
+ white-space: pre-wrap;
+}
diff --git a/themes/light-high-contrast.less b/themes/light-high-contrast.less
new file mode 100644
index 000000000..eae190d32
--- /dev/null
+++ b/themes/light-high-contrast.less
@@ -0,0 +1,8 @@
+@import "light/defines.less";
+
+@default-fg: black;
+@default-text: @default-fg;
+
+@import "light/dijit_light.less";
+@import "light/zoom.less";
+@import "../lib/flat-ttrss/flat_combined.css";
diff --git a/themes/light.css b/themes/light.css
index 9a4ac98c0..d26e5f81b 100644
--- a/themes/light.css
+++ b/themes/light.css
@@ -11,71 +11,81 @@ body.ttrss_prefs,
}
body.ttrss_main {
background: white;
- color: black;
+ color: #555;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
}
body.ttrss_main :focus {
outline: none;
}
-body.ttrss_main div.post {
- padding: 0px;
+body.ttrss_main .post {
+ padding: 0;
font-size: 13px;
}
-body.ttrss_main div.post div.header {
+body.ttrss_main .post .header {
padding: 5px;
- color: #909090;
- border: 0px solid #ddd;
+ color: #555;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
background: #f5f5f5;
}
-body.ttrss_main div.post div.header .left,
-body.ttrss_main div.post div.header .right {
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
display: flex;
}
-body.ttrss_main div.post div.header .row {
+body.ttrss_main .post .header .row {
display: flex;
margin-bottom: 4px;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
}
-body.ttrss_main div.post div.header .comments {
+body.ttrss_main .post .header .comments {
flex-grow: 2;
}
-body.ttrss_main div.post div.header .date {
+body.ttrss_main .post .header .date {
white-space: nowrap;
}
-body.ttrss_main div.post div.header img,
-body.ttrss_main div.post div.header i.material-icons {
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
margin: 0px 4px;
vertical-align: middle;
color: #777;
}
-body.ttrss_main div.post div.header .title {
+body.ttrss_main .post .header .title {
flex-grow: 2;
font-size: 15px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main div.post div.content {
+body.ttrss_main .post div.content {
padding: 10px;
font-size: 16px;
}
-body.ttrss_main div.post div.content img,
-body.ttrss_main div.post div.content video {
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
border-width: 0px;
max-width: 98%;
height: auto;
}
-body.ttrss_main div.post div.content div.embed-responsive {
+body.ttrss_main .post div.content div.embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-body.ttrss_main div.post div.content div.embed-responsive iframe {
+body.ttrss_main .post div.content div.embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -172,6 +182,11 @@ body.ttrss_main .notify.notify_progress {
border-color: #d7c47a;
background-color: #fff7d5;
}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
body.ttrss_main .notify.notify_info {
border-color: #257aa7;
background-color: #d5ebf6;
@@ -217,6 +232,10 @@ body.ttrss_main .hl .right {
display: flex;
align-items: center;
}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
body.ttrss_main .hl .left i.material-icons,
body.ttrss_main .hl .right i.material-icons {
margin-left: 2px;
@@ -225,25 +244,28 @@ body.ttrss_main .hl .right i.material-icons {
user-select: none;
font-size: 21px;
}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
body.ttrss_main .hl .right i.material-icons {
color: #777;
}
-body.ttrss_main .hl div.title {
+body.ttrss_main .hl .title {
cursor: pointer;
flex-grow: 2;
overflow: hidden;
text-overflow: ellipsis;
}
-body.ttrss_main .hl span.author {
+body.ttrss_main .hl .author {
white-space: nowrap;
color: #555;
font-size: 11px;
font-weight: normal;
}
-body.ttrss_main .hl div.right {
- text-align: right;
-}
-body.ttrss_main .hl span.feed a {
+body.ttrss_main .hl .feed a {
border-radius: 4px;
display: inline-block;
padding: 1px 4px;
@@ -252,29 +274,22 @@ body.ttrss_main .hl span.feed a {
font-weight: normal;
color: #555;
}
-body.ttrss_main .hl span.feed a:hover {
+body.ttrss_main .hl .feed a:hover {
color: #257aa7;
}
-body.ttrss_main .hl span.updated {
+body.ttrss_main .hl .updated {
color: #555;
text-align: right;
font-size: 11px;
padding-left: 10px;
}
-body.ttrss_main .hl span.updated div {
+body.ttrss_main .hl .updated div {
display: inline-block;
}
-body.ttrss_main .hl div.left input {
- margin: 0px 4px;
-}
-body.ttrss_main .hl div.left img,
-body.ttrss_main .hl div.right img {
- margin: 0px 4px;
-}
body.ttrss_main .hl div.title a {
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #555;
}
body.ttrss_main .hl a.title.high,
@@ -287,10 +302,10 @@ body.ttrss_main .hl.vgrlf .feed {
body.ttrss_main .hl.Unread {
background: white;
}
-body.ttrss_main .hl.Unread div.title a {
+body.ttrss_main .hl.Unread .title a {
color: black;
}
-body.ttrss_main .hl.active div.title a {
+body.ttrss_main .hl.active .title a {
color: #257aa7;
/* text-shadow : 1px 1px 2px #fff; */
}
@@ -312,9 +327,6 @@ body.ttrss_main .hl.active span,
body.ttrss_main .hl.Selected span {
color: white;
}
-body.ttrss_main .hl.Grayed {
- color: #909090;
-}
body.ttrss_main #content-insert blockquote,
body.ttrss_main #headlines-frame blockquote,
body.ttrss_main .dijitContentPane blockquote {
@@ -360,7 +372,7 @@ body.ttrss_main .label {
vertical-align: middle;
background-color: #fff7d5;
font-size: 9px;
- color: black;
+ color: #555;
font-weight: normal;
margin-left: 2px;
padding: 2px 4px;
@@ -371,45 +383,6 @@ body.ttrss_main i.pub-pic {
cursor: pointer;
color: #ccc;
}
-body.ttrss_main div.errorExplained {
- border: 1px solid #ddd;
- margin: 5px 0px 5px 0px;
- padding: 5px;
-}
-body.ttrss_main ul.browseFeedList {
- height: 300px;
- width: 100%;
- overflow: auto;
- border-width: 0px 1px 1px 1px;
- border-color: #ddd;
- border-style: solid;
- margin: 0px 0px 5px 0px;
- background-color: white;
- list-style-type: none;
- padding: 0px;
-}
-body.ttrss_main ul.browseFeedList li {
- display: flex;
- align-items: center;
-}
-body.ttrss_main ul.browseFeedList li > * {
- margin: 2px;
-}
-body.ttrss_main .browseFeedList span.subscribers {
- color: #808080;
-}
-body.ttrss_main ul.compact {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main ul.compact li {
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main .noborder {
- border-width: 0px;
-}
body.ttrss_main #overlay {
background: white;
left: 0;
@@ -423,11 +396,6 @@ body.ttrss_main #overlay_inner {
font-weight: bold;
margin: 1em;
}
-body.ttrss_main div.loadingPrompt {
- padding: 1em;
- text-align: center;
- font-weight: bold;
-}
body.ttrss_main div.whiteBox {
margin-left: 1px;
text-align: center;
@@ -436,20 +404,13 @@ body.ttrss_main div.whiteBox {
border: 0px solid #ddd;
border-bottom-width: 1px;
}
-body.ttrss_main div#headlines-frame.wide .title {
- overflow: visible;
- white-space: normal;
-}
-body.ttrss_main div#headlines-frame.wide .hl .feed {
- display: none;
-}
body.ttrss_main .dijitDialog header,
body.ttrss_main .dijitDialog .dlgSec,
body.ttrss_main .dijitDialog .dlgSecHoriz {
font-size: 16px;
font-weight: 600;
color: #555;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_main .dijitDialog section,
body.ttrss_main .dijitDialog .dlgSecCont {
@@ -527,11 +488,6 @@ body.ttrss_main div#cmdline {
padding: 3px 5px 3px 5px;
z-index: 5;
}
-body.ttrss_main #feed_browser_spinner {
- vertical-align: middle;
- height: 18px;
- width: 18px;
-}
body.ttrss_main .exception-contents h3 {
color: red;
}
@@ -540,14 +496,15 @@ body.ttrss_main .exception-contents textarea {
height: 200px;
font-size: 11px;
}
+body.ttrss_main #headlines-wrap-inner,
body.ttrss_main #content-wrap {
- padding: 0px;
- border-width: 0px;
- margin: 0px;
+ padding: 0;
+ border: 0;
+ margin: 0;
}
body.ttrss_main #feeds-holder {
- padding: 0px;
- border: 0px solid #ddd;
+ padding: 0;
+ border: 0 solid #ddd;
overflow: hidden;
background: #f5f5f5;
box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
@@ -557,19 +514,26 @@ body.ttrss_main #feeds-holder #feedTree {
height: 100%;
overflow-x: hidden;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- background: #f5f5f5;
- color: #6f6f6f;
- border-color: #dcdcdc;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- border-color: #257aa7;
- background: #ffffff;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
font-weight: bold;
display: none;
font-size: 9px;
@@ -578,111 +542,215 @@ body.ttrss_main #feeds-holder #feedTree .counterNode {
color: white;
background: #2a89bc;
border-radius: 4px;
- vertical-align: middle;
- float: right;
- position: relative;
line-height: 14px;
margin-right: 8px;
- margin-top: 2px;
min-width: 23px;
height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #f5f5f5;
+ color: #6f6f6f;
+ border-color: #dcdcdc;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #257aa7;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .loadingExpando {
- left: -3px;
- height: 22px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
position: relative;
- top: -3px;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeLabel.Unread {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
font-weight: bold;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow.Error .dijitTreeLabel {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
color: red;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
- border: 1px solid transparent;
-}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRowSelected {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
border-color: #ddd transparent;
background: white;
- color: #333;
+ color: #555;
}
-body.ttrss_main #feeds-holder #feedTree .dijitIcon.feed-icon {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
margin-right: 2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
- color: #555;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #888888;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-archive {
- color: #c77b2e;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-star {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
position: relative;
color: #ffc069;
font-size: 21px;
left: -2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-rss_feed {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
color: #ff7c4b;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-whatshot {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
color: #69C671;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-restore {
- position: relative;
- top: -1px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
font-weight: bold;
color: #257aa7;
}
-body.ttrss_main #headlines-wrap-inner {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #f5f5f5;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: white;
+ border: 1px solid #ddd;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
}
-body.ttrss_main #headlines-frame[is-vfeed="0"] .header .feed {
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
display: none;
}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
body.ttrss_main #headlines-frame {
- padding: 0px;
- border: 0px #ddd;
- margin-top: 0px;
+ padding: 0;
+ border: 0;
+ margin-top: 0;
-webkit-overflow-scrolling: touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: #555;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: #555;
+ padding: 10px;
+ display: block;
}
-body.ttrss_main #headlines-frame div.feed-title {
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 8px;
}
-body.ttrss_main #headlines-frame div.feed-title a.title {
+body.ttrss_main #headlines-frame .feed-title a.title {
color: #555;
font-weight: bold;
}
-body.ttrss_main #headlines-frame div.feed-title a {
+body.ttrss_main #headlines-frame .feed-title a {
color: #555;
}
-body.ttrss_main #headlines-frame div.feed-title a:hover {
+body.ttrss_main #headlines-frame .feed-title a:hover {
color: #257aa7;
}
body.ttrss_main #headlines-frame span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
body.ttrss_main #toolbar-frame_splitter {
display: none;
}
body.ttrss_main #toolbar-frame {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+ padding: 0;
+ margin: 0;
+ border: 0;
white-space: nowrap;
- font-size: 12px;
+ font-size: 13px;
}
body.ttrss_main #toolbar-frame #toolbar {
background: white;
- border: 0px solid #ddd;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
padding-left: 4px;
height: 32px;
@@ -690,13 +758,13 @@ body.ttrss_main #toolbar-frame #toolbar {
flex-direction: row;
flex-wrap: nowrap;
color: #555;
- font-size: 12px;
+ font-size: 13px;
align-items: center;
}
body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
- border: 0px;
+ border: 0;
}
body.ttrss_main #toolbar-frame #toolbar i.net-alert,
body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
@@ -710,7 +778,7 @@ body.ttrss_main #toolbar-frame #toolbar i {
margin: 0 4px;
}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
- font-size: 12px;
+ font-size: 13px;
background: transparent;
padding-right: 4px;
flex-grow: 2;
@@ -725,6 +793,12 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
margin-left: 4px;
}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
display: flex;
align-items: center;
@@ -739,20 +813,26 @@ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
margin-right: 4px;
color: #257aa7;
}
-@media (max-width: 992px) {
+@media (max-width: 768px) {
body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
display: none;
}
}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
body.ttrss_main #header {
- border-width: 0px;
text-align: right;
color: #555;
- padding: 5px 5px 0px 0px;
- margin: 0px;
+ padding: 5px 5px 0 0px;
position: absolute;
- right: 0px;
- top: 0px;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
z-index: 5;
}
body.ttrss_main #header i.net-alert,
@@ -771,9 +851,8 @@ body.ttrss_main #header i {
margin: 0 4px;
}
body.ttrss_main #content-insert {
- padding: 0px;
- border-color: #ddd;
- border-width: 0px;
+ padding: 0;
+ border: 0;
line-height: 1.5;
overflow: auto;
-webkit-overflow-scrolling: touch;
@@ -786,59 +865,11 @@ body.ttrss_main img.icon {
vertical-align: middle;
display: inline-block;
}
-body.ttrss_main .player {
- display: inline-block;
- color: #555;
- font-size: 11px;
- font-family: sans-serif;
- border: 1px solid #555;
- padding: 0px 4px 0px 4px;
- margin: 0px 2px 0px 2px;
- width: 50px;
- text-align: center;
- background: white;
-}
-body.ttrss_main .player.playing {
- color: #00c000;
- border-color: #00c000;
-}
-body.ttrss_main .player:hover {
- background: #f5f5f5;
- cursor: pointer;
-}
-body.ttrss_main #headlines-frame.auto_catchup #headlines-spacer {
- height: 100%;
-}
-body.ttrss_main #headlines-spacer {
- margin-left: 1px;
- text-align: center;
- color: #555;
- font-size: 11px;
- font-style: italic;
-}
-body.ttrss_main #headlines-spacer a,
-body.ttrss_main #headlines-spacer span {
- color: #555;
- padding: 10px;
- display: block;
-}
-body.ttrss_main #headlines-spacer a:hover {
- color: #257aa7;
-}
body.ttrss_main ul#filterDlg_Matches,
body.ttrss_main ul#filterDlg_Actions {
list-style-type: none;
margin: 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
body.ttrss_main ul#filterDlg_Matches li,
body.ttrss_main ul#filterDlg_Actions li {
@@ -874,9 +905,6 @@ body.ttrss_main span.highlight {
background-color: #ffff00;
color: #cc90cc;
}
-body.ttrss_main #headlines-frame .dijitCheckBox {
- margin-right: 4px;
-}
body.ttrss_main #feedEditDlg img.feedIcon {
border: 1px solid #ccc;
padding: 5px;
@@ -934,6 +962,11 @@ body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-show
body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
display: none;
}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
body.ttrss_main #toolbar-headlines i.icon-syndicate {
color: #ff7c4b;
margin-right: 8px;
@@ -970,10 +1003,15 @@ body.ttrss_main .score-high i.icon-score {
body.ttrss_main .score-low i.icon-score {
color: #500;
}
-body.ttrss_main .score-neutral i.icon-score {
- opacity: 0.5;
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #777;
}
-body.ttrss_main i.icon-score {
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
cursor: pointer;
}
body.ttrss_main .panel {
@@ -1004,20 +1042,62 @@ body.ttrss_main ul.list-unstyled {
body.ttrss_main .text-center {
text-align: center;
}
-body.ttrss_main #prefFilterTestResultList .preview {
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
margin: 8px;
}
-body.ttrss_main #prefFilterTestResultList .title {
+body.ttrss_main .dijitDialog .filter-results-list .title {
font-weight: bold;
}
-body.ttrss_main #prefFilterTestResultList .feed {
- color: #257aa7;
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
}
body.ttrss_main .alert,
body.ttrss_utility .alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1058,6 +1138,16 @@ body.ttrss_main .text-warning,
body.ttrss_utility .text-warning {
color: #a47e3c;
}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: #555;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
body.ttrss_main .alert,
body.ttrss_utility .alert,
body.ttrss_main .alert h4,
@@ -1107,41 +1197,6 @@ body.ttrss_utility hr {
border: 0px solid #ccc;
border-bottom-width: 1px;
}
-body.ttrss_main .text-muted,
-body.ttrss_utility .text-muted {
- color: #555;
-}
-body.ttrss_main .small,
-body.ttrss_utility .small {
- font-size: 11px;
-}
-body.ttrss_main div.autocomplete,
-body.ttrss_utility div.autocomplete {
- position: absolute;
- width: 250px;
- background-color: white;
- border: 1px solid #ddd;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul,
-body.ttrss_utility div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul li.selected,
-body.ttrss_utility div.autocomplete ul li.selected {
- background-color: #e6e6e6;
-}
-body.ttrss_main div.autocomplete ul li,
-body.ttrss_utility div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
- cursor: pointer;
-}
::selection {
background: #257aa7;
color: white;
@@ -1155,16 +1210,13 @@ body.ttrss_utility div.autocomplete ul li {
::-webkit-scrollbar-track {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
- display: none;
-}
-.cdm i.material-icons {
- color: #777;
-}
-.cdm .header {
- position: sticky;
- top: 0;
- z-index: 3;
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
}
.cdm .header,
.cdm .footer {
@@ -1175,13 +1227,16 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header img,
.cdm .footer img,
.cdm .footer i.material-icons {
- margin: 0px 4px;
+ margin: 0 4px;
vertical-align: middle;
}
.cdm .header-sticky-guard {
height: 0;
}
.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
align-items: center;
}
.cdm .header > * {
@@ -1204,7 +1259,7 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header .titleWrap {
flex-grow: 2;
}
-.cdm .header span.updated {
+.cdm .header .updated {
color: #555;
font-weight: normal;
font-size: 11px;
@@ -1213,6 +1268,30 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header input {
margin: 0px 4px;
}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: #555;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: #555;
+ font-size: 11px;
+ font-weight: normal;
+}
.cdm .footer {
height: 30px;
padding-left: 5px;
@@ -1221,30 +1300,37 @@ video::-webkit-media-controls-overlay-play-button {
clear: both;
align-items: center;
}
+.cdm .footer i.material-icons {
+ color: #777;
+}
.cdm .footer .left {
flex-grow: 2;
}
.cdm .intermediate {
margin-top: 10px;
margin-left: 10px;
+ line-height: 1.5;
}
.cdm .content-inner {
margin: 10px;
line-height: 1.5;
font-size: 16px;
}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
.cdm .intermediate img,
.cdm .intermediate video,
.cdm .content-inner img,
.cdm .content-inner video {
border-width: 0px;
max-width: 98%;
+ width: auto;
height: auto;
}
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-}
.cdm.expanded .collapse,
.cdm.expanded .excerpt {
display: none;
@@ -1257,72 +1343,54 @@ video::-webkit-media-controls-overlay-play-button {
border-bottom-width: 1px;
}
.cdm.expanded > hr {
- margin-top: 0px;
- margin-bottom: 0px;
+ margin-top: 0;
+ margin-bottom: 0;
}
-div.cdm.expanded div.header a.title {
+.cdm.expanded .header a.title {
font-size: 16px;
color: #999;
font-weight: 600;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expanded.active {
- background: white;
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
}
-div.cdm.expanded.active div.header a.title {
+.cdm.expanded.active .header .title {
color: #257aa7;
}
-div.cdm.expanded.Unread div.header a.title {
+.cdm.expanded.Unread .header .title {
color: black;
}
-div.cdm.expanded div.content {
+.cdm.expanded .content {
color: #555;
}
-div.cdm.expanded.Unread div.content {
- color: black;
-}
-div.cdm.active div.content {
- color: black;
-}
-div.cdm.vgrlf .feed {
+.cdm.vgrlf .feed {
display: none;
}
-.cdm div.feed-title {
+.cdm .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 3px 5px 5px;
}
-.cdm div.feed-title a.title {
+.cdm .feed-title a.title {
color: #555;
font-weight: bold;
}
-.cdm div.feed-title a {
+.cdm .feed-title a {
color: #555;
}
-.cdm div.feed-title a:hover {
+.cdm .feed-title a:hover {
color: #257aa7;
}
-.cdm div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
-}
-.cdm div.header div.feed,
-.cdm div.header div.feed a {
- vertical-align: middle;
- color: #555;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
-}
-.cdm div.content-inner div.embed-responsive {
+.cdm .content-inner .embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-.cdm div.content-inner div.embed-responsive iframe {
+.cdm .content-inner .embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -1331,17 +1399,6 @@ div.cdm.vgrlf .feed {
top: 0;
width: 100%;
}
-.cdm div.header span.author {
- white-space: nowrap;
- color: #555;
- font-size: 11px;
- font-weight: normal;
-}
-.cdm .feed a {
- border-radius: 4px;
- display: inline-block;
- padding: 1px 4px 1px 4px;
-}
.cdm.expandable {
background-color: #f5f5f5;
border: 0px solid #ddd;
@@ -1379,43 +1436,43 @@ div.cdm.vgrlf .feed {
.cdm.expandable.active {
background: white ! important;
}
-div.cdm.expandable.active div.header span.titleWrap {
+.cdm.expandable.active div.header span.titleWrap {
white-space: normal;
}
-div.cdm.expandable div.header a.title {
+.cdm.expandable .header a.title {
font-weight: 600;
color: #555;
font-size: 14px;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable.Unread div.header a.title {
+.cdm.expandable.Unread div.header a.title {
color: black;
}
-div.cdm.expandable.active .collapse i.material-icons {
+.cdm.expandable.active .collapse i.material-icons {
color: #257aa7;
cursor: pointer;
}
-div.cdm.expandable.active .excerpt {
+.cdm.expandable.active .excerpt {
display: none;
}
-div.cdm.expandable.active div.header a.title {
+.cdm.expandable.active div.header a.title {
color: #257aa7;
font-size: 16px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable:not(.active) {
+.cdm.expandable:not(.active) {
cursor: pointer;
}
-div.cdm.expandable:not(.active) .content,
-div.cdm.expandable:not(.active) .collapse {
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
display: none;
}
-div.cdm.expandable.active .header[stuck],
-div.cdm.expanded .header[stuck] {
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
border: 0 solid #ddd;
border-bottom-width: 1px;
@@ -1432,7 +1489,7 @@ body.ttrss_prefs h1,
body.ttrss_prefs h2,
body.ttrss_prefs h3,
body.ttrss_prefs h4 {
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 600;
color: #555;
}
@@ -1503,14 +1560,6 @@ body.ttrss_prefs fieldset.prefs .help-text {
body.ttrss_prefs fieldset.prefs .help-text-bottom {
margin-top: 10px;
}
-body.ttrss_prefs fieldset.plugin label.description {
- width: 550px;
- margin-right: 150px;
- display: inline-block;
-}
-body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox {
- margin-right: 10px;
-}
body.ttrss_prefs table th {
text-align: left;
}
@@ -1538,17 +1587,26 @@ body.ttrss_prefs ul.prefs-plugin-list li > * {
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
display: flex;
align-items: center;
- min-width: 300px;
cursor: pointer;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
cursor: auto;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
}
body.ttrss_prefs ul.prefs-plugin-list li .actions {
flex-grow: 2;
@@ -1602,6 +1660,11 @@ body.ttrss_prefs .event-log tr .errno {
body.ttrss_prefs .event-log tr .errstr {
word-break: break-all;
white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
}
body.ttrss_prefs .event-log tr .filename,
body.ttrss_prefs .event-log tr .login,
@@ -1665,7 +1728,7 @@ body.ttrss_utility.sanity_failed {
}
body.ttrss_utility {
background: #f5f5f5;
- color: black;
+ color: #555;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
margin: 4em;
@@ -1683,7 +1746,7 @@ body.ttrss_utility .content h2,
body.ttrss_utility .content h3,
body.ttrss_utility .content h4 {
color: #257aa7;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_utility .content h2 {
font-size: 18px;
@@ -1702,7 +1765,7 @@ body.ttrss_utility a:focus {
}
body.ttrss_utility h1 {
color: gray;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
margin: 10px 0 0 0;
}
@@ -1758,12 +1821,16 @@ body.ttrss_utility.share_popup .content {
border-width: 0;
box-shadow: none;
}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
.flat li {
padding: 2px;
}
-.flat #feedTree .dijitTreeContent .dijitInline {
- vertical-align: baseline;
-}
.flat .dijitButton i.material-icons {
position: relative;
top: -1px;
@@ -1787,7 +1854,8 @@ body.ttrss_utility.share_popup .content {
}
.flat .dijitToolbar {
font-size: 13px;
- padding: 0px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
}
.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
line-height: 10px;
@@ -1810,12 +1878,13 @@ body.ttrss_utility.share_popup .content {
.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
padding: 4px 8px;
font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
color: #2e99d1;
}
.flat .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ padding: 0;
}
.flat .dijitCheckBox {
margin: 1px;
@@ -1825,10 +1894,33 @@ body.ttrss_utility.share_popup .content {
content: "\f00c";
color: white;
}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
.flat .dijitTab i.material-icons,
.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
color: #257aa7;
}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
.flat .dijitTree .dijitFolderClosed,
.flat .dijitTree .dijitFolderOpened {
display: none;
@@ -1842,10 +1934,6 @@ body.ttrss_utility.share_popup .content {
.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
color: white;
}
-.flat .dijitTree .dijitTreeRow .dijitTreeExpando {
- position: relative;
- top: -2px;
-}
.flat .dijitTree .labelParam {
float: right;
margin-right: 16px;
@@ -1874,6 +1962,7 @@ body.ttrss_utility.share_popup .content {
.flat .dijitTree .dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
.flat label.dijitButton {
@@ -1948,11 +2037,11 @@ body.ttrss_zoom div.post .attachments {
display: none;
}
body.ttrss_zoom div.post div.header {
- padding-bottom: 10px;
- border: 0px solid #ddd;
+ padding-bottom: 8px;
+ border: 0 solid #ddd;
border-bottom-width: 1px;
background: white;
- font-size: 12px;
+ font-size: 13px;
color: #555;
}
body.ttrss_zoom div.post div.header .row {
@@ -1962,32 +2051,36 @@ body.ttrss_zoom div.post div.header .row {
align-items: center;
justify-content: space-between;
}
-body.ttrss_zoom div.post div.content {
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
font-size: 15px;
line-height: 1.5;
border-width: 0;
padding: 0;
+ padding-top: 8px;
}
-body.ttrss_zoom div.post div.content img,
-body.ttrss_zoom div.post div.content video {
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
max-width: 760px;
height: auto;
}
-body.ttrss_zoom div.post div.content blockquote {
+body.ttrss_zoom div.post .content blockquote {
margin: 5px 0px 5px 0px;
color: #555;
- padding-left: 10px;
+ padding-left: 8px;
border: 0px solid #ddd;
border-left-width: 4px;
}
-body.ttrss_zoom div.post div.content code {
+body.ttrss_zoom div.post .content code {
color: #009900;
font-family: monospace;
font-size: 12px;
}
-body.ttrss_zoom div.post div.content pre {
- margin: 5px 0px 5px 0px;
- padding: 10px;
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
color: #555;
font-family: monospace;
font-size: 12px;
diff --git a/themes/light/cdm.less b/themes/light/cdm.less
index 3a5b602f2..41d789a09 100644
--- a/themes/light/cdm.less
+++ b/themes/light/cdm.less
@@ -1,13 +1,7 @@
.cdm {
- i.material-icons {
+ /*i.material-icons {
color : @color-icon;
- }
-
- .header {
- position: sticky;
- top : 0;
- z-index: 3;
- }
+ }*/
.header, .footer {
display : flex;
@@ -17,7 +11,7 @@
.header img, .footer img,
.footer i.material-icons {
- margin : 0px 4px;
+ margin : 0 4px;
vertical-align: middle;
}
@@ -26,6 +20,9 @@
}
.header {
+ position: sticky;
+ top : 0;
+ z-index: 3;
align-items : center;
> * {
@@ -50,16 +47,43 @@
flex-grow : 2;
}
- span.updated {
+ .updated {
color : @default-text;
font-weight : normal;
- font-size : 11px;
+ font-size : @font-size-small;
white-space : nowrap;
}
input {
margin : 0px 4px;
}
+
+ .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+
+ a {
+ border-radius : 4px;
+ display : inline-block;
+ padding : 1px 4px 1px 4px;
+ }
+ }
+
+ .feed, .feed a {
+ vertical-align: middle;
+ color: @default-text;
+ font-weight: normal;
+ font-style: italic;
+ font-size: @font-size-small;
+ }
+
+ .author {
+ white-space : nowrap;
+ color : @default-text;
+ font-size : @font-size-small;
+ font-weight : normal;
+ }
}
.footer {
@@ -70,6 +94,10 @@
clear : both;
align-items : center;
+ i.material-icons {
+ color : @color-icon;
+ }
+
.left {
flex-grow : 2;
}
@@ -78,6 +106,7 @@
.intermediate {
margin-top : 10px;
margin-left : 10px;
+ line-height : 1.5;
}
.content-inner {
@@ -86,112 +115,100 @@
font-size : 16px;
}
+ .intermediate iframe,
+ .content-inner iframe {
+ max-width : 98%;
+ width : auto;
+ height : auto;
+ }
+
.intermediate img,
.intermediate video,
.content-inner img,
.content-inner video {
border-width : 0px;
max-width : 98%;
+ width : auto;
height : auto;
}
-}
-
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-
- .collapse, .excerpt {
- display : none;
- }
- .titleWrap {
- white-space : normal;
- }
-
- .footer {
- border: 0px solid @border-default;
- border-bottom-width: 1px;
- }
+ &.expanded {
- > hr {
- margin-top : 0px;
- margin-bottom : 0px;
- }
+ .collapse, .excerpt {
+ display : none;
+ }
-}
+ .titleWrap {
+ white-space : normal;
+ }
-div.cdm.expanded div.header a.title {
- font-size : 16px;
- color : #999;
- font-weight : 600;
- transition : color 0.2s, background 0.2s;
- text-rendering: optimizelegibility;
- font-family : @fonts-ui-bold;
-}
+ .footer {
+ border: 0px solid @border-default;
+ border-bottom-width: 1px;
+ }
-div.cdm.expanded.active {
- background : white;
-}
+ > hr {
+ margin-top : 0;
+ margin-bottom : 0;
+ }
-div.cdm.expanded.active div.header a.title {
- color : @color-link;
-}
+ .header a.title {
+ font-size : 16px;
+ color : #999;
+ font-weight : 600;
+ transition : color 0.2s, background 0.2s;
+ text-rendering: optimizelegibility;
+ font-family : @fonts-ui;
+ }
-div.cdm.expanded.Unread div.header a.title {
- color : black;
-}
+ &.active,
+ &.Unread {
+ .content {
+ color : black;
+ }
+ }
-div.cdm.expanded div.content {
- color : @default-text;
-}
+ &.active {
+ .header .title {
+ color : @color-link;
+ }
+ }
-div.cdm.expanded.Unread div.content {
- color : black;
-}
+ &.Unread {
+ .header .title {
+ color : black;
+ }
+ }
-div.cdm.active div.content {
- color : black;
-}
+ .content {
+ color : @default-text;
+ }
+ }
-div.cdm.vgrlf .feed {
- display : none;
-}
+ &.vgrlf .feed {
+ display : none;
+ }
-.cdm {
- div.feed-title {
+ .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;
- }
+ a.title {
+ color: @default-text;
+ font-weight: bold;
+ }
- div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
- }
+ a {
+ color: @default-text;
+ }
- div.header div.feed, div.header div.feed a {
- vertical-align: middle;
- color: @default-text;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
+ a:hover {
+ color: @color-link;
+ }
}
- div.content-inner div.embed-responsive {
+ .content-inner .embed-responsive {
overflow : hidden;
padding-bottom : @embed-responsive-padding;
position : relative;
@@ -207,115 +224,99 @@ div.cdm.vgrlf .feed {
}
}
- div.header span.author {
- white-space : nowrap;
- color : @default-text;
- font-size : 11px;
- font-weight : normal;
- }
-
- .feed a {
- border-radius : 4px;
- display : inline-block;
- padding : 1px 4px 1px 4px;
- }
-}
-
-.cdm.expandable {
- background-color : @color-panel-bg;
- border: 0px solid @border-default;
- border-bottom-width: 1px;
-
- > hr {
- display : none;
- }
+ &.expandable {
+ background-color : @color-panel-bg;
+ border: 0px solid @border-default;
+ border-bottom-width: 1px;
- div.header span.titleWrap {
- white-space : nowrap;
- text-overflow : ellipsis;
- overflow : hidden;
- }
+ > hr {
+ display : none;
+ }
- .excerpt {
- white-space : nowrap;
- font-size : 11px;
- color : #999;
- font-weight : normal;
- cursor : pointer;
- }
+ div.header span.titleWrap {
+ white-space : nowrap;
+ text-overflow : ellipsis;
+ overflow : hidden;
+ }
-}
+ .excerpt {
+ white-space : nowrap;
+ font-size : @font-size-small;
+ color : #999;
+ font-weight : normal;
+ cursor : pointer;
+ }
-.cdm.expandable:not(.active) {
- user-select : none;
-}
+ &:not(.active) {
+ user-select : none;
+ }
-.cdm.expandable.Unread {
- background : white;
-}
+ &.Unread {
+ background : white;
+ }
-.cdm.expandable.Selected:not(.active) {
- background : desaturate(@color-accent, 25%);
+ &.Selected:not(.active) {
+ background : desaturate(@color-accent, 25%);
- a,
- .header a.title,
- span {
- color : white;
- }
-}
+ a,
+ .header a.title,
+ span {
+ color : white;
+ }
+ }
-.cdm.expandable.active {
- background : white ! important;
-}
+ &.active {
+ background : white ! important;
+ }
-div.cdm.expandable.active div.header span.titleWrap {
- white-space : normal;
-}
+ &.active div.header span.titleWrap {
+ white-space : normal;
+ }
-div.cdm.expandable div.header a.title {
- font-weight : 600;
- color : @default-text;
- font-size : 14px;
- transition : color 0.2s, background 0.2s;
- text-rendering: optimizelegibility;
- font-family : @fonts-ui-bold;
-}
+ .header a.title {
+ font-weight : 600;
+ color : @default-text;
+ font-size : @font-size-content;
+ transition : color 0.2s, background 0.2s;
+ text-rendering: optimizelegibility;
+ font-family : @fonts-ui;
+ }
-div.cdm.expandable.Unread div.header a.title {
- color : black;
-}
+ &.Unread div.header a.title {
+ color : black;
+ }
-div.cdm.expandable.active {
- .collapse i.material-icons {
- color : @color-accent;
- cursor : pointer;
- }
+ &.active {
+ .collapse i.material-icons {
+ color : @color-accent;
+ cursor : pointer;
+ }
- .excerpt {
- display: none;
- }
+ .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.header a.title {
+ color: @color-link;
+ font-size: 16px;
+ font-weight: 600;
+ text-rendering: optimizelegibility;
+ font-family: @fonts-ui;
+ }
+ }
-div.cdm.expandable:not(.active) {
- cursor : pointer;
+ &:not(.active) {
+ cursor : pointer;
- .content, .collapse {
- display : none;
+ .content, .collapse {
+ display : none;
+ }
+ }
}
-}
-div.cdm {
&.expandable.active,
&.expanded {
- .header[stuck] {
+ .header[data-is-stuck] {
box-shadow : 0 1px 1px -1px rgba(0,0,0,0.1);
border: 0 solid @border-default;
border-bottom-width: 1px;
diff --git a/themes/light/defines.less b/themes/light/defines.less
index dd3f62251..08896b4f1 100644
--- a/themes/light/defines.less
+++ b/themes/light/defines.less
@@ -1,7 +1,6 @@
-@fonts-ui-bold: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
-@fonts-ui: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+@fonts-ui: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
-@default-fg: black;
+@default-fg: #555;
@default-bg: white;
@color-accent: #257aa7;
@color-accent-light: lighten(@color-accent, 50%);
@@ -12,10 +11,22 @@
@color-panel-bg: #f5f5f5;
@color-checked: #69C671;
@border-default : #ddd;
-@default-text: #555;
+@default-text: @default-fg;
@color-icon: #777;
+@color-hl-icon: #ccc;
@color-tooltip-fg: @color-panel-bg;
@color-tooltip-bg: darken(@color-accent, 10%);
+@cdm-grid-padding: 8px;
+@cdm-grid-col-width: 600px;
+@font-size-tiny: 9px;
+@font-size-small: 11px;
+@font-size-toolbar: 13px;
+@font-size-content: 14px;
+
+@breakpoint-sm: 576px;
+@breakpoint-md: 768px;
+@breakpoint-lg: 992px;
+@breakpoint-xl: 1200px;
@embed-responsive-padding: 56.25%; // Use 56.25% for 16:9 aspect ratio, 75% for 4:3.
diff --git a/themes/light/dijit_basic.less b/themes/light/dijit_basic.less
index da1138986..f29461530 100644
--- a/themes/light/dijit_basic.less
+++ b/themes/light/dijit_basic.less
@@ -4,11 +4,11 @@
padding: 2px;
}
- #feedTree {
+ /*#feedTree {
.dijitTreeContent .dijitInline {
vertical-align : baseline;
}
- }
+ }*/
.dijitButton i.material-icons {
position: relative;
@@ -38,8 +38,9 @@
}
.dijitToolbar {
- font-size: 13px;
- padding: 0px;
+ font-size: @font-size-toolbar;
+ font-family: @fonts-ui;
+ padding: 0;
.dijitTextBox .dijitInputContainer {
.dijitInputInner {
@@ -67,27 +68,35 @@
border-color : darken(@color-checked, 10%);
}
- .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
- padding: 4px 8px;
- font-size: 13px;
- }
+ .dijitMenu {
+ .dijitMenuItem .dijitMenuItemLabel {
+ padding: 4px 8px;
+ font-size: @font-size-toolbar;
+ font-family: @fonts-ui;
+ }
- .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
- color : lighten(@color-accent, 10%);
- }
+ .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
+ color : lighten(@color-accent, 10%);
+ }
- .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ .dijitMenuItem td {
+ padding: 0;
+ }
}
.dijitCheckBox {
margin : 1px;
+
+ &:before {
+ font-family: "flat-icon";
+ content: "\f00c";
+ color: white;
+ }
}
- .dijitCheckBox:before {
- font-family: "flat-icon";
- content: "\f00c";
- color: white;
+ .dijitTab,
+ .dijitAccordionTitle {
+ font-family: @fonts-ui;
}
.dijitTab,
@@ -98,6 +107,23 @@
}
.dijitTree {
+ .dijitTreeRowFlex {
+ display : flex;
+ flex-direction : row;
+ align-items : center;
+
+ // AAAAAA (pushes element down)
+ .dijitTreeIcon {
+ font-size : inherit;
+ height : auto;
+ }
+
+ .dijitTreeExpando {
+ height : auto;
+ line-height : 0;
+ }
+ }
+
.dijitFolderClosed,
.dijitFolderOpened {
display : none;
@@ -117,10 +143,10 @@
color : white;
}
- .dijitTreeRow .dijitTreeExpando {
+ /*.dijitTreeRow .dijitTreeExpando {
position : relative;
top : -2px;
- }
+ }*/
.labelParam {
float: right;
@@ -157,6 +183,7 @@
.dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
@@ -169,10 +196,10 @@
cursor : pointer;
position: relative;
top : 1px;
- }
- label.dijitButton:hover {
- background-color : @color-panel-bg;
+ &:hover {
+ background-color : @color-panel-bg;
+ }
}
.dijitTree {
diff --git a/themes/light/prefs.less b/themes/light/prefs.less
index 15345bcb4..27e88d601 100644
--- a/themes/light/prefs.less
+++ b/themes/light/prefs.less
@@ -1,10 +1,10 @@
body.ttrss_prefs {
background-color : @color-panel-bg;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
+ font-size: @font-size-content;
h1, h2, h3, h4 {
- font-family : @fonts-ui-bold;
+ font-family : @fonts-ui;
font-weight : 600;
color : @default-text;
}
@@ -94,18 +94,6 @@ body.ttrss_prefs {
}
}
- fieldset.plugin {
- label.description {
- width : 550px;
- margin-right : 150px;
- display : inline-block;
-
- .dijitCheckBox {
- margin-right : 10px;
- }
- }
- }
-
table {
th {
text-align : left;
@@ -140,7 +128,6 @@ body.ttrss_prefs {
label.checkbox {
display : flex;
align-items : center;
- min-width : 300px;
cursor : pointer;
&.system {
@@ -148,10 +135,22 @@ body.ttrss_prefs {
}
.name {
+ min-width : 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight : bold;
+ margin-right : 20px;
+ }
+ }
+
+ @media (max-width: @breakpoint-lg) {
+ label.checkbox .name {
+ min-width : 200px ! important;
+ }
+
+ .version {
+ display : none;
}
}
@@ -217,6 +216,12 @@ body.ttrss_prefs {
.errstr {
word-break : break-all;
white-space : pre-wrap;
+ width : 30%;
+ }
+
+ .filename {
+ word-break: break-all;
+ width : 20%;
}
.filename, .login, .timestamp {
diff --git a/themes/light/tt-rss.less b/themes/light/tt-rss.less
index 36b73b4f4..088a3c7ff 100644
--- a/themes/light/tt-rss.less
+++ b/themes/light/tt-rss.less
@@ -2,21 +2,21 @@ body.ttrss_main {
background : @default-bg;
color : @default-fg;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
+ font-size: @font-size-content;
overflow : hidden;
:focus {
outline: none;
}
- div.post {
- padding : 0px;
- font-size : 13px;
+ .post {
+ padding : 0;
+ font-size : @font-size-toolbar;
- div.header {
+ .header {
padding : 5px;
- color : #909090;
- border: 0px solid @border-default;
+ color : @default-text;
+ border: 0 solid @border-default;
border-bottom-width: 1px;
background: @color-panel-bg;
@@ -51,7 +51,7 @@ body.ttrss_main {
font-size : 15px;
font-weight : 600;
text-rendering: optimizelegibility;
- font-family : @fonts-ui-bold;
+ font-family : @fonts-ui;
}
}
@@ -160,7 +160,7 @@ body.ttrss_main {
border-width : 1px;
border-style : solid;
position : fixed;
- font-size : 14px;
+ font-size : @font-size-content;
z-index : 99;
display : flex;
opacity: 0;
@@ -192,6 +192,12 @@ body.ttrss_main {
.notify.notify_progress {
border-color : #d7c47a;
background-color : #fff7d5;
+
+ img {
+ width : 18px;
+ height : 18px;
+ filter : saturate(0);
+ }
}
.notify.notify_info {
@@ -248,6 +254,10 @@ body.ttrss_main {
display : flex;
align-items : center;
+ img {
+ margin : 0 4px;
+ }
+
i.material-icons {
margin-left : 2px;
padding : 2px;
@@ -257,61 +267,57 @@ body.ttrss_main {
}
}
+ .left {
+ input {
+ margin : 0 4px;
+ }
+ }
+
.right {
+ text-align : right;
+
i.material-icons {
color : @color-icon;
}
}
- div.title {
+ .title {
cursor : pointer;
flex-grow : 2;
overflow : hidden;
text-overflow : ellipsis;
}
- span.author {
+ .author {
white-space : nowrap;
color : @default-text;
- font-size : 11px;
+ font-size : @font-size-small;
font-weight : normal;
}
- div.right {
- text-align : right;
- }
-
- span.feed a {
+ .feed a {
border-radius : 4px;
display : inline-block;
padding : 1px 4px;
- font-size : 11px;
+ font-size : @font-size-small;
font-style : italic;
font-weight : normal;
color : @default-text;
- }
- span.feed a:hover {
- color : @color-accent;
+ &:hover {
+ color : @color-accent;
+ }
}
- span.updated {
+ .updated {
color : @default-text;
text-align : right;
- font-size : 11px;
+ font-size : @font-size-small;
padding-left : 10px;
- }
-
- span.updated div {
- display : inline-block;
- }
-
- div.left input {
- margin : 0px 4px;
- }
- div.left img, div.right img {
- margin : 0px 4px;
+ div {
+ display : inline-block;
+ }
}
div.title a {
@@ -324,44 +330,40 @@ body.ttrss_main {
a.title.high, span.hl-content.high .preview {
color : #00aa00;
}
- }
- .hl.vgrlf .feed {
- display : none;
- }
-
- .hl.Unread {
- background : white;
- }
+ &.vgrlf .feed {
+ display : none;
+ }
- .hl.Unread div.title a {
- color : black;
- }
+ &.Unread {
+ background : white;
+ }
- .hl.active div.title a {
- color : @color-accent;
- /* text-shadow : 1px 1px 2px #fff; */
- }
+ &.Unread .title a {
+ color : black;
+ }
- .hl.active {
- background : @color-accent ! important;
- }
+ &.active .title a {
+ color : @color-accent;
+ /* text-shadow : 1px 1px 2px #fff; */
+ }
- .hl.active,
- .hl.Selected {
- color : white;
- background : desaturate(@color-accent, 25%);
+ &.active {
+ background : @color-accent ! important;
+ }
- a,
- .feed a,
- .hl-content a.title,
- span {
+ &.active,
+ &.Selected {
color : white;
- }
- }
+ background : desaturate(@color-accent, 25%);
- .hl.Grayed {
- color : #909090;
+ a,
+ .feed a,
+ .hl-content a.title,
+ span {
+ color : white;
+ }
+ }
}
#content-insert blockquote,
@@ -413,7 +415,7 @@ body.ttrss_main {
display : inline-block;
vertical-align: middle;
background-color : #fff7d5;
- font-size : 9px;
+ font-size : @font-size-tiny;
color : @default-fg;
font-weight : normal;
margin-left : 2px;
@@ -423,56 +425,19 @@ body.ttrss_main {
i.marked-pic, i.pub-pic {
cursor : pointer;
- color : #ccc;
- }
-
- div.errorExplained {
- border : 1px solid @border-default;
- margin : 5px 0px 5px 0px;
- padding : 5px;
+ color : @color-hl-icon;
}
- ul.browseFeedList {
- height : 300px;
- width : 100%;
- overflow : auto;
- border-width : 0px 1px 1px 1px;
- border-color : @border-default;
- border-style : solid;
- margin : 0px 0px 5px 0px;
- background-color : white;
- list-style-type : none;
- padding : 0px;
-
- li {
- display : flex;
- align-items : center;
-
- > * {
- margin : 2px;
- }
- }
- }
-
-
- .browseFeedList span.subscribers {
- color : #808080;
- }
-
- ul.compact {
+ /*ul.compact {
list-style-type : none;
- margin : 0px;
- padding : 0px;
+ margin : 0;
+ padding : 0;
li {
- margin : 0px;
- padding : 0px;
+ margin : 0;
+ padding : 0;
}
- }
-
- .noborder {
- border-width : 0px;
- }
+ }*/
#overlay {
background : @default-bg;
@@ -489,39 +454,22 @@ body.ttrss_main {
margin : 1em;
}
- div.loadingPrompt {
- padding : 1em;
- text-align : center;
- font-weight : bold;
- }
-
div.whiteBox {
margin-left : 1px;
text-align : center;
padding : 1em 1em 0px 1em;
- font-size : 11px;
+ font-size : @font-size-small;
border: 0px solid @border-default;
border-bottom-width: 1px;
}
- div#headlines-frame.wide {
- .title {
- overflow: visible;
- white-space: normal;
- }
-
- .hl .feed {
- display: none;
- }
- }
-
.dijitDialog {
header,
.dlgSec, .dlgSecHoriz {
font-size : 16px;
font-weight : 600;
color : @default-text;
- font-family: @fonts-ui-bold;
+ font-family: @fonts-ui;
}
section,
@@ -564,14 +512,14 @@ body.ttrss_main {
fieldset {
border-width : 0px;
padding : 5px 0px;
- }
- fieldset.narrow {
- padding : 2px 0px;
- }
+ &.narrow {
+ padding : 2px 0px;
+ }
- fieldset.align-right {
- text-align : right;
+ &.align-right {
+ text-align : right;
+ }
}
}
@@ -600,7 +548,7 @@ body.ttrss_main {
position : absolute;
left : 5px;
bottom : 5px;
- font-size : 11px;
+ font-size : @font-size-small;
color : @default-text;
font-weight : bold;
background-color : @default-bg;
@@ -609,12 +557,6 @@ body.ttrss_main {
z-index : 5;
}
- #feed_browser_spinner {
- vertical-align : middle;
- height : 18px;
- width : 18px;
- }
-
.exception-contents {
h3 {
color : red;
@@ -622,19 +564,20 @@ body.ttrss_main {
textarea {
width : 99%;
height : 200px;
- font-size : 11px;
+ font-size : @font-size-small;
}
}
+ #headlines-wrap-inner,
#content-wrap {
- padding : 0px;
- border-width : 0px;
- margin : 0px;
+ padding : 0;
+ border : 0;
+ margin : 0;
}
#feeds-holder {
- padding : 0px;
- border: 0px solid @border-default;
+ padding : 0;
+ border: 0 solid @border-default;
overflow : hidden;
background : @color-panel-bg;
box-shadow : inset -1px 0px 2px -1px rgba(0,0,0,0.1);
@@ -646,139 +589,293 @@ body.ttrss_main {
text-rendering: optimizelegibility;
font-family : @fonts-ui;
- .counterNode.aux, .counterNode.marked {
- background : @color-panel-bg;
- color : lighten(@default-text, 10%);
- border-color : darken(@color-panel-bg, 10%);
- }
+ .dijitTreeNode {
+ .dijitTreeRow {
+ border : 1px solid transparent;
+
+ &.Is_Feed {
+ .loadingNode {
+ left : -2px;
+ height : 14px;
+ width : 14px;
+ position : relative;
+ }
+ }
- .counterNode.marked {
- border-color : @color-accent-marked;
- background : lighten(@color-accent-marked, 60%);
- }
+ &.Is_Cat {
+ .loadingNode {
+ height : 11px;
+ width : 18px;
+ margin-left : 4px;
+ position : relative;
+ top : 2px;
+ }
+ }
- .counterNode {
- font-weight : bold;
- display : none;
- font-size : 9px;
- text-align : center;
- border : 1px solid lighten(@color-accent, 5%);;
- color : white;
- background : lighten(@color-accent, 5%);
- border-radius : 4px;
- vertical-align : middle;
- float : right;
- position : relative;
- line-height : 14px;
- margin-right : 8px;
- margin-top : 2px;
- min-width : 23px;
- height : 14px;
- }
+ .counterNode {
+ order : 2;
+ font-weight : bold;
+ display : none;
+ font-size : @font-size-tiny;
+ text-align : center;
+ border : 1px solid lighten(@color-accent, 5%);
+ color : white;
+ background : lighten(@color-accent, 5%);
+ border-radius : 4px;
+ //vertical-align : middle;
+ //float : right;
+ //position : relative;
+ line-height : 14px;
+ margin-right : 8px;
+ //margin-top : 2px;
+ min-width : 23px;
+ height : 14px;
+ flex-shrink : 0;
+
+ &.aux, &.marked {
+ background : @color-panel-bg;
+ color : lighten(@default-text, 10%);
+ border-color : darken(@color-panel-bg, 10%);
+ }
+
+ &.marked {
+ border-color : @color-accent-marked;
+ background : lighten(@color-accent-marked, 60%);
+ }
+ }
- .dijitTreeNode .loadingExpando {
- left : -3px;
- height : 22px;
- position : relative;
- top : -3px;
- }
+ // fresh
+ &[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: darken(@color-checked, 15%);
+ border-color: darken(@color-checked, 25%);
+ }
- .dijitTreeRow .dijitTreeLabel.Unread {
- font-weight : bold;
- }
+ .dijitTreeContent {
+ display : flex;
+ align-items : center;
+ flex-grow : 2;
+ min-width : 0;
+ }
- .dijitTreeRow.Error .dijitTreeLabel {
- color : red;
+ .dijitTreeLabel {
+ cursor : pointer;
+ min-width : 0;
+ overflow : hidden;
+ text-overflow : ellipsis;
+ position : relative;
+
+ // Segoe UI (@fonts-ui) seems to have wrong baseline set
+ // top : -0.5px;
+
+ &.Unread {
+ font-weight : bold;
+ }
+ }
+
+ &.Error .dijitTreeLabel {
+ color : red;
+ }
+
+ &.dijitTreeRowSelected {
+ box-shadow : -1px 0px 2px -1px rgba(0,0,0,0.1);
+ border-color : @border-default transparent;
+ background : @default-bg;
+ color : @default-text;
+ }
+
+ .dijitIcon.feed-icon {
+ margin-right : 2px;
+ }
+
+ i.icon.icon-inbox {
+ color : lighten(@default-text, 20%);
+ }
+
+ i.icon.icon-archive {
+ color : darken(@color-marked, 30%);
+ }
+
+ i.icon.icon-star {
+ position : relative;
+ color : @color-marked;
+ font-size : 21px;
+ left : -2px;
+ }
+
+ i.icon.icon-rss_feed {
+ color : @color-published;
+ }
+
+ i.icon.icon-whatshot {
+ color : @color-checked;
+ }
+
+ i.icon.icon-restore {
+ //position : relative;
+ //top : -1px;
+ font-weight : bold;
+ color : @color-accent;
+ }
+ }
}
+ }
+ }
+
+ #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display : grid;
+ grid-template-columns: repeat(auto-fit, minmax(@cdm-grid-col-width, 1fr));
+ padding : @cdm-grid-padding;
+ grid-gap : @cdm-grid-padding;
+ background-color: @color-panel-bg;
- .dijitTreeNode .dijitTreeRow {
- border : 1px solid transparent;
+ > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+ &.grid-span-row,
+ &:nth-last-child(2):nth-child(odd),
+ &:nth-last-child(1) {
+ grid-column : 1 e("/") -1;
}
+ }
- .dijitTreeNode .dijitTreeRowSelected {
- box-shadow : -1px 0px 2px -1px rgba(0,0,0,0.1);
- border-color : @border-default transparent;
+ .cdm.expanded {
+ .header, .content {
background : @default-bg;
- color : #333;
+ border : 1px solid @border-default;
+ overflow : hidden;
}
- .dijitIcon.feed-icon {
- margin-right : 2px;
+ .content {
+ border-top-width : 0;
+ padding : 0 4px 4px 4px;
}
- i.icon.icon-inbox {
- color : #555;
+ .header[data-is-stuck] {
+ top : -@cdm-grid-padding;
+ border-bottom-width: 1px;
}
- i.icon.icon-archive {
- color : #c77b2e;
- }
+ .header {
+ border-bottom-width : 0;
+ padding : 4px;
- i.icon.icon-star {
- position : relative;
- color : @color-marked;
- font-size : 21px;
- left : -2px;
- }
+ .icon-grid-span {
+ display : inline;
+ }
- i.icon.icon-rss_feed {
- color : @color-published;
+ .feed {
+ display : none;
+ }
}
- i.icon.icon-whatshot {
- color : @color-checked;
- }
+ .footer {
+ border : 0;
+ padding : 4px;
- i.icon.icon-restore {
- position : relative;
- top : -1px;
- font-weight : bold;
- color : @color-accent;
+ .left, .right {
+ white-space: nowrap;
+ }
+
+ .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
}
+ .content-inner,
+ .intermediate {
+ a {
+ word-break: break-all;
+ }
+ }
}
}
- #headlines-wrap-inner {
- padding : 0px;
- margin : 0px;
- border-width : 0px;
- }
-
- #headlines-frame[is-vfeed="0"] .header .feed {
- display : none;
- }
-
#headlines-frame {
- padding : 0px;
- border: 0px @border-default;
- margin-top : 0px;
+ padding : 0;
+ border: 0;
+ margin-top : 0;
+
-webkit-overflow-scrolling : touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
- div.feed-title {
- border: 0px solid @color-link;
- border-bottom-width: 1px;
- padding: 5px 8px;
+ &[data-is-vfeed="false"] {
+ .header,
+ .hl {
+ .feed, .icon-feed {
+ display : none;
+ }
+ }
+ }
+
+ &[data-auto-catchup="true"] #headlines-spacer {
+ height : 100vh;
}
- div.feed-title a.title {
- color: @default-text;
- font-weight: bold;
+ .dijitCheckBox {
+ margin-right : 4px;
}
- div.feed-title a {
- color: @default-text;
+ &[data-is-wide-screen="true"] {
+ .title {
+ overflow: visible;
+ white-space: normal;
+ }
+
+ .hl .feed {
+ display: none;
+ }
}
- div.feed-title a:hover {
- color: @color-link;
+ #headlines-spacer {
+ margin-left : 1px;
+ text-align : center;
+ color : @default-text;
+ font-size : @font-size-small;
+
+ a, span {
+ color : @default-text;
+ padding : 10px;
+ display : block;
+ }
+
+ a:hover {
+ color : @color-accent;
+ }
+ }
+
+ .feed-title {
+ border: 0px solid @color-link;
+ border-bottom-width: 1px;
+ padding: 5px 8px;
+
+ a.title {
+ color: @default-text;
+ font-weight: bold;
+ }
+
+ a {
+ color: @default-text;
+
+ &:hover {
+ color: @color-link;
+ }
+ }
}
span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
}
@@ -787,15 +884,15 @@ body.ttrss_main {
}
#toolbar-frame {
- padding : 0px;
- margin : 0px;
- border-width : 0px;
+ padding : 0;
+ margin : 0;
+ border : 0;
white-space: nowrap;
- font-size : 12px;
+ font-size : @font-size-toolbar;
#toolbar {
background : white;
- border: 0px solid @border-default;
+ border: 0 solid @border-default;
border-bottom-width: 1px;
padding-left : 4px;
height : 32px;
@@ -803,13 +900,13 @@ body.ttrss_main {
flex-direction : row;
flex-wrap : nowrap;
color : @default-text;
- font-size : 12px;
+ font-size : @font-size-toolbar;
align-items : center;
.dijitSelect,
.dijitDropDownButton .dijitButtonNode,
.dijitComboButton .dijitButtonNode {
- border : 0px;
+ border : 0;
}
i.net-alert, .left i.icon-error {
@@ -826,7 +923,7 @@ body.ttrss_main {
}
#toolbar-headlines {
- font-size : 12px;
+ font-size : @font-size-toolbar;
background: transparent;
padding-right : 4px;
flex-grow : 2;
@@ -840,6 +937,12 @@ body.ttrss_main {
.feed_title, .cancel_search {
margin-left : 4px;
}
+
+ @media (max-width: @breakpoint-md) {
+ .feed_title, i.icon-syndicate {
+ display : none;
+ }
+ }
}
.right {
@@ -860,23 +963,31 @@ body.ttrss_main {
color : @color-accent;
}
- @media (max-width: 992px) {
+ @media (max-width: @breakpoint-md) {
#selected_prompt {
display : none;
}
}
+
+ @media (max-width: @breakpoint-sm) {
+ .select-articles-dropdown,
+ .catchup-button {
+ display : none;
+ }
+ }
+
}
}
#header {
- border-width : 0px;
text-align : right;
color : @default-text;
- padding : 5px 5px 0px 0px;
- margin : 0px;
+ padding : 5px 5px 0 0px;
position : absolute;
- right : 0px;
- top : 0px;
+ border : 0;
+ margin : 0;
+ right : 0;
+ top : 0;
z-index : 5;
i.net-alert, .left i.icon-error {
@@ -899,9 +1010,8 @@ body.ttrss_main {
}
#content-insert {
- padding : 0px;
- border-color : @border-default;
- border-width : 0px;
+ padding : 0;
+ border : 0;
line-height: 1.5;
overflow : auto;
-webkit-overflow-scrolling : touch;
@@ -915,64 +1025,10 @@ body.ttrss_main {
display : inline-block;
}
- .player {
- display : inline-block;
- color : @default-text;
- font-size : 11px;
- font-family : sans-serif;
- border : 1px solid @default-text;
- padding : 0px 4px 0px 4px;
- margin : 0px 2px 0px 2px;
- width : 50px;
- text-align : center;
- background : @default-bg;
- }
-
- .player.playing {
- color : #00c000;
- border-color : #00c000;
- }
-
- .player:hover {
- background : @color-panel-bg;
- cursor : pointer;
- }
-
- #headlines-frame.auto_catchup #headlines-spacer {
- height : 100%;
- }
-
- #headlines-spacer {
- margin-left : 1px;
- text-align : center;
- color : @default-text;
- font-size : 11px;
- font-style : italic;
-
- a, span {
- color : @default-text;
- padding : 10px;
- display : block;
- }
-
- a:hover {
- color : @color-accent;
- }
- }
-
ul#filterDlg_Matches, ul#filterDlg_Actions {
list-style-type : none;
margin : 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
@@ -1018,10 +1074,6 @@ body.ttrss_main {
color : #cc90cc;
}
- #headlines-frame .dijitCheckBox {
- margin-right : 4px;
- }
-
#feedEditDlg img.feedIcon {
border : 1px solid #ccc;
padding : 5px;
@@ -1110,6 +1162,7 @@ body.ttrss_main {
border: 1px solid @color-published;
border-radius: 4px;
}
+
#feed_current_unread {
margin-left : 8px;
font-weight : bold;
@@ -1148,11 +1201,21 @@ body.ttrss_main {
color : #500;
}
- .score-neutral i.icon-score {
+ /*.score-neutral i.icon-score {
opacity : 0.5;
+ }*/
+
+ i.icon-score, i.icon-grid-span {
+ cursor : pointer;
+ color : @color-icon;
+ }
+
+ // only shown in grid mode
+ .icon-grid-span {
+ display : none;
}
- i.icon-score {
+ .icon-feed {
cursor : pointer;
}
@@ -1192,27 +1255,44 @@ body.ttrss_main {
text-align : center;
}
- #prefFilterTestResultList {
- .preview {
- margin : 8px;
- }
+ .text-right {
+ text-align : right;
+ }
- .title {
- font-weight: bold;
+ .text-left {
+ text-align : left;
+ }
+
+ .dijitDialog {
+ .filter-results-list {
+ .preview {
+ margin : 8px;
+ }
+
+ .title {
+ font-weight: bold;
+ }
}
- .feed {
- color : @color-accent;
+ #feed_add_spinner {
+ position : relative;
+ top : 5px;
+ width : 18px;
+ height : 18px;
}
}
+ .icon-three-dots {
+ width : 18px;
+ height : 18px;
+ vertical-align : middle;
+ }
}
body.ttrss_main, body.ttrss_utility {
.alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1254,6 +1334,14 @@ body.ttrss_main, body.ttrss_utility {
color: darken(#c09853, 10%);
}
+ .text-muted {
+ color : @default-text;
+ }
+
+ .text-small, .small {
+ font-size : @font-size-small;
+ }
+
.alert,
.alert h4 {
color: #c09853;
@@ -1300,15 +1388,7 @@ body.ttrss_main, body.ttrss_utility {
border-bottom-width: 1px;
}
- .text-muted {
- color : @default-text;
- }
-
- .small {
- font-size : 11px;
- }
-
- div.autocomplete {
+ /*div.autocomplete {
position : absolute;
width : 250px;
background-color : @default-bg;
@@ -1333,8 +1413,7 @@ body.ttrss_main, body.ttrss_utility {
padding : 2px;
cursor : pointer;
}
- }
-
+ }*/
}
::selection {
@@ -1354,7 +1433,7 @@ body.ttrss_main, body.ttrss_utility {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
+/*video::-webkit-media-controls-overlay-play-button {
display: none;
-}
+}*/
diff --git a/themes/light/utility.less b/themes/light/utility.less
index 1c30c77ab..89675ac13 100644
--- a/themes/light/utility.less
+++ b/themes/light/utility.less
@@ -6,7 +6,7 @@ body.ttrss_utility {
background : @color-panel-bg;
color : @default-fg;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
+ font-size: @font-size-content;
margin : 4em;
.content {
@@ -21,7 +21,7 @@ body.ttrss_utility {
h2, h3, h4 {
color : @color-accent;
- font-family: @fonts-ui-bold;
+ font-family: @fonts-ui;
}
h2 {
@@ -46,7 +46,7 @@ body.ttrss_utility {
h1 {
color : gray;
- font-family: @fonts-ui-bold;
+ font-family: @fonts-ui;
font-size : 18px;
margin : 10px 0 0 0;
}
diff --git a/themes/light/zoom.less b/themes/light/zoom.less
index e599bc447..3318482c2 100644
--- a/themes/light/zoom.less
+++ b/themes/light/zoom.less
@@ -12,11 +12,11 @@ body.ttrss_zoom {
}
div.header {
- padding-bottom : 10px;
- border: 0px solid @border-default;
+ padding-bottom : 8px;
+ border: 0 solid @border-default;
border-bottom-width: 1px;
background : @default-bg;
- font-size : 12px;
+ font-size : @font-size-toolbar;
color : @default-text;
.row {
@@ -25,14 +25,20 @@ body.ttrss_zoom {
flex-wrap : nowrap;
align-items : center;
justify-content : space-between;
+
+ h1 {
+ margin-top : 0;
+ margin-bottom : 8px;
+ }
}
}
- div.content {
+ .content {
font-size : 15px;
line-height : 1.5;
border-width : 0;
padding : 0;
+ padding-top : 8px;
img, video {
max-width : 760px;
@@ -42,7 +48,7 @@ body.ttrss_zoom {
blockquote {
margin : 5px 0px 5px 0px;
color : @default-text;
- padding-left : 10px;
+ padding-left : 8px;
border: 0px solid @border-default;
border-left-width: 4px;
}
@@ -54,8 +60,7 @@ body.ttrss_zoom {
}
pre {
- margin : 5px 0px 5px 0px;
- padding : 10px;
+ padding : 8px;
color : @default-text;
font-family : monospace;
font-size : 12px;
diff --git a/themes/night.css b/themes/night.css
index 22eb17e9f..f5e23e59a 100644
--- a/themes/night.css
+++ b/themes/night.css
@@ -16,67 +16,77 @@ body.ttrss_main {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
}
body.ttrss_main :focus {
outline: none;
}
-body.ttrss_main div.post {
- padding: 0px;
+body.ttrss_main .post {
+ padding: 0;
font-size: 13px;
}
-body.ttrss_main div.post div.header {
+body.ttrss_main .post .header {
padding: 5px;
- color: #909090;
- border: 0px solid #222;
+ color: #ccc;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #222;
}
-body.ttrss_main div.post div.header .left,
-body.ttrss_main div.post div.header .right {
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
display: flex;
}
-body.ttrss_main div.post div.header .row {
+body.ttrss_main .post .header .row {
display: flex;
margin-bottom: 4px;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
}
-body.ttrss_main div.post div.header .comments {
+body.ttrss_main .post .header .comments {
flex-grow: 2;
}
-body.ttrss_main div.post div.header .date {
+body.ttrss_main .post .header .date {
white-space: nowrap;
}
-body.ttrss_main div.post div.header img,
-body.ttrss_main div.post div.header i.material-icons {
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
margin: 0px 4px;
vertical-align: middle;
- color: #777;
+ color: #999;
}
-body.ttrss_main div.post div.header .title {
+body.ttrss_main .post .header .title {
flex-grow: 2;
font-size: 15px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main div.post div.content {
+body.ttrss_main .post div.content {
padding: 10px;
font-size: 16px;
}
-body.ttrss_main div.post div.content img,
-body.ttrss_main div.post div.content video {
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
border-width: 0px;
max-width: 98%;
height: auto;
}
-body.ttrss_main div.post div.content div.embed-responsive {
+body.ttrss_main .post div.content div.embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-body.ttrss_main div.post div.content div.embed-responsive iframe {
+body.ttrss_main .post div.content div.embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -173,6 +183,11 @@ body.ttrss_main .notify.notify_progress {
border-color: #d7c47a;
background-color: #fff7d5;
}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
body.ttrss_main .notify.notify_info {
border-color: #b87d2c;
background-color: #faf3e9;
@@ -218,6 +233,10 @@ body.ttrss_main .hl .right {
display: flex;
align-items: center;
}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
body.ttrss_main .hl .left i.material-icons,
body.ttrss_main .hl .right i.material-icons {
margin-left: 2px;
@@ -226,25 +245,28 @@ body.ttrss_main .hl .right i.material-icons {
user-select: none;
font-size: 21px;
}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
body.ttrss_main .hl .right i.material-icons {
- color: #777;
+ color: #999;
}
-body.ttrss_main .hl div.title {
+body.ttrss_main .hl .title {
cursor: pointer;
flex-grow: 2;
overflow: hidden;
text-overflow: ellipsis;
}
-body.ttrss_main .hl span.author {
+body.ttrss_main .hl .author {
white-space: nowrap;
color: #ccc;
font-size: 11px;
font-weight: normal;
}
-body.ttrss_main .hl div.right {
- text-align: right;
-}
-body.ttrss_main .hl span.feed a {
+body.ttrss_main .hl .feed a {
border-radius: 4px;
display: inline-block;
padding: 1px 4px;
@@ -253,29 +275,22 @@ body.ttrss_main .hl span.feed a {
font-weight: normal;
color: #ccc;
}
-body.ttrss_main .hl span.feed a:hover {
+body.ttrss_main .hl .feed a:hover {
color: #b87d2c;
}
-body.ttrss_main .hl span.updated {
+body.ttrss_main .hl .updated {
color: #ccc;
text-align: right;
font-size: 11px;
padding-left: 10px;
}
-body.ttrss_main .hl span.updated div {
+body.ttrss_main .hl .updated div {
display: inline-block;
}
-body.ttrss_main .hl div.left input {
- margin: 0px 4px;
-}
-body.ttrss_main .hl div.left img,
-body.ttrss_main .hl div.right img {
- margin: 0px 4px;
-}
body.ttrss_main .hl div.title a {
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #555;
}
body.ttrss_main .hl a.title.high,
@@ -288,10 +303,10 @@ body.ttrss_main .hl.vgrlf .feed {
body.ttrss_main .hl.Unread {
background: white;
}
-body.ttrss_main .hl.Unread div.title a {
+body.ttrss_main .hl.Unread .title a {
color: black;
}
-body.ttrss_main .hl.active div.title a {
+body.ttrss_main .hl.active .title a {
color: #b87d2c;
/* text-shadow : 1px 1px 2px #fff; */
}
@@ -313,9 +328,6 @@ body.ttrss_main .hl.active span,
body.ttrss_main .hl.Selected span {
color: white;
}
-body.ttrss_main .hl.Grayed {
- color: #909090;
-}
body.ttrss_main #content-insert blockquote,
body.ttrss_main #headlines-frame blockquote,
body.ttrss_main .dijitContentPane blockquote {
@@ -372,45 +384,6 @@ body.ttrss_main i.pub-pic {
cursor: pointer;
color: #ccc;
}
-body.ttrss_main div.errorExplained {
- border: 1px solid #222;
- margin: 5px 0px 5px 0px;
- padding: 5px;
-}
-body.ttrss_main ul.browseFeedList {
- height: 300px;
- width: 100%;
- overflow: auto;
- border-width: 0px 1px 1px 1px;
- border-color: #222;
- border-style: solid;
- margin: 0px 0px 5px 0px;
- background-color: white;
- list-style-type: none;
- padding: 0px;
-}
-body.ttrss_main ul.browseFeedList li {
- display: flex;
- align-items: center;
-}
-body.ttrss_main ul.browseFeedList li > * {
- margin: 2px;
-}
-body.ttrss_main .browseFeedList span.subscribers {
- color: #808080;
-}
-body.ttrss_main ul.compact {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main ul.compact li {
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main .noborder {
- border-width: 0px;
-}
body.ttrss_main #overlay {
background: #333;
left: 0;
@@ -424,11 +397,6 @@ body.ttrss_main #overlay_inner {
font-weight: bold;
margin: 1em;
}
-body.ttrss_main div.loadingPrompt {
- padding: 1em;
- text-align: center;
- font-weight: bold;
-}
body.ttrss_main div.whiteBox {
margin-left: 1px;
text-align: center;
@@ -437,20 +405,13 @@ body.ttrss_main div.whiteBox {
border: 0px solid #222;
border-bottom-width: 1px;
}
-body.ttrss_main div#headlines-frame.wide .title {
- overflow: visible;
- white-space: normal;
-}
-body.ttrss_main div#headlines-frame.wide .hl .feed {
- display: none;
-}
body.ttrss_main .dijitDialog header,
body.ttrss_main .dijitDialog .dlgSec,
body.ttrss_main .dijitDialog .dlgSecHoriz {
font-size: 16px;
font-weight: 600;
color: #ccc;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_main .dijitDialog section,
body.ttrss_main .dijitDialog .dlgSecCont {
@@ -528,11 +489,6 @@ body.ttrss_main div#cmdline {
padding: 3px 5px 3px 5px;
z-index: 5;
}
-body.ttrss_main #feed_browser_spinner {
- vertical-align: middle;
- height: 18px;
- width: 18px;
-}
body.ttrss_main .exception-contents h3 {
color: red;
}
@@ -541,14 +497,15 @@ body.ttrss_main .exception-contents textarea {
height: 200px;
font-size: 11px;
}
+body.ttrss_main #headlines-wrap-inner,
body.ttrss_main #content-wrap {
- padding: 0px;
- border-width: 0px;
- margin: 0px;
+ padding: 0;
+ border: 0;
+ margin: 0;
}
body.ttrss_main #feeds-holder {
- padding: 0px;
- border: 0px solid #222;
+ padding: 0;
+ border: 0 solid #222;
overflow: hidden;
background: #222;
box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
@@ -558,19 +515,26 @@ body.ttrss_main #feeds-holder #feedTree {
height: 100%;
overflow-x: hidden;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- background: #222;
- color: #e6e6e6;
- border-color: #080808;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- border-color: #b87d2c;
- background: #ffffff;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
font-weight: bold;
display: none;
font-size: 9px;
@@ -579,111 +543,215 @@ body.ttrss_main #feeds-holder #feedTree .counterNode {
color: white;
background: #cd8b31;
border-radius: 4px;
- vertical-align: middle;
- float: right;
- position: relative;
line-height: 14px;
margin-right: 8px;
- margin-top: 2px;
min-width: 23px;
height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #222;
+ color: #e6e6e6;
+ border-color: #080808;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #b87d2c;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .loadingExpando {
- left: -3px;
- height: 22px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
position: relative;
- top: -3px;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeLabel.Unread {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
font-weight: bold;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow.Error .dijitTreeLabel {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
color: red;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
- border: 1px solid transparent;
-}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRowSelected {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
border-color: #222 transparent;
background: #333;
- color: #333;
+ color: #ccc;
}
-body.ttrss_main #feeds-holder #feedTree .dijitIcon.feed-icon {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
margin-right: 2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
- color: #555;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #ffffff;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-archive {
- color: #c77b2e;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-star {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
position: relative;
color: #ffc069;
font-size: 21px;
left: -2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-rss_feed {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
color: #ff7c4b;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-whatshot {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
color: #69C671;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-restore {
- position: relative;
- top: -1px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
font-weight: bold;
color: #b87d2c;
}
-body.ttrss_main #headlines-wrap-inner {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #222;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: #333;
+ border: 1px solid #222;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
}
-body.ttrss_main #headlines-frame[is-vfeed="0"] .header .feed {
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
display: none;
}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
body.ttrss_main #headlines-frame {
- padding: 0px;
- border: 0px #222;
- margin-top: 0px;
+ padding: 0;
+ border: 0;
+ margin-top: 0;
-webkit-overflow-scrolling: touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
}
-body.ttrss_main #headlines-frame div.feed-title {
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: #ccc;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: #ccc;
+ padding: 10px;
+ display: block;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #b87d2c;
+}
+body.ttrss_main #headlines-frame .feed-title {
border: 0px solid #b87d2c;
border-bottom-width: 1px;
padding: 5px 8px;
}
-body.ttrss_main #headlines-frame div.feed-title a.title {
+body.ttrss_main #headlines-frame .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-body.ttrss_main #headlines-frame div.feed-title a {
+body.ttrss_main #headlines-frame .feed-title a {
color: #ccc;
}
-body.ttrss_main #headlines-frame div.feed-title a:hover {
+body.ttrss_main #headlines-frame .feed-title a:hover {
color: #b87d2c;
}
body.ttrss_main #headlines-frame span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
body.ttrss_main #toolbar-frame_splitter {
display: none;
}
body.ttrss_main #toolbar-frame {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+ padding: 0;
+ margin: 0;
+ border: 0;
white-space: nowrap;
- font-size: 12px;
+ font-size: 13px;
}
body.ttrss_main #toolbar-frame #toolbar {
background: white;
- border: 0px solid #222;
+ border: 0 solid #222;
border-bottom-width: 1px;
padding-left: 4px;
height: 32px;
@@ -691,13 +759,13 @@ body.ttrss_main #toolbar-frame #toolbar {
flex-direction: row;
flex-wrap: nowrap;
color: #ccc;
- font-size: 12px;
+ font-size: 13px;
align-items: center;
}
body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
- border: 0px;
+ border: 0;
}
body.ttrss_main #toolbar-frame #toolbar i.net-alert,
body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
@@ -711,7 +779,7 @@ body.ttrss_main #toolbar-frame #toolbar i {
margin: 0 4px;
}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
- font-size: 12px;
+ font-size: 13px;
background: transparent;
padding-right: 4px;
flex-grow: 2;
@@ -726,6 +794,12 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
margin-left: 4px;
}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
display: flex;
align-items: center;
@@ -740,20 +814,26 @@ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
margin-right: 4px;
color: #b87d2c;
}
-@media (max-width: 992px) {
+@media (max-width: 768px) {
body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
display: none;
}
}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
body.ttrss_main #header {
- border-width: 0px;
text-align: right;
color: #ccc;
- padding: 5px 5px 0px 0px;
- margin: 0px;
+ padding: 5px 5px 0 0px;
position: absolute;
- right: 0px;
- top: 0px;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
z-index: 5;
}
body.ttrss_main #header i.net-alert,
@@ -772,9 +852,8 @@ body.ttrss_main #header i {
margin: 0 4px;
}
body.ttrss_main #content-insert {
- padding: 0px;
- border-color: #222;
- border-width: 0px;
+ padding: 0;
+ border: 0;
line-height: 1.5;
overflow: auto;
-webkit-overflow-scrolling: touch;
@@ -787,59 +866,11 @@ body.ttrss_main img.icon {
vertical-align: middle;
display: inline-block;
}
-body.ttrss_main .player {
- display: inline-block;
- color: #ccc;
- font-size: 11px;
- font-family: sans-serif;
- border: 1px solid #ccc;
- padding: 0px 4px 0px 4px;
- margin: 0px 2px 0px 2px;
- width: 50px;
- text-align: center;
- background: #333;
-}
-body.ttrss_main .player.playing {
- color: #00c000;
- border-color: #00c000;
-}
-body.ttrss_main .player:hover {
- background: #222;
- cursor: pointer;
-}
-body.ttrss_main #headlines-frame.auto_catchup #headlines-spacer {
- height: 100%;
-}
-body.ttrss_main #headlines-spacer {
- margin-left: 1px;
- text-align: center;
- color: #ccc;
- font-size: 11px;
- font-style: italic;
-}
-body.ttrss_main #headlines-spacer a,
-body.ttrss_main #headlines-spacer span {
- color: #ccc;
- padding: 10px;
- display: block;
-}
-body.ttrss_main #headlines-spacer a:hover {
- color: #b87d2c;
-}
body.ttrss_main ul#filterDlg_Matches,
body.ttrss_main ul#filterDlg_Actions {
list-style-type: none;
margin: 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
body.ttrss_main ul#filterDlg_Matches li,
body.ttrss_main ul#filterDlg_Actions li {
@@ -875,9 +906,6 @@ body.ttrss_main span.highlight {
background-color: #ffff00;
color: #cc90cc;
}
-body.ttrss_main #headlines-frame .dijitCheckBox {
- margin-right: 4px;
-}
body.ttrss_main #feedEditDlg img.feedIcon {
border: 1px solid #ccc;
padding: 5px;
@@ -935,6 +963,11 @@ body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-show
body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
display: none;
}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
body.ttrss_main #toolbar-headlines i.icon-syndicate {
color: #ff7c4b;
margin-right: 8px;
@@ -971,10 +1004,15 @@ body.ttrss_main .score-high i.icon-score {
body.ttrss_main .score-low i.icon-score {
color: #500;
}
-body.ttrss_main .score-neutral i.icon-score {
- opacity: 0.5;
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #999;
}
-body.ttrss_main i.icon-score {
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
cursor: pointer;
}
body.ttrss_main .panel {
@@ -1005,20 +1043,62 @@ body.ttrss_main ul.list-unstyled {
body.ttrss_main .text-center {
text-align: center;
}
-body.ttrss_main #prefFilterTestResultList .preview {
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
margin: 8px;
}
-body.ttrss_main #prefFilterTestResultList .title {
+body.ttrss_main .dijitDialog .filter-results-list .title {
font-weight: bold;
}
-body.ttrss_main #prefFilterTestResultList .feed {
- color: #b87d2c;
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
}
body.ttrss_main .alert,
body.ttrss_utility .alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1059,6 +1139,16 @@ body.ttrss_main .text-warning,
body.ttrss_utility .text-warning {
color: #a47e3c;
}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: #ccc;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
body.ttrss_main .alert,
body.ttrss_utility .alert,
body.ttrss_main .alert h4,
@@ -1108,41 +1198,6 @@ body.ttrss_utility hr {
border: 0px solid #ccc;
border-bottom-width: 1px;
}
-body.ttrss_main .text-muted,
-body.ttrss_utility .text-muted {
- color: #ccc;
-}
-body.ttrss_main .small,
-body.ttrss_utility .small {
- font-size: 11px;
-}
-body.ttrss_main div.autocomplete,
-body.ttrss_utility div.autocomplete {
- position: absolute;
- width: 250px;
- background-color: #333;
- border: 1px solid #222;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul,
-body.ttrss_utility div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul li.selected,
-body.ttrss_utility div.autocomplete ul li.selected {
- background-color: #1a1a1a;
-}
-body.ttrss_main div.autocomplete ul li,
-body.ttrss_utility div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
- cursor: pointer;
-}
::selection {
background: #b87d2c;
color: #333;
@@ -1156,16 +1211,13 @@ body.ttrss_utility div.autocomplete ul li {
::-webkit-scrollbar-track {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
- display: none;
-}
-.cdm i.material-icons {
- color: #777;
-}
-.cdm .header {
- position: sticky;
- top: 0;
- z-index: 3;
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
}
.cdm .header,
.cdm .footer {
@@ -1176,13 +1228,16 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header img,
.cdm .footer img,
.cdm .footer i.material-icons {
- margin: 0px 4px;
+ margin: 0 4px;
vertical-align: middle;
}
.cdm .header-sticky-guard {
height: 0;
}
.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
align-items: center;
}
.cdm .header > * {
@@ -1205,7 +1260,7 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header .titleWrap {
flex-grow: 2;
}
-.cdm .header span.updated {
+.cdm .header .updated {
color: #ccc;
font-weight: normal;
font-size: 11px;
@@ -1214,6 +1269,30 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header input {
margin: 0px 4px;
}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: #ccc;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: #ccc;
+ font-size: 11px;
+ font-weight: normal;
+}
.cdm .footer {
height: 30px;
padding-left: 5px;
@@ -1222,30 +1301,37 @@ video::-webkit-media-controls-overlay-play-button {
clear: both;
align-items: center;
}
+.cdm .footer i.material-icons {
+ color: #999;
+}
.cdm .footer .left {
flex-grow: 2;
}
.cdm .intermediate {
margin-top: 10px;
margin-left: 10px;
+ line-height: 1.5;
}
.cdm .content-inner {
margin: 10px;
line-height: 1.5;
font-size: 16px;
}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
.cdm .intermediate img,
.cdm .intermediate video,
.cdm .content-inner img,
.cdm .content-inner video {
border-width: 0px;
max-width: 98%;
+ width: auto;
height: auto;
}
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-}
.cdm.expanded .collapse,
.cdm.expanded .excerpt {
display: none;
@@ -1258,72 +1344,54 @@ video::-webkit-media-controls-overlay-play-button {
border-bottom-width: 1px;
}
.cdm.expanded > hr {
- margin-top: 0px;
- margin-bottom: 0px;
+ margin-top: 0;
+ margin-bottom: 0;
}
-div.cdm.expanded div.header a.title {
+.cdm.expanded .header a.title {
font-size: 16px;
color: #999;
font-weight: 600;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expanded.active {
- background: white;
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
}
-div.cdm.expanded.active div.header a.title {
+.cdm.expanded.active .header .title {
color: #b87d2c;
}
-div.cdm.expanded.Unread div.header a.title {
+.cdm.expanded.Unread .header .title {
color: black;
}
-div.cdm.expanded div.content {
+.cdm.expanded .content {
color: #ccc;
}
-div.cdm.expanded.Unread div.content {
- color: black;
-}
-div.cdm.active div.content {
- color: black;
-}
-div.cdm.vgrlf .feed {
+.cdm.vgrlf .feed {
display: none;
}
-.cdm div.feed-title {
+.cdm .feed-title {
border: 0px solid #b87d2c;
border-bottom-width: 1px;
padding: 5px 3px 5px 5px;
}
-.cdm div.feed-title a.title {
+.cdm .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-.cdm div.feed-title a {
+.cdm .feed-title a {
color: #ccc;
}
-.cdm div.feed-title a:hover {
+.cdm .feed-title a:hover {
color: #b87d2c;
}
-.cdm div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
-}
-.cdm div.header div.feed,
-.cdm div.header div.feed a {
- vertical-align: middle;
- color: #ccc;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
-}
-.cdm div.content-inner div.embed-responsive {
+.cdm .content-inner .embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-.cdm div.content-inner div.embed-responsive iframe {
+.cdm .content-inner .embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -1332,17 +1400,6 @@ div.cdm.vgrlf .feed {
top: 0;
width: 100%;
}
-.cdm div.header span.author {
- white-space: nowrap;
- color: #ccc;
- font-size: 11px;
- font-weight: normal;
-}
-.cdm .feed a {
- border-radius: 4px;
- display: inline-block;
- padding: 1px 4px 1px 4px;
-}
.cdm.expandable {
background-color: #222;
border: 0px solid #222;
@@ -1380,43 +1437,43 @@ div.cdm.vgrlf .feed {
.cdm.expandable.active {
background: white ! important;
}
-div.cdm.expandable.active div.header span.titleWrap {
+.cdm.expandable.active div.header span.titleWrap {
white-space: normal;
}
-div.cdm.expandable div.header a.title {
+.cdm.expandable .header a.title {
font-weight: 600;
color: #ccc;
font-size: 14px;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable.Unread div.header a.title {
+.cdm.expandable.Unread div.header a.title {
color: black;
}
-div.cdm.expandable.active .collapse i.material-icons {
+.cdm.expandable.active .collapse i.material-icons {
color: #b87d2c;
cursor: pointer;
}
-div.cdm.expandable.active .excerpt {
+.cdm.expandable.active .excerpt {
display: none;
}
-div.cdm.expandable.active div.header a.title {
+.cdm.expandable.active div.header a.title {
color: #b87d2c;
font-size: 16px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable:not(.active) {
+.cdm.expandable:not(.active) {
cursor: pointer;
}
-div.cdm.expandable:not(.active) .content,
-div.cdm.expandable:not(.active) .collapse {
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
display: none;
}
-div.cdm.expandable.active .header[stuck],
-div.cdm.expanded .header[stuck] {
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
border: 0 solid #222;
border-bottom-width: 1px;
@@ -1433,7 +1490,7 @@ body.ttrss_prefs h1,
body.ttrss_prefs h2,
body.ttrss_prefs h3,
body.ttrss_prefs h4 {
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 600;
color: #ccc;
}
@@ -1504,14 +1561,6 @@ body.ttrss_prefs fieldset.prefs .help-text {
body.ttrss_prefs fieldset.prefs .help-text-bottom {
margin-top: 10px;
}
-body.ttrss_prefs fieldset.plugin label.description {
- width: 550px;
- margin-right: 150px;
- display: inline-block;
-}
-body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox {
- margin-right: 10px;
-}
body.ttrss_prefs table th {
text-align: left;
}
@@ -1539,17 +1588,26 @@ body.ttrss_prefs ul.prefs-plugin-list li > * {
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
display: flex;
align-items: center;
- min-width: 300px;
cursor: pointer;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
cursor: auto;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
}
body.ttrss_prefs ul.prefs-plugin-list li .actions {
flex-grow: 2;
@@ -1603,6 +1661,11 @@ body.ttrss_prefs .event-log tr .errno {
body.ttrss_prefs .event-log tr .errstr {
word-break: break-all;
white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
}
body.ttrss_prefs .event-log tr .filename,
body.ttrss_prefs .event-log tr .login,
@@ -1661,12 +1724,16 @@ body.ttrss_utility fieldset > label.checkbox {
display: inline;
font-weight: normal;
}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
.flat li {
padding: 2px;
}
-.flat #feedTree .dijitTreeContent .dijitInline {
- vertical-align: baseline;
-}
.flat .dijitButton i.material-icons {
position: relative;
top: -1px;
@@ -1690,7 +1757,8 @@ body.ttrss_utility fieldset > label.checkbox {
}
.flat .dijitToolbar {
font-size: 13px;
- padding: 0px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
}
.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
line-height: 10px;
@@ -1713,12 +1781,13 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
padding: 4px 8px;
font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
color: #d29745;
}
.flat .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ padding: 0;
}
.flat .dijitCheckBox {
margin: 1px;
@@ -1728,10 +1797,33 @@ body.ttrss_utility fieldset > label.checkbox {
content: "\f00c";
color: white;
}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
.flat .dijitTab i.material-icons,
.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
color: #b87d2c;
}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
.flat .dijitTree .dijitFolderClosed,
.flat .dijitTree .dijitFolderOpened {
display: none;
@@ -1745,10 +1837,6 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
color: white;
}
-.flat .dijitTree .dijitTreeRow .dijitTreeExpando {
- position: relative;
- top: -2px;
-}
.flat .dijitTree .labelParam {
float: right;
margin-right: 16px;
@@ -1777,6 +1865,7 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
.flat label.dijitButton {
@@ -1852,7 +1941,7 @@ body.ttrss_utility .content h2,
body.ttrss_utility .content h3,
body.ttrss_utility .content h4 {
color: #b87d2c;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_utility .content h2 {
font-size: 18px;
@@ -1871,7 +1960,7 @@ body.ttrss_utility a:focus {
}
body.ttrss_utility h1 {
color: gray;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
margin: 10px 0 0 0;
}
@@ -1940,11 +2029,11 @@ body.ttrss_zoom div.post .attachments {
display: none;
}
body.ttrss_zoom div.post div.header {
- padding-bottom: 10px;
- border: 0px solid #222;
+ padding-bottom: 8px;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #333;
- font-size: 12px;
+ font-size: 13px;
color: #ccc;
}
body.ttrss_zoom div.post div.header .row {
@@ -1954,32 +2043,36 @@ body.ttrss_zoom div.post div.header .row {
align-items: center;
justify-content: space-between;
}
-body.ttrss_zoom div.post div.content {
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
font-size: 15px;
line-height: 1.5;
border-width: 0;
padding: 0;
+ padding-top: 8px;
}
-body.ttrss_zoom div.post div.content img,
-body.ttrss_zoom div.post div.content video {
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
max-width: 760px;
height: auto;
}
-body.ttrss_zoom div.post div.content blockquote {
+body.ttrss_zoom div.post .content blockquote {
margin: 5px 0px 5px 0px;
color: #ccc;
- padding-left: 10px;
+ padding-left: 8px;
border: 0px solid #222;
border-left-width: 4px;
}
-body.ttrss_zoom div.post div.content code {
+body.ttrss_zoom div.post .content code {
color: #009900;
font-family: monospace;
font-size: 12px;
}
-body.ttrss_zoom div.post div.content pre {
- margin: 5px 0px 5px 0px;
- padding: 10px;
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
color: #ccc;
font-family: monospace;
font-size: 12px;
@@ -2023,26 +2116,34 @@ body.flat.ttrss_main #feeds-holder {
background: #222;
box-shadow: inset -1px 0px 2px -1px #666;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.aux,
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
background: #222;
color: #ccc;
border-color: #333;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
border-color: #b87d2c;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected {
background: #333;
border-color: #333 transparent;
color: #e6e6e6;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLabel {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected .dijitTreeLabel {
text-shadow: none;
}
-body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow i.icon.icon-inbox {
color: #999999;
}
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .loadingNode {
+ filter: invert(1);
+}
+body.flat.ttrss_main #headlines-frame {
+ /*.cdm.expanded {
+ background: @default-bg;
+ }*/
+}
body.flat.ttrss_main #headlines-frame .hl:not(.active):not(.Selected):not(.Unread),
body.flat.ttrss_main #headlines-frame .cdm.expandable:not(.active):not(.Selected):not(.Unread) {
background: #333;
@@ -2051,9 +2152,6 @@ body.flat.ttrss_main #headlines-frame .hl.Unread:not(.active):not(.Selected),
body.flat.ttrss_main #headlines-frame .cdm.expandable.Unread:not(.active):not(.Selected) {
background: #222;
}
-body.flat.ttrss_main #headlines-frame .cdm.expanded {
- background: #333;
-}
body.flat.ttrss_main #headlines-frame .hl.Unread .title,
body.flat.ttrss_main #headlines-frame .cdm.Unread .title {
color: #e6e6e6;
@@ -2226,3 +2324,6 @@ body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextAreaError {
body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextArea:not(.dijitValidationTextAreaError) {
background: #305030;
}
+body.flat.ttrss_main .dijitDialog #feed_add_spinner {
+ filter: invert(1);
+}
diff --git a/themes/night_base.less b/themes/night_base.less
index 76ea04a7f..a3945c856 100644
--- a/themes/night_base.less
+++ b/themes/night_base.less
@@ -9,11 +9,9 @@
@default-fg: @default-text;
@border-default: #222;
@default-bg : #333;
-
+@color-icon: #999;
@border-light : #666;
-@default-text: #ccc;
-
@fg-text-muted: darken(@default-text, 20%);
@fg-light : lighten(@default-text, 10%);
@@ -65,28 +63,34 @@ body.flat.ttrss_main {
box-shadow : inset -1px 0px 2px -1px @border-light;
#feedTree {
- .counterNode.aux, .counterNode.marked {
- background: @color-panel-bg;
- color: @default-text;
- border-color: @default-bg;
- }
+ .dijitTreeRow {
+ .counterNode.aux, .counterNode.marked {
+ background: @color-panel-bg;
+ color: @default-text;
+ border-color: @default-bg;
+ }
- .counterNode.marked {
- border-color : @color-accent-marked;
- }
+ .counterNode.marked {
+ border-color : @color-accent-marked;
+ }
- .dijitTreeRowSelected {
- background : @default-bg;
- border-color : @default-bg transparent;
- color : @fg-light;
- }
+ .dijitTreeRowSelected {
+ background : @default-bg;
+ border-color : @default-bg transparent;
+ color : @fg-light;
+ }
- .dijitTreeRowSelected .dijitTreeLabel {
- text-shadow : none;
- }
+ .dijitTreeRowSelected .dijitTreeLabel {
+ text-shadow : none;
+ }
+
+ i.icon.icon-inbox {
+ color : darken(@default-text, 20%);
+ }
- i.icon.icon-inbox {
- color : darken(@default-text, 20%);
+ .loadingNode {
+ filter : invert(1);
+ }
}
}
}
@@ -102,9 +106,9 @@ body.flat.ttrss_main {
background : @color-panel-bg;
}
- .cdm.expanded {
+ /*.cdm.expanded {
background: @default-bg;
- }
+ }*/
.hl.Unread .title,
.cdm.Unread .title {
@@ -324,4 +328,11 @@ body.flat.ttrss_main {
background : #305030;
}
}
+
+ .dijitDialog {
+ #feed_add_spinner {
+ filter : invert(1);
+ }
+ }
+
}
diff --git a/themes/night_blue.css b/themes/night_blue.css
index 8a3d7f8a5..60293f52c 100644
--- a/themes/night_blue.css
+++ b/themes/night_blue.css
@@ -16,67 +16,77 @@ body.ttrss_main {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
+ /*ul.compact {
+ list-style-type : none;
+ margin : 0;
+ padding : 0;
+
+ li {
+ margin : 0;
+ padding : 0;
+ }
+ }*/
}
body.ttrss_main :focus {
outline: none;
}
-body.ttrss_main div.post {
- padding: 0px;
+body.ttrss_main .post {
+ padding: 0;
font-size: 13px;
}
-body.ttrss_main div.post div.header {
+body.ttrss_main .post .header {
padding: 5px;
- color: #909090;
- border: 0px solid #222;
+ color: #ccc;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #222;
}
-body.ttrss_main div.post div.header .left,
-body.ttrss_main div.post div.header .right {
+body.ttrss_main .post .header .left,
+body.ttrss_main .post .header .right {
display: flex;
}
-body.ttrss_main div.post div.header .row {
+body.ttrss_main .post .header .row {
display: flex;
margin-bottom: 4px;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
}
-body.ttrss_main div.post div.header .comments {
+body.ttrss_main .post .header .comments {
flex-grow: 2;
}
-body.ttrss_main div.post div.header .date {
+body.ttrss_main .post .header .date {
white-space: nowrap;
}
-body.ttrss_main div.post div.header img,
-body.ttrss_main div.post div.header i.material-icons {
+body.ttrss_main .post .header img,
+body.ttrss_main .post .header i.material-icons {
margin: 0px 4px;
vertical-align: middle;
- color: #777;
+ color: #999;
}
-body.ttrss_main div.post div.header .title {
+body.ttrss_main .post .header .title {
flex-grow: 2;
font-size: 15px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main div.post div.content {
+body.ttrss_main .post div.content {
padding: 10px;
font-size: 16px;
}
-body.ttrss_main div.post div.content img,
-body.ttrss_main div.post div.content video {
+body.ttrss_main .post div.content img,
+body.ttrss_main .post div.content video {
border-width: 0px;
max-width: 98%;
height: auto;
}
-body.ttrss_main div.post div.content div.embed-responsive {
+body.ttrss_main .post div.content div.embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-body.ttrss_main div.post div.content div.embed-responsive iframe {
+body.ttrss_main .post div.content div.embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -173,6 +183,11 @@ body.ttrss_main .notify.notify_progress {
border-color: #d7c47a;
background-color: #fff7d5;
}
+body.ttrss_main .notify.notify_progress img {
+ width: 18px;
+ height: 18px;
+ filter: saturate(0);
+}
body.ttrss_main .notify.notify_info {
border-color: #257aa7;
background-color: #d5ebf6;
@@ -218,6 +233,10 @@ body.ttrss_main .hl .right {
display: flex;
align-items: center;
}
+body.ttrss_main .hl .left img,
+body.ttrss_main .hl .right img {
+ margin: 0 4px;
+}
body.ttrss_main .hl .left i.material-icons,
body.ttrss_main .hl .right i.material-icons {
margin-left: 2px;
@@ -226,25 +245,28 @@ body.ttrss_main .hl .right i.material-icons {
user-select: none;
font-size: 21px;
}
+body.ttrss_main .hl .left input {
+ margin: 0 4px;
+}
+body.ttrss_main .hl .right {
+ text-align: right;
+}
body.ttrss_main .hl .right i.material-icons {
- color: #777;
+ color: #999;
}
-body.ttrss_main .hl div.title {
+body.ttrss_main .hl .title {
cursor: pointer;
flex-grow: 2;
overflow: hidden;
text-overflow: ellipsis;
}
-body.ttrss_main .hl span.author {
+body.ttrss_main .hl .author {
white-space: nowrap;
color: #ccc;
font-size: 11px;
font-weight: normal;
}
-body.ttrss_main .hl div.right {
- text-align: right;
-}
-body.ttrss_main .hl span.feed a {
+body.ttrss_main .hl .feed a {
border-radius: 4px;
display: inline-block;
padding: 1px 4px;
@@ -253,29 +275,22 @@ body.ttrss_main .hl span.feed a {
font-weight: normal;
color: #ccc;
}
-body.ttrss_main .hl span.feed a:hover {
+body.ttrss_main .hl .feed a:hover {
color: #257aa7;
}
-body.ttrss_main .hl span.updated {
+body.ttrss_main .hl .updated {
color: #ccc;
text-align: right;
font-size: 11px;
padding-left: 10px;
}
-body.ttrss_main .hl span.updated div {
+body.ttrss_main .hl .updated div {
display: inline-block;
}
-body.ttrss_main .hl div.left input {
- margin: 0px 4px;
-}
-body.ttrss_main .hl div.left img,
-body.ttrss_main .hl div.right img {
- margin: 0px 4px;
-}
body.ttrss_main .hl div.title a {
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #555;
}
body.ttrss_main .hl a.title.high,
@@ -288,10 +303,10 @@ body.ttrss_main .hl.vgrlf .feed {
body.ttrss_main .hl.Unread {
background: white;
}
-body.ttrss_main .hl.Unread div.title a {
+body.ttrss_main .hl.Unread .title a {
color: black;
}
-body.ttrss_main .hl.active div.title a {
+body.ttrss_main .hl.active .title a {
color: #257aa7;
/* text-shadow : 1px 1px 2px #fff; */
}
@@ -313,9 +328,6 @@ body.ttrss_main .hl.active span,
body.ttrss_main .hl.Selected span {
color: white;
}
-body.ttrss_main .hl.Grayed {
- color: #909090;
-}
body.ttrss_main #content-insert blockquote,
body.ttrss_main #headlines-frame blockquote,
body.ttrss_main .dijitContentPane blockquote {
@@ -372,45 +384,6 @@ body.ttrss_main i.pub-pic {
cursor: pointer;
color: #ccc;
}
-body.ttrss_main div.errorExplained {
- border: 1px solid #222;
- margin: 5px 0px 5px 0px;
- padding: 5px;
-}
-body.ttrss_main ul.browseFeedList {
- height: 300px;
- width: 100%;
- overflow: auto;
- border-width: 0px 1px 1px 1px;
- border-color: #222;
- border-style: solid;
- margin: 0px 0px 5px 0px;
- background-color: white;
- list-style-type: none;
- padding: 0px;
-}
-body.ttrss_main ul.browseFeedList li {
- display: flex;
- align-items: center;
-}
-body.ttrss_main ul.browseFeedList li > * {
- margin: 2px;
-}
-body.ttrss_main .browseFeedList span.subscribers {
- color: #808080;
-}
-body.ttrss_main ul.compact {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main ul.compact li {
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main .noborder {
- border-width: 0px;
-}
body.ttrss_main #overlay {
background: #333;
left: 0;
@@ -424,11 +397,6 @@ body.ttrss_main #overlay_inner {
font-weight: bold;
margin: 1em;
}
-body.ttrss_main div.loadingPrompt {
- padding: 1em;
- text-align: center;
- font-weight: bold;
-}
body.ttrss_main div.whiteBox {
margin-left: 1px;
text-align: center;
@@ -437,20 +405,13 @@ body.ttrss_main div.whiteBox {
border: 0px solid #222;
border-bottom-width: 1px;
}
-body.ttrss_main div#headlines-frame.wide .title {
- overflow: visible;
- white-space: normal;
-}
-body.ttrss_main div#headlines-frame.wide .hl .feed {
- display: none;
-}
body.ttrss_main .dijitDialog header,
body.ttrss_main .dijitDialog .dlgSec,
body.ttrss_main .dijitDialog .dlgSecHoriz {
font-size: 16px;
font-weight: 600;
color: #ccc;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_main .dijitDialog section,
body.ttrss_main .dijitDialog .dlgSecCont {
@@ -528,11 +489,6 @@ body.ttrss_main div#cmdline {
padding: 3px 5px 3px 5px;
z-index: 5;
}
-body.ttrss_main #feed_browser_spinner {
- vertical-align: middle;
- height: 18px;
- width: 18px;
-}
body.ttrss_main .exception-contents h3 {
color: red;
}
@@ -541,14 +497,15 @@ body.ttrss_main .exception-contents textarea {
height: 200px;
font-size: 11px;
}
+body.ttrss_main #headlines-wrap-inner,
body.ttrss_main #content-wrap {
- padding: 0px;
- border-width: 0px;
- margin: 0px;
+ padding: 0;
+ border: 0;
+ margin: 0;
}
body.ttrss_main #feeds-holder {
- padding: 0px;
- border: 0px solid #222;
+ padding: 0;
+ border: 0 solid #222;
overflow: hidden;
background: #222;
box-shadow: inset -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
@@ -558,19 +515,26 @@ body.ttrss_main #feeds-holder #feedTree {
height: 100%;
overflow-x: hidden;
text-rendering: optimizelegibility;
- font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- background: #222;
- color: #e6e6e6;
- border-color: #080808;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
+ border: 1px solid transparent;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode.marked {
- border-color: #257aa7;
- background: #ffffff;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Feed .loadingNode {
+ left: -2px;
+ height: 14px;
+ width: 14px;
+ position: relative;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Is_Cat .loadingNode {
+ height: 11px;
+ width: 18px;
+ margin-left: 4px;
+ position: relative;
+ top: 2px;
}
-body.ttrss_main #feeds-holder #feedTree .counterNode {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode {
+ order: 2;
font-weight: bold;
display: none;
font-size: 9px;
@@ -579,111 +543,215 @@ body.ttrss_main #feeds-holder #feedTree .counterNode {
color: white;
background: #2a89bc;
border-radius: 4px;
- vertical-align: middle;
- float: right;
- position: relative;
line-height: 14px;
margin-right: 8px;
- margin-top: 2px;
min-width: 23px;
height: 14px;
+ flex-shrink: 0;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.aux,
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ background: #222;
+ color: #e6e6e6;
+ border-color: #080808;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .counterNode.marked {
+ border-color: #257aa7;
+ background: #ffffff;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread {
+ background-color: #3ea447;
+ border-color: #307f37;
+}
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeContent {
+ display: flex;
+ align-items: center;
+ flex-grow: 2;
+ min-width: 0;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .loadingExpando {
- left: -3px;
- height: 22px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel {
+ cursor: pointer;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
position: relative;
- top: -3px;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeLabel.Unread {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitTreeLabel.Unread {
font-weight: bold;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeRow.Error .dijitTreeLabel {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.Error .dijitTreeLabel {
color: red;
}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow {
- border: 1px solid transparent;
-}
-body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRowSelected {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
box-shadow: -1px 0px 2px -1px rgba(0, 0, 0, 0.1);
border-color: #222 transparent;
background: #333;
- color: #333;
+ color: #ccc;
}
-body.ttrss_main #feeds-holder #feedTree .dijitIcon.feed-icon {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow .dijitIcon.feed-icon {
margin-right: 2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
- color: #555;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-inbox {
+ color: #ffffff;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-archive {
- color: #c77b2e;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-archive {
+ color: #cf7800;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-star {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-star {
position: relative;
color: #ffc069;
font-size: 21px;
left: -2px;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-rss_feed {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-rss_feed {
color: #ff7c4b;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-whatshot {
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-whatshot {
color: #69C671;
}
-body.ttrss_main #feeds-holder #feedTree i.icon.icon-restore {
- position: relative;
- top: -1px;
+body.ttrss_main #feeds-holder #feedTree .dijitTreeNode .dijitTreeRow i.icon.icon-restore {
font-weight: bold;
color: #257aa7;
}
-body.ttrss_main #headlines-wrap-inner {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
+ padding: 8px;
+ grid-gap: 8px;
+ background-color: #222;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > * {
+ /* 2 = because #headlines-spacer is the actual last child
+ only if odd to deal with 1) single article and 2) not break any previous rows;
+ 1 = spacer;
+
+ this is outside of .cdm selector because of #headlines-spacer etc
+
+ .grid-span-row is manually expanded RROWs
+ */
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *.grid-span-row,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(2):nth-child(odd),
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] > *:nth-last-child(1) {
+ grid-column: 1 / -1;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ background: #333;
+ border: 1px solid #222;
+ overflow: hidden;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content {
+ border-top-width: 0;
+ padding: 0 4px 4px 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header[data-is-stuck] {
+ top: -8px;
+ border-bottom-width: 1px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header {
+ border-bottom-width: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .icon-grid-span {
+ display: inline;
}
-body.ttrss_main #headlines-frame[is-vfeed="0"] .header .feed {
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .header .feed {
display: none;
}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer {
+ border: 0;
+ padding: 4px;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .right {
+ white-space: nowrap;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .footer .left {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .content-inner a,
+body.ttrss_main #headlines-frame:not([data-headlines-count="0"])[data-is-cdm="true"][data-is-cdm-expanded="true"][data-enable-grid="true"] .cdm.expanded .intermediate a {
+ word-break: break-all;
+}
body.ttrss_main #headlines-frame {
- padding: 0px;
- border: 0px #222;
- margin-top: 0px;
+ padding: 0;
+ border: 0;
+ margin-top: 0;
-webkit-overflow-scrolling: touch;
-webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .header .icon-feed,
+body.ttrss_main #headlines-frame[data-is-vfeed="false"] .hl .icon-feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame[data-auto-catchup="true"] #headlines-spacer {
+ height: 100vh;
+}
+body.ttrss_main #headlines-frame .dijitCheckBox {
+ margin-right: 4px;
+}
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .title {
+ overflow: visible;
+ white-space: normal;
}
-body.ttrss_main #headlines-frame div.feed-title {
+body.ttrss_main #headlines-frame[data-is-wide-screen="true"] .hl .feed {
+ display: none;
+}
+body.ttrss_main #headlines-frame #headlines-spacer {
+ margin-left: 1px;
+ text-align: center;
+ color: #ccc;
+ font-size: 11px;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a,
+body.ttrss_main #headlines-frame #headlines-spacer span {
+ color: #ccc;
+ padding: 10px;
+ display: block;
+}
+body.ttrss_main #headlines-frame #headlines-spacer a:hover {
+ color: #257aa7;
+}
+body.ttrss_main #headlines-frame .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 8px;
}
-body.ttrss_main #headlines-frame div.feed-title a.title {
+body.ttrss_main #headlines-frame .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-body.ttrss_main #headlines-frame div.feed-title a {
+body.ttrss_main #headlines-frame .feed-title a {
color: #ccc;
}
-body.ttrss_main #headlines-frame div.feed-title a:hover {
+body.ttrss_main #headlines-frame .feed-title a:hover {
color: #257aa7;
}
body.ttrss_main #headlines-frame span.hlMenuAttach {
-webkit-touch-callout: none;
-webkit-user-select: none;
+ user-select: none;
}
body.ttrss_main #toolbar-frame_splitter {
display: none;
}
body.ttrss_main #toolbar-frame {
- padding: 0px;
- margin: 0px;
- border-width: 0px;
+ padding: 0;
+ margin: 0;
+ border: 0;
white-space: nowrap;
- font-size: 12px;
+ font-size: 13px;
}
body.ttrss_main #toolbar-frame #toolbar {
background: white;
- border: 0px solid #222;
+ border: 0 solid #222;
border-bottom-width: 1px;
padding-left: 4px;
height: 32px;
@@ -691,13 +759,13 @@ body.ttrss_main #toolbar-frame #toolbar {
flex-direction: row;
flex-wrap: nowrap;
color: #ccc;
- font-size: 12px;
+ font-size: 13px;
align-items: center;
}
body.ttrss_main #toolbar-frame #toolbar .dijitSelect,
body.ttrss_main #toolbar-frame #toolbar .dijitDropDownButton .dijitButtonNode,
body.ttrss_main #toolbar-frame #toolbar .dijitComboButton .dijitButtonNode {
- border: 0px;
+ border: 0;
}
body.ttrss_main #toolbar-frame #toolbar i.net-alert,
body.ttrss_main #toolbar-frame #toolbar .left i.icon-error {
@@ -711,7 +779,7 @@ body.ttrss_main #toolbar-frame #toolbar i {
margin: 0 4px;
}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines {
- font-size: 12px;
+ font-size: 13px;
background: transparent;
padding-right: 4px;
flex-grow: 2;
@@ -726,6 +794,12 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search {
margin-left: 4px;
}
+@media (max-width: 768px) {
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title,
+ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left i.icon-syndicate {
+ display: none;
+ }
+}
body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right {
display: flex;
align-items: center;
@@ -740,20 +814,26 @@ body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
margin-right: 4px;
color: #257aa7;
}
-@media (max-width: 992px) {
+@media (max-width: 768px) {
body.ttrss_main #toolbar-frame #toolbar #selected_prompt {
display: none;
}
}
+@media (max-width: 576px) {
+ body.ttrss_main #toolbar-frame #toolbar .select-articles-dropdown,
+ body.ttrss_main #toolbar-frame #toolbar .catchup-button {
+ display: none;
+ }
+}
body.ttrss_main #header {
- border-width: 0px;
text-align: right;
color: #ccc;
- padding: 5px 5px 0px 0px;
- margin: 0px;
+ padding: 5px 5px 0 0px;
position: absolute;
- right: 0px;
- top: 0px;
+ border: 0;
+ margin: 0;
+ right: 0;
+ top: 0;
z-index: 5;
}
body.ttrss_main #header i.net-alert,
@@ -772,9 +852,8 @@ body.ttrss_main #header i {
margin: 0 4px;
}
body.ttrss_main #content-insert {
- padding: 0px;
- border-color: #222;
- border-width: 0px;
+ padding: 0;
+ border: 0;
line-height: 1.5;
overflow: auto;
-webkit-overflow-scrolling: touch;
@@ -787,59 +866,11 @@ body.ttrss_main img.icon {
vertical-align: middle;
display: inline-block;
}
-body.ttrss_main .player {
- display: inline-block;
- color: #ccc;
- font-size: 11px;
- font-family: sans-serif;
- border: 1px solid #ccc;
- padding: 0px 4px 0px 4px;
- margin: 0px 2px 0px 2px;
- width: 50px;
- text-align: center;
- background: #333;
-}
-body.ttrss_main .player.playing {
- color: #00c000;
- border-color: #00c000;
-}
-body.ttrss_main .player:hover {
- background: #222;
- cursor: pointer;
-}
-body.ttrss_main #headlines-frame.auto_catchup #headlines-spacer {
- height: 100%;
-}
-body.ttrss_main #headlines-spacer {
- margin-left: 1px;
- text-align: center;
- color: #ccc;
- font-size: 11px;
- font-style: italic;
-}
-body.ttrss_main #headlines-spacer a,
-body.ttrss_main #headlines-spacer span {
- color: #ccc;
- padding: 10px;
- display: block;
-}
-body.ttrss_main #headlines-spacer a:hover {
- color: #257aa7;
-}
body.ttrss_main ul#filterDlg_Matches,
body.ttrss_main ul#filterDlg_Actions {
list-style-type: none;
margin: 0;
padding: 0;
- /*max-height : 100px;
- overflow : auto;
- border-style : solid;
- border-color : @border-default;
- border-width : 1px 1px 1px 1px;
- background-color : @default-bg;
- margin : 0px 0px 5px 0px;
- padding : 4px;
- min-height : 16px;*/
}
body.ttrss_main ul#filterDlg_Matches li,
body.ttrss_main ul#filterDlg_Actions li {
@@ -875,9 +906,6 @@ body.ttrss_main span.highlight {
background-color: #ffff00;
color: #cc90cc;
}
-body.ttrss_main #headlines-frame .dijitCheckBox {
- margin-right: 4px;
-}
body.ttrss_main #feedEditDlg img.feedIcon {
border: 1px solid #ccc;
padding: 5px;
@@ -935,6 +963,11 @@ body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-show
body.ttrss_main:not([view-mode="marked"])[hide-read-feeds="true"][hide-read-shows-special="false"] #feeds-holder #feedTree .dijitTreeRow:not(.Unread):not(.AlwaysVisible) {
display: none;
}
+body.ttrss_main {
+ /*.score-neutral i.icon-score {
+ opacity : 0.5;
+ }*/
+}
body.ttrss_main #toolbar-headlines i.icon-syndicate {
color: #ff7c4b;
margin-right: 8px;
@@ -971,10 +1004,15 @@ body.ttrss_main .score-high i.icon-score {
body.ttrss_main .score-low i.icon-score {
color: #500;
}
-body.ttrss_main .score-neutral i.icon-score {
- opacity: 0.5;
+body.ttrss_main i.icon-score,
+body.ttrss_main i.icon-grid-span {
+ cursor: pointer;
+ color: #999;
}
-body.ttrss_main i.icon-score {
+body.ttrss_main .icon-grid-span {
+ display: none;
+}
+body.ttrss_main .icon-feed {
cursor: pointer;
}
body.ttrss_main .panel {
@@ -1005,20 +1043,62 @@ body.ttrss_main ul.list-unstyled {
body.ttrss_main .text-center {
text-align: center;
}
-body.ttrss_main #prefFilterTestResultList .preview {
+body.ttrss_main .text-right {
+ text-align: right;
+}
+body.ttrss_main .text-left {
+ text-align: left;
+}
+body.ttrss_main .dijitDialog .filter-results-list .preview {
margin: 8px;
}
-body.ttrss_main #prefFilterTestResultList .title {
+body.ttrss_main .dijitDialog .filter-results-list .title {
font-weight: bold;
}
-body.ttrss_main #prefFilterTestResultList .feed {
- color: #257aa7;
+body.ttrss_main .dijitDialog #feed_add_spinner {
+ position: relative;
+ top: 5px;
+ width: 18px;
+ height: 18px;
+}
+body.ttrss_main .icon-three-dots {
+ width: 18px;
+ height: 18px;
+ vertical-align: middle;
+}
+body.ttrss_main,
+body.ttrss_utility {
+ /*div.autocomplete {
+ position : absolute;
+ width : 250px;
+ background-color : @default-bg;
+ border :1px solid @border-default;
+ margin : 0px;
+ padding : 0px;
+
+ ul {
+ list-style-type : none;
+ margin : 0px;
+ padding : 0px;
+ }
+
+ ul li.selected {
+ background-color : darken(@default-bg, 10%);
+ }
+
+ ul li {
+ list-style-type : none;
+ display : block;
+ margin : 0;
+ padding : 2px;
+ cursor : pointer;
+ }
+ }*/
}
body.ttrss_main .alert,
body.ttrss_utility .alert {
padding: 8px 35px 8px 14px;
margin-bottom: 10px;
- /* text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); */
background-color: #fcf8e3;
border: 1px solid #fbeed5;
border-radius: 4px;
@@ -1059,6 +1139,16 @@ body.ttrss_main .text-warning,
body.ttrss_utility .text-warning {
color: #a47e3c;
}
+body.ttrss_main .text-muted,
+body.ttrss_utility .text-muted {
+ color: #ccc;
+}
+body.ttrss_main .text-small,
+body.ttrss_utility .text-small,
+body.ttrss_main .small,
+body.ttrss_utility .small {
+ font-size: 11px;
+}
body.ttrss_main .alert,
body.ttrss_utility .alert,
body.ttrss_main .alert h4,
@@ -1108,41 +1198,6 @@ body.ttrss_utility hr {
border: 0px solid #ccc;
border-bottom-width: 1px;
}
-body.ttrss_main .text-muted,
-body.ttrss_utility .text-muted {
- color: #ccc;
-}
-body.ttrss_main .small,
-body.ttrss_utility .small {
- font-size: 11px;
-}
-body.ttrss_main div.autocomplete,
-body.ttrss_utility div.autocomplete {
- position: absolute;
- width: 250px;
- background-color: #333;
- border: 1px solid #222;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul,
-body.ttrss_utility div.autocomplete ul {
- list-style-type: none;
- margin: 0px;
- padding: 0px;
-}
-body.ttrss_main div.autocomplete ul li.selected,
-body.ttrss_utility div.autocomplete ul li.selected {
- background-color: #1a1a1a;
-}
-body.ttrss_main div.autocomplete ul li,
-body.ttrss_utility div.autocomplete ul li {
- list-style-type: none;
- display: block;
- margin: 0;
- padding: 2px;
- cursor: pointer;
-}
::selection {
background: #257aa7;
color: #333;
@@ -1156,16 +1211,13 @@ body.ttrss_utility div.autocomplete ul li {
::-webkit-scrollbar-track {
background-color: #eee;
}
-video::-webkit-media-controls-overlay-play-button {
- display: none;
-}
-.cdm i.material-icons {
- color: #777;
-}
-.cdm .header {
- position: sticky;
- top: 0;
- z-index: 3;
+/*video::-webkit-media-controls-overlay-play-button {
+ display: none;
+}*/
+.cdm {
+ /*i.material-icons {
+ color : @color-icon;
+ }*/
}
.cdm .header,
.cdm .footer {
@@ -1176,13 +1228,16 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header img,
.cdm .footer img,
.cdm .footer i.material-icons {
- margin: 0px 4px;
+ margin: 0 4px;
vertical-align: middle;
}
.cdm .header-sticky-guard {
height: 0;
}
.cdm .header {
+ position: sticky;
+ top: 0;
+ z-index: 3;
align-items: center;
}
.cdm .header > * {
@@ -1205,7 +1260,7 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header .titleWrap {
flex-grow: 2;
}
-.cdm .header span.updated {
+.cdm .header .updated {
color: #ccc;
font-weight: normal;
font-size: 11px;
@@ -1214,6 +1269,30 @@ video::-webkit-media-controls-overlay-play-button {
.cdm .header input {
margin: 0px 4px;
}
+.cdm .header .feed {
+ float: right;
+ font-weight: normal;
+ font-style: italic;
+}
+.cdm .header .feed a {
+ border-radius: 4px;
+ display: inline-block;
+ padding: 1px 4px 1px 4px;
+}
+.cdm .header .feed,
+.cdm .header .feed a {
+ vertical-align: middle;
+ color: #ccc;
+ font-weight: normal;
+ font-style: italic;
+ font-size: 11px;
+}
+.cdm .header .author {
+ white-space: nowrap;
+ color: #ccc;
+ font-size: 11px;
+ font-weight: normal;
+}
.cdm .footer {
height: 30px;
padding-left: 5px;
@@ -1222,30 +1301,37 @@ video::-webkit-media-controls-overlay-play-button {
clear: both;
align-items: center;
}
+.cdm .footer i.material-icons {
+ color: #999;
+}
.cdm .footer .left {
flex-grow: 2;
}
.cdm .intermediate {
margin-top: 10px;
margin-left: 10px;
+ line-height: 1.5;
}
.cdm .content-inner {
margin: 10px;
line-height: 1.5;
font-size: 16px;
}
+.cdm .intermediate iframe,
+.cdm .content-inner iframe {
+ max-width: 98%;
+ width: auto;
+ height: auto;
+}
.cdm .intermediate img,
.cdm .intermediate video,
.cdm .content-inner img,
.cdm .content-inner video {
border-width: 0px;
max-width: 98%;
+ width: auto;
height: auto;
}
-.cdm.expanded {
- /*margin-top : 4px;
- margin-bottom : 4px;*/
-}
.cdm.expanded .collapse,
.cdm.expanded .excerpt {
display: none;
@@ -1258,72 +1344,54 @@ video::-webkit-media-controls-overlay-play-button {
border-bottom-width: 1px;
}
.cdm.expanded > hr {
- margin-top: 0px;
- margin-bottom: 0px;
+ margin-top: 0;
+ margin-bottom: 0;
}
-div.cdm.expanded div.header a.title {
+.cdm.expanded .header a.title {
font-size: 16px;
color: #999;
font-weight: 600;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expanded.active {
- background: white;
+.cdm.expanded.active .content,
+.cdm.expanded.Unread .content {
+ color: black;
}
-div.cdm.expanded.active div.header a.title {
+.cdm.expanded.active .header .title {
color: #257aa7;
}
-div.cdm.expanded.Unread div.header a.title {
+.cdm.expanded.Unread .header .title {
color: black;
}
-div.cdm.expanded div.content {
+.cdm.expanded .content {
color: #ccc;
}
-div.cdm.expanded.Unread div.content {
- color: black;
-}
-div.cdm.active div.content {
- color: black;
-}
-div.cdm.vgrlf .feed {
+.cdm.vgrlf .feed {
display: none;
}
-.cdm div.feed-title {
+.cdm .feed-title {
border: 0px solid #257aa7;
border-bottom-width: 1px;
padding: 5px 3px 5px 5px;
}
-.cdm div.feed-title a.title {
+.cdm .feed-title a.title {
color: #ccc;
font-weight: bold;
}
-.cdm div.feed-title a {
+.cdm .feed-title a {
color: #ccc;
}
-.cdm div.feed-title a:hover {
+.cdm .feed-title a:hover {
color: #257aa7;
}
-.cdm div.header span.feed {
- float: right;
- font-weight: normal;
- font-style: italic;
-}
-.cdm div.header div.feed,
-.cdm div.header div.feed a {
- vertical-align: middle;
- color: #ccc;
- font-weight: normal;
- font-style: italic;
- font-size: 11px;
-}
-.cdm div.content-inner div.embed-responsive {
+.cdm .content-inner .embed-responsive {
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
}
-.cdm div.content-inner div.embed-responsive iframe {
+.cdm .content-inner .embed-responsive iframe {
border: 0;
bottom: 0;
height: 100%;
@@ -1332,17 +1400,6 @@ div.cdm.vgrlf .feed {
top: 0;
width: 100%;
}
-.cdm div.header span.author {
- white-space: nowrap;
- color: #ccc;
- font-size: 11px;
- font-weight: normal;
-}
-.cdm .feed a {
- border-radius: 4px;
- display: inline-block;
- padding: 1px 4px 1px 4px;
-}
.cdm.expandable {
background-color: #222;
border: 0px solid #222;
@@ -1380,43 +1437,43 @@ div.cdm.vgrlf .feed {
.cdm.expandable.active {
background: white ! important;
}
-div.cdm.expandable.active div.header span.titleWrap {
+.cdm.expandable.active div.header span.titleWrap {
white-space: normal;
}
-div.cdm.expandable div.header a.title {
+.cdm.expandable .header a.title {
font-weight: 600;
color: #ccc;
font-size: 14px;
transition: color 0.2s, background 0.2s;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable.Unread div.header a.title {
+.cdm.expandable.Unread div.header a.title {
color: black;
}
-div.cdm.expandable.active .collapse i.material-icons {
+.cdm.expandable.active .collapse i.material-icons {
color: #257aa7;
cursor: pointer;
}
-div.cdm.expandable.active .excerpt {
+.cdm.expandable.active .excerpt {
display: none;
}
-div.cdm.expandable.active div.header a.title {
+.cdm.expandable.active div.header a.title {
color: #257aa7;
font-size: 16px;
font-weight: 600;
text-rendering: optimizelegibility;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
-div.cdm.expandable:not(.active) {
+.cdm.expandable:not(.active) {
cursor: pointer;
}
-div.cdm.expandable:not(.active) .content,
-div.cdm.expandable:not(.active) .collapse {
+.cdm.expandable:not(.active) .content,
+.cdm.expandable:not(.active) .collapse {
display: none;
}
-div.cdm.expandable.active .header[stuck],
-div.cdm.expanded .header[stuck] {
+.cdm.expandable.active .header[data-is-stuck],
+.cdm.expanded .header[data-is-stuck] {
box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
border: 0 solid #222;
border-bottom-width: 1px;
@@ -1433,7 +1490,7 @@ body.ttrss_prefs h1,
body.ttrss_prefs h2,
body.ttrss_prefs h3,
body.ttrss_prefs h4 {
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 600;
color: #ccc;
}
@@ -1504,14 +1561,6 @@ body.ttrss_prefs fieldset.prefs .help-text {
body.ttrss_prefs fieldset.prefs .help-text-bottom {
margin-top: 10px;
}
-body.ttrss_prefs fieldset.plugin label.description {
- width: 550px;
- margin-right: 150px;
- display: inline-block;
-}
-body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox {
- margin-right: 10px;
-}
body.ttrss_prefs table th {
text-align: left;
}
@@ -1539,17 +1588,26 @@ body.ttrss_prefs ul.prefs-plugin-list li > * {
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox {
display: flex;
align-items: center;
- min-width: 300px;
cursor: pointer;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system {
cursor: auto;
}
body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 300px;
flex-grow: 2;
display: inline-block;
text-align: right;
font-weight: bold;
+ margin-right: 20px;
+}
+@media (max-width: 992px) {
+ body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name {
+ min-width: 200px ! important;
+ }
+ body.ttrss_prefs ul.prefs-plugin-list li .version {
+ display: none;
+ }
}
body.ttrss_prefs ul.prefs-plugin-list li .actions {
flex-grow: 2;
@@ -1603,6 +1661,11 @@ body.ttrss_prefs .event-log tr .errno {
body.ttrss_prefs .event-log tr .errstr {
word-break: break-all;
white-space: pre-wrap;
+ width: 30%;
+}
+body.ttrss_prefs .event-log tr .filename {
+ word-break: break-all;
+ width: 20%;
}
body.ttrss_prefs .event-log tr .filename,
body.ttrss_prefs .event-log tr .login,
@@ -1661,12 +1724,16 @@ body.ttrss_utility fieldset > label.checkbox {
display: inline;
font-weight: normal;
}
+.flat {
+ /*#feedTree {
+ .dijitTreeContent .dijitInline {
+ vertical-align : baseline;
+ }
+ }*/
+}
.flat li {
padding: 2px;
}
-.flat #feedTree .dijitTreeContent .dijitInline {
- vertical-align: baseline;
-}
.flat .dijitButton i.material-icons {
position: relative;
top: -1px;
@@ -1690,7 +1757,8 @@ body.ttrss_utility fieldset > label.checkbox {
}
.flat .dijitToolbar {
font-size: 13px;
- padding: 0px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 0;
}
.flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner {
line-height: 10px;
@@ -1713,12 +1781,13 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel {
padding: 4px 8px;
font-size: 13px;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.flat .dijitMenu .dijitMenuItem.dijitDisabled:not(.dijitMenuItemSelected) .dijitMenuItemLabel {
color: #2e99d1;
}
.flat .dijitMenu .dijitMenuItem td {
- padding: 0px;
+ padding: 0;
}
.flat .dijitCheckBox {
margin: 1px;
@@ -1728,10 +1797,33 @@ body.ttrss_utility fieldset > label.checkbox {
content: "\f00c";
color: white;
}
+.flat .dijitTab,
+.flat .dijitAccordionTitle {
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
.flat .dijitTab i.material-icons,
.flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons {
color: #257aa7;
}
+.flat .dijitTree {
+ /*.dijitTreeRow .dijitTreeExpando {
+ position : relative;
+ top : -2px;
+ }*/
+}
+.flat .dijitTree .dijitTreeRowFlex {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeIcon {
+ font-size: inherit;
+ height: auto;
+}
+.flat .dijitTree .dijitTreeRowFlex .dijitTreeExpando {
+ height: auto;
+ line-height: 0;
+}
.flat .dijitTree .dijitFolderClosed,
.flat .dijitTree .dijitFolderOpened {
display: none;
@@ -1745,10 +1837,6 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeNode .dijitTreeRow.dijitTreeRowSelected {
color: white;
}
-.flat .dijitTree .dijitTreeRow .dijitTreeExpando {
- position: relative;
- top: -2px;
-}
.flat .dijitTree .labelParam {
float: right;
margin-right: 16px;
@@ -1777,6 +1865,7 @@ body.ttrss_utility fieldset > label.checkbox {
.flat .dijitTree .dijitTreeRow {
overflow: hidden;
-moz-user-select: none;
+ user-select: none;
text-overflow: ellipsis;
}
.flat label.dijitButton {
@@ -1852,7 +1941,7 @@ body.ttrss_utility .content h2,
body.ttrss_utility .content h3,
body.ttrss_utility .content h4 {
color: #257aa7;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body.ttrss_utility .content h2 {
font-size: 18px;
@@ -1871,7 +1960,7 @@ body.ttrss_utility a:focus {
}
body.ttrss_utility h1 {
color: gray;
- font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
margin: 10px 0 0 0;
}
@@ -1940,11 +2029,11 @@ body.ttrss_zoom div.post .attachments {
display: none;
}
body.ttrss_zoom div.post div.header {
- padding-bottom: 10px;
- border: 0px solid #222;
+ padding-bottom: 8px;
+ border: 0 solid #222;
border-bottom-width: 1px;
background: #333;
- font-size: 12px;
+ font-size: 13px;
color: #ccc;
}
body.ttrss_zoom div.post div.header .row {
@@ -1954,32 +2043,36 @@ body.ttrss_zoom div.post div.header .row {
align-items: center;
justify-content: space-between;
}
-body.ttrss_zoom div.post div.content {
+body.ttrss_zoom div.post div.header .row h1 {
+ margin-top: 0;
+ margin-bottom: 8px;
+}
+body.ttrss_zoom div.post .content {
font-size: 15px;
line-height: 1.5;
border-width: 0;
padding: 0;
+ padding-top: 8px;
}
-body.ttrss_zoom div.post div.content img,
-body.ttrss_zoom div.post div.content video {
+body.ttrss_zoom div.post .content img,
+body.ttrss_zoom div.post .content video {
max-width: 760px;
height: auto;
}
-body.ttrss_zoom div.post div.content blockquote {
+body.ttrss_zoom div.post .content blockquote {
margin: 5px 0px 5px 0px;
color: #ccc;
- padding-left: 10px;
+ padding-left: 8px;
border: 0px solid #222;
border-left-width: 4px;
}
-body.ttrss_zoom div.post div.content code {
+body.ttrss_zoom div.post .content code {
color: #009900;
font-family: monospace;
font-size: 12px;
}
-body.ttrss_zoom div.post div.content pre {
- margin: 5px 0px 5px 0px;
- padding: 10px;
+body.ttrss_zoom div.post .content pre {
+ padding: 8px;
color: #ccc;
font-family: monospace;
font-size: 12px;
@@ -2023,26 +2116,34 @@ body.flat.ttrss_main #feeds-holder {
background: #222;
box-shadow: inset -1px 0px 2px -1px #666;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.aux,
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.aux,
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
background: #222;
color: #ccc;
border-color: #333;
}
-body.flat.ttrss_main #feeds-holder #feedTree .counterNode.marked {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .counterNode.marked {
border-color: #257aa7;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected {
background: #333;
border-color: #333 transparent;
color: #e6e6e6;
}
-body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLabel {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .dijitTreeRowSelected .dijitTreeLabel {
text-shadow: none;
}
-body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox {
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow i.icon.icon-inbox {
color: #999999;
}
+body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRow .loadingNode {
+ filter: invert(1);
+}
+body.flat.ttrss_main #headlines-frame {
+ /*.cdm.expanded {
+ background: @default-bg;
+ }*/
+}
body.flat.ttrss_main #headlines-frame .hl:not(.active):not(.Selected):not(.Unread),
body.flat.ttrss_main #headlines-frame .cdm.expandable:not(.active):not(.Selected):not(.Unread) {
background: #333;
@@ -2051,9 +2152,6 @@ body.flat.ttrss_main #headlines-frame .hl.Unread:not(.active):not(.Selected),
body.flat.ttrss_main #headlines-frame .cdm.expandable.Unread:not(.active):not(.Selected) {
background: #222;
}
-body.flat.ttrss_main #headlines-frame .cdm.expanded {
- background: #333;
-}
body.flat.ttrss_main #headlines-frame .hl.Unread .title,
body.flat.ttrss_main #headlines-frame .cdm.Unread .title {
color: #e6e6e6;
@@ -2226,3 +2324,6 @@ body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextAreaError {
body.flat.ttrss_main #filterNewRuleDlg .dijitValidationTextArea:not(.dijitValidationTextAreaError) {
background: #305030;
}
+body.flat.ttrss_main .dijitDialog #feed_add_spinner {
+ filter: invert(1);
+}
diff --git a/update.php b/update.php
index 956aa8548..079069a3b 100755
--- a/update.php
+++ b/update.php
@@ -74,31 +74,34 @@
init_plugins();
- $longopts = array("feeds",
- "daemon",
- "daemon-loop",
- "update-feed:",
- "send-digests",
- "task:",
- "cleanup-tags",
- "quiet",
- "log:",
- "log-level:",
- "indexes",
- "pidlock:",
- "update-schema::",
- "convert-filters",
- "force-update",
- "gen-search-idx",
- "list-plugins",
- "debug-feed:",
- "force-refetch",
- "force-rehash",
- "opml-export:",
- "help");
+ $options_map = [
+ "feeds" => "update all pending feeds",
+ "daemon" => "start single-process update daemon",
+ "daemon-loop" => "",
+ "update-feed:" => "",
+ "send-digests" => "send pending email digests",
+ "task:" => "",
+ "cleanup-tags" => "perform maintenance on tags table",
+ "quiet" => "don't output messages to stdout",
+ "log:" => ["FILE", "log messages to FILE"],
+ "log-level:" => ["N", "set log verbosity level (0-2)"],
+ "pidlock:" => "",
+ "update-schema::" => ["[force-yes]", "update database schema, optionally without prompting"],
+ "force-update" => "mark all feeds as pending update",
+ "gen-search-idx" => "generate basic PostgreSQL fulltext search index",
+ "plugins-list" => "list installed plugins",
+ "debug-feed:" => ["N", "update specified feed with debug output enabled"],
+ "debug-force-refetch" => "debug update: force refetch feed data",
+ "debug-force-rehash" => "debug update: force rehash articles",
+ "opml-export:" => ["USER:FILE", "export OPML of USER to FILE"],
+ "user-list" => "list all users",
+# "user-add:" => ["USER[:PASSWORD]", "add USER, optionally without prompting for PASSWORD"],
+# "user-remove:" => ["USERNAME", "remove specified user"],
+ "help" => "",
+ ];
foreach (PluginHost::getInstance()->get_commands() as $command => $data) {
- array_push($longopts, $command . $data["suffix"]);
+ $options_map[$command . $data["suffix"]] = [ $data["arghelp"] ?? "", $data["description"] ];
}
if (php_sapi_name() != "cli") {
@@ -107,35 +110,32 @@
exit;
}
- $options = getopt("", $longopts);
+ $options = getopt("", array_keys($options_map));
if (count($options) == 0 || isset($options["help"]) ) {
- print "Tiny Tiny RSS data update script.\n\n";
- print "Options:\n";
- print " --feeds - update feeds\n";
- print " --daemon - start single-process update daemon\n";
- print " --task N - create lockfile using this task id\n";
- print " --cleanup-tags - perform tags table maintenance\n";
- print " --quiet - don't output messages to stdout\n";
- print " --log FILE - log messages to FILE\n";
- print " --log-level N - log verbosity level\n";
- print " --indexes - recreate missing schema indexes\n";
- print " --update-schema[=force-yes] - update database schema (without prompting)\n";
- print " --gen-search-idx - generate basic PostgreSQL fulltext search index\n";
- print " --convert-filters - convert type1 filters to type2\n";
- print " --send-digests - send pending email digests\n";
- print " --force-update - force update of all feeds\n";
- print " --list-plugins - list all available plugins\n";
- print " --debug-feed N - perform debug update of feed N\n";
- print " --force-refetch - debug update: force refetch feed data\n";
- print " --force-rehash - debug update: force rehash articles\n";
- print " --opml-export \"USER FILE\" - export feeds of selected user to OPML\n";
- print " --help - show this help\n";
- print "Plugin options:\n";
-
- foreach (PluginHost::getInstance()->get_commands() as $command => $data) {
- $args = $data['arghelp'];
- printf(" --%-26s - %s\n", "$command $args", $data["description"]);
+ print "Tiny Tiny RSS CLI management tool\n";
+ print "=================================\n";
+ print "Options:\n\n";
+
+ $options_help = [];
+
+ foreach ($options_map as $option => $descr) {
+ if (substr($option, -1) === ":")
+ $option = substr($option, 0, -1);
+
+ $help_key = trim(sprintf("--%s %s",
+ $option, is_array($descr) ? $descr[0] : ""));
+ $help_value = is_array($descr) ? $descr[1] : $descr;
+
+ if ($help_value)
+ $options_help[$help_key] = $help_value;
+ }
+
+ $max_key_len = array_reduce(array_keys($options_help),
+ function ($carry, $item) { $len = strlen($item); return $len > $carry ? strlen($item) : $carry; });
+
+ foreach ($options_help as $option => $help_text) {
+ printf(" %s %s\n", str_pad($option, $max_key_len + 5), $help_text);
}
return;
@@ -263,112 +263,6 @@
Debug::log("$rc tags deleted.\n");
}
- if (isset($options["indexes"])) {
- Debug::log("PLEASE BACKUP YOUR DATABASE BEFORE PROCEEDING!");
- Debug::log("Type 'yes' to continue.");
-
- if (read_stdin() != 'yes')
- exit;
-
- Debug::log("clearing existing indexes...");
-
- if (Config::get(Config::DB_TYPE) == "pgsql") {
- $sth = $pdo->query( "SELECT relname FROM
- pg_catalog.pg_class WHERE relname LIKE 'ttrss_%'
- AND relname NOT LIKE '%_pkey'
- AND relkind = 'i'");
- } else {
- $sth = $pdo->query( "SELECT index_name,table_name FROM
- information_schema.statistics WHERE index_name LIKE 'ttrss_%'");
- }
-
- while ($line = $sth->fetch()) {
- if (Config::get(Config::DB_TYPE) == "pgsql") {
- $statement = "DROP INDEX " . $line["relname"];
- Debug::log($statement);
- } else {
- $statement = "ALTER TABLE ".
- $line['table_name']." DROP INDEX ".$line['index_name'];
- Debug::log($statement);
- }
- $pdo->query($statement);
- }
-
- Debug::log("reading indexes from schema for: " . Config::get(Config::DB_TYPE));
-
- $fp = fopen("schema/ttrss_schema_" . Config::get(Config::DB_TYPE) . ".sql", "r");
- if ($fp) {
- while ($line = fgets($fp)) {
- $matches = array();
-
- if (preg_match("/^create index ([^ ]+) on ([^ ]+)$/i", $line, $matches)) {
- $index = $matches[1];
- $table = $matches[2];
-
- $statement = "CREATE INDEX $index ON $table";
-
- Debug::log($statement);
- $pdo->query($statement);
- }
- }
- fclose($fp);
- } else {
- Debug::log("unable to open schema file.");
- }
- Debug::log("all done.");
- }
-
- if (isset($options["convert-filters"])) {
- Debug::log("WARNING: this will remove all existing type2 filters.");
- Debug::log("Type 'yes' to continue.");
-
- if (read_stdin() != 'yes')
- exit;
-
- Debug::log("converting filters...");
-
- $pdo->query("DELETE FROM ttrss_filters2");
-
- $res = $pdo->query("SELECT * FROM ttrss_filters ORDER BY id");
-
- while ($line = $res->fetch()) {
- $owner_uid = $line["owner_uid"];
-
- // date filters are removed
- if ($line["filter_type"] != 5) {
- $filter = array();
-
- if (sql_bool_to_bool($line["cat_filter"])) {
- $feed_id = "CAT:" . (int)$line["cat_id"];
- } else {
- $feed_id = (int)$line["feed_id"];
- }
-
- $filter["enabled"] = $line["enabled"] ? "on" : "off";
- $filter["rule"] = array(
- json_encode(array(
- "reg_exp" => $line["reg_exp"],
- "feed_id" => $feed_id,
- "filter_type" => $line["filter_type"])));
-
- $filter["action"] = array(
- json_encode(array(
- "action_id" => $line["action_id"],
- "action_param_label" => $line["action_param"],
- "action_param" => $line["action_param"])));
-
- // Oh god it's full of hacks
-
- $_REQUEST = $filter;
- $_SESSION["uid"] = $owner_uid;
-
- $filters = new Pref_Filters($_REQUEST);
- $filters->add();
- }
- }
-
- }
-
if (isset($options["update-schema"])) {
if (Config::is_migration_needed()) {
@@ -431,7 +325,7 @@
}
}
- if (isset($options["list-plugins"])) {
+ if (isset($options["plugins-list"])) {
$tmppluginhost = new PluginHost();
$tmppluginhost->load_all($tmppluginhost::KIND_ALL);
$enabled = array_map("trim", explode(",", Config::get(Config::PLUGINS)));
@@ -470,8 +364,19 @@
Digest::send_headlines_digests();
}
+ if (isset($options["user-list"])) {
+ $users = ORM::for_table('ttrss_users')
+ ->order_by_expr('id')
+ ->find_many();
+
+ foreach ($users as $user) {
+ printf ("%-4d\t%-15s\t%-20s\t%-20s\n",
+ $user->id, $user->login, $user->full_name, $user->email);
+ }
+ }
+
if (isset($options["opml-export"])) {
- list ($user, $filename) = explode(" ", $options["opml-export"], 2);
+ list ($user, $filename) = explode(":", $options["opml-export"], 2);
Debug::log("Exporting feeds of user $user to $filename as OPML...");