diff options
53 files changed, 3003 insertions, 2537 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/classes/api.php b/classes/api.php index a1ed7968c..407afabad 100755 --- a/classes/api.php +++ b/classes/api.php @@ -792,7 +792,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; 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/handler/public.php b/classes/handler/public.php index 2de073cc2..d5319c306 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -638,9 +638,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) { 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/pref/prefs.php b/classes/pref/prefs.php index 16c41df9d..1d61059cb 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) @@ -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> 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..bde0b1e46 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); } @@ -603,6 +603,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 +664,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 +678,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..d797838ba 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -1422,8 +1422,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 +1431,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)) 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/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) { @@ -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"]; ?>"; @@ -199,7 +197,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')"> @@ -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); @@ -1102,6 +1109,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 +1207,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..4388b41e6 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()}`); @@ -389,10 +399,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/FeedTree.js b/js/FeedTree.js index 17cd3deea..af0f420d6 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,6 +135,9 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dojo/_base/array", "dojo/co } if (id.match("CAT:")) { + tnode.rowNode.setAttribute('data-feed-id', bare_id); + tnode.rowNode.setAttribute('data-is-cat', "true"); + tnode.loadingNode = dojo.create('img', { className: 'loadingNode', src: 'images/blank_icon.gif'}); domConstruct.place(tnode.loadingNode, tnode.labelNode, 'after'); } diff --git a/js/Feeds.js b/js/Feeds.js index 33a1fa3dc..7b6366959 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) { @@ -311,18 +311,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); diff --git a/js/Headlines.js b/js/Headlines.js index 28e43be1f..58348aca7 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) { @@ -371,6 +382,9 @@ const Headlines = { } } } + + PluginHost.run(PluginHost.HOOK_HEADLINES_SCROLL_HANDLER); + } catch (e) { console.warn("scrollHandler", e); } @@ -378,11 +392,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 +413,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 +442,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 +521,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> @@ -560,7 +588,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 +642,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 +699,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 { @@ -799,6 +831,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 +852,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..cd831d4d0 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"); 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..8c1154566 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; @@ -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..0d876c423 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,19 +31,12 @@ 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><summary>" . __("Not safe for work (click to toggle)") . "</summary>" . $article["content"] . "</details>"; } return $article; @@ -55,7 +44,7 @@ class NSFW extends Plugin { 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..4ad788428 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -189,18 +189,19 @@ class Share extends Plugin { <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() { @@ -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"]; ?>"; 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..ef4464ed3 100644 --- a/themes/compact.css +++ b/themes/compact.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 #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; } -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%; @@ -217,6 +227,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 +239,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,25 +269,18 @@ 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; @@ -287,10 +297,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 +322,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 +378,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 +391,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,13 +399,6 @@ 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 { @@ -527,11 +483,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 +491,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); @@ -559,16 +511,6 @@ body.ttrss_main #feeds-holder #feedTree { text-rendering: optimizelegibility; font-family: "Segoe UI", Ubuntu, "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 .counterNode.marked { - border-color: #257aa7; - background: #ffffff; -} body.ttrss_main #feeds-holder #feedTree .counterNode { font-weight: bold; display: none; @@ -587,6 +529,20 @@ body.ttrss_main #feeds-holder #feedTree .counterNode { min-width: 23px; height: 14px; } +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 .counterNode.marked { + border-color: #257aa7; + background: #ffffff; +} +body.ttrss_main #feeds-holder #feedTree .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; @@ -635,54 +591,146 @@ body.ttrss_main #feeds-holder #feedTree 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: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 #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; + font-style: italic; } -body.ttrss_main #headlines-frame div.feed-title { +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 #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 +738,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 +758,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 +773,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 +793,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 +831,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 +845,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 +885,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 +942,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 +983,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,6 +1022,12 @@ body.ttrss_main ul.list-unstyled { 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 #prefFilterTestResultList .preview { margin: 8px; } @@ -1013,11 +1037,39 @@ body.ttrss_main #prefFilterTestResultList .title { body.ttrss_main #prefFilterTestResultList .feed { color: #257aa7; } +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 +1110,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 +1169,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 +1182,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 +1199,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 +1231,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 +1240,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 +1272,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,10 +1315,10 @@ 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; @@ -1268,61 +1326,43 @@ div.cdm.expanded div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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 +1371,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,10 +1408,10 @@ 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; @@ -1390,32 +1419,32 @@ div.cdm.expandable div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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; } -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; @@ -1503,14 +1532,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 +1559,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 +1633,9 @@ body.ttrss_prefs .event-log tr .errstr { word-break: break-all; white-space: pre-wrap; } +body.ttrss_prefs .event-log tr .filename { + word-break: break-all; +} body.ttrss_prefs .event-log tr .filename, body.ttrss_prefs .event-log tr .login, body.ttrss_prefs .event-log tr .timestamp { @@ -1787,7 +1820,8 @@ body.ttrss_utility.share_popup .content { } .flat .dijitToolbar { font-size: 13px; - padding: 0px; + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0; } .flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner { line-height: 10px; @@ -1810,12 +1844,13 @@ body.ttrss_utility.share_popup .content { .flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel { padding: 4px 8px; font-size: 13px; + font-family: "Segoe UI", Ubuntu, "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,6 +1860,10 @@ body.ttrss_utility.share_popup .content { content: "\f00c"; color: white; } +.flat .dijitTab, +.flat .dijitAccordionTitle { + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; +} .flat .dijitTab i.material-icons, .flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons { color: #257aa7; @@ -1874,6 +1913,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 +1988,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 +2002,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..0edf5ca1c 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; } -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%; @@ -217,6 +227,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 +239,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,25 +269,18 @@ 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; @@ -287,10 +297,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 +322,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 +378,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 +391,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,13 +399,6 @@ 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 { @@ -527,11 +483,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 +491,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); @@ -559,16 +511,6 @@ body.ttrss_main #feeds-holder #feedTree { text-rendering: optimizelegibility; font-family: "Segoe UI", Ubuntu, "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 .counterNode.marked { - border-color: #b87d2c; - background: #ffffff; -} body.ttrss_main #feeds-holder #feedTree .counterNode { font-weight: bold; display: none; @@ -587,6 +529,20 @@ body.ttrss_main #feeds-holder #feedTree .counterNode { min-width: 23px; height: 14px; } +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 .counterNode.marked { + border-color: #b87d2c; + background: #ffffff; +} +body.ttrss_main #feeds-holder #feedTree .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; @@ -635,54 +591,146 @@ body.ttrss_main #feeds-holder #feedTree 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[data-is-wide-screen="true"] .hl .feed { + display: none; } -body.ttrss_main #headlines-frame div.feed-title { +body.ttrss_main #headlines-frame #headlines-spacer { + margin-left: 1px; + text-align: center; + color: #ccc; + font-size: 11px; + font-style: italic; +} +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 +738,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 +758,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 +773,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 +793,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 +831,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 +845,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 +885,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 +942,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 +983,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,6 +1022,12 @@ body.ttrss_main ul.list-unstyled { 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 #prefFilterTestResultList .preview { margin: 8px; } @@ -1013,11 +1037,39 @@ body.ttrss_main #prefFilterTestResultList .title { body.ttrss_main #prefFilterTestResultList .feed { color: #b87d2c; } +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 +1110,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 +1169,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 +1182,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 +1199,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 +1231,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 +1240,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 +1272,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,10 +1315,10 @@ 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; @@ -1268,61 +1326,43 @@ div.cdm.expanded div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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 +1371,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,10 +1408,10 @@ 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; @@ -1390,32 +1419,32 @@ div.cdm.expandable div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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; } -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; @@ -1503,14 +1532,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 +1559,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 +1633,9 @@ body.ttrss_prefs .event-log tr .errstr { word-break: break-all; white-space: pre-wrap; } +body.ttrss_prefs .event-log tr .filename { + word-break: break-all; +} body.ttrss_prefs .event-log tr .filename, body.ttrss_prefs .event-log tr .login, body.ttrss_prefs .event-log tr .timestamp { @@ -1689,7 +1722,8 @@ body.ttrss_utility fieldset > label.checkbox { } .flat .dijitToolbar { font-size: 13px; - padding: 0px; + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0; } .flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner { line-height: 10px; @@ -1712,12 +1746,13 @@ body.ttrss_utility fieldset > label.checkbox { .flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel { padding: 4px 8px; font-size: 13px; + font-family: "Segoe UI", Ubuntu, "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,6 +1762,10 @@ body.ttrss_utility fieldset > label.checkbox { content: "\f00c"; color: white; } +.flat .dijitTab, +.flat .dijitAccordionTitle { + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; +} .flat .dijitTab i.material-icons, .flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons { color: #b87d2c; @@ -1776,6 +1815,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 { @@ -1939,11 +1979,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 +1993,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; @@ -2042,6 +2086,11 @@ body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLab body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox { color: #999999; } +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 +2099,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; diff --git a/themes/light.css b/themes/light.css index 9a4ac98c0..821619446 100644 --- a/themes/light.css +++ b/themes/light.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 #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; } -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%; @@ -217,6 +227,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 +239,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,25 +269,18 @@ 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; @@ -287,10 +297,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 +322,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 +378,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 +391,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,13 +399,6 @@ 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 { @@ -527,11 +483,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 +491,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); @@ -559,16 +511,6 @@ body.ttrss_main #feeds-holder #feedTree { text-rendering: optimizelegibility; font-family: "Segoe UI", Ubuntu, "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 .counterNode.marked { - border-color: #257aa7; - background: #ffffff; -} body.ttrss_main #feeds-holder #feedTree .counterNode { font-weight: bold; display: none; @@ -587,6 +529,20 @@ body.ttrss_main #feeds-holder #feedTree .counterNode { min-width: 23px; height: 14px; } +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 .counterNode.marked { + border-color: #257aa7; + background: #ffffff; +} +body.ttrss_main #feeds-holder #feedTree .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; @@ -635,54 +591,146 @@ body.ttrss_main #feeds-holder #feedTree 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: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 #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; + font-style: italic; } -body.ttrss_main #headlines-frame div.feed-title { +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 #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 +738,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 +758,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 +773,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 +793,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 +831,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 +845,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 +885,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 +942,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 +983,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,6 +1022,12 @@ body.ttrss_main ul.list-unstyled { 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 #prefFilterTestResultList .preview { margin: 8px; } @@ -1013,11 +1037,39 @@ body.ttrss_main #prefFilterTestResultList .title { body.ttrss_main #prefFilterTestResultList .feed { color: #257aa7; } +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 +1110,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 +1169,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 +1182,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 +1199,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 +1231,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 +1240,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 +1272,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,10 +1315,10 @@ 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; @@ -1268,61 +1326,43 @@ div.cdm.expanded div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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 +1371,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,10 +1408,10 @@ 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; @@ -1390,32 +1419,32 @@ div.cdm.expandable div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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; } -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; @@ -1503,14 +1532,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 +1559,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 +1633,9 @@ body.ttrss_prefs .event-log tr .errstr { word-break: break-all; white-space: pre-wrap; } +body.ttrss_prefs .event-log tr .filename { + word-break: break-all; +} body.ttrss_prefs .event-log tr .filename, body.ttrss_prefs .event-log tr .login, body.ttrss_prefs .event-log tr .timestamp { @@ -1787,7 +1820,8 @@ body.ttrss_utility.share_popup .content { } .flat .dijitToolbar { font-size: 13px; - padding: 0px; + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0; } .flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner { line-height: 10px; @@ -1810,12 +1844,13 @@ body.ttrss_utility.share_popup .content { .flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel { padding: 4px 8px; font-size: 13px; + font-family: "Segoe UI", Ubuntu, "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,6 +1860,10 @@ body.ttrss_utility.share_popup .content { content: "\f00c"; color: white; } +.flat .dijitTab, +.flat .dijitAccordionTitle { + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; +} .flat .dijitTab i.material-icons, .flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons { color: #257aa7; @@ -1874,6 +1913,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 +1988,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 +2002,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..4bb1c6064 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-bold; + } -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-bold; + } -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-bold; + } + } -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..db86ee0c0 100644 --- a/themes/light/defines.less +++ b/themes/light/defines.less @@ -14,8 +14,20 @@ @border-default : #ddd; @default-text: #555; @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..4f2faadcb 100644 --- a/themes/light/dijit_basic.less +++ b/themes/light/dijit_basic.less @@ -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, @@ -157,6 +166,7 @@ .dijitTreeRow { overflow: hidden; -moz-user-select: none; + user-select: none; text-overflow: ellipsis; } @@ -169,10 +179,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..587adfcf6 100644 --- a/themes/light/prefs.less +++ b/themes/light/prefs.less @@ -1,7 +1,7 @@ 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; @@ -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; } } @@ -219,6 +218,10 @@ body.ttrss_prefs { white-space : pre-wrap; } + .filename { + word-break: break-all; + } + .filename, .login, .timestamp { color : @default-text; } diff --git a/themes/light/tt-rss.less b/themes/light/tt-rss.less index 36b73b4f4..c262ce9af 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; @@ -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; @@ -248,6 +248,10 @@ body.ttrss_main { display : flex; align-items : center; + img { + margin : 0 4px; + } + i.material-icons { margin-left : 2px; padding : 2px; @@ -257,61 +261,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 +324,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 +409,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 +419,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; + /*ul.compact { list-style-type : none; - padding : 0px; - - li { - display : flex; - align-items : center; - - > * { - margin : 2px; - } - } - } - - - .browseFeedList span.subscribers { - color : #808080; - } - - 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,32 +448,15 @@ 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 { @@ -564,14 +506,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 +542,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 +551,6 @@ body.ttrss_main { z-index : 5; } - #feed_browser_spinner { - vertical-align : middle; - height : 18px; - width : 18px; - } - .exception-contents { h3 { color : red; @@ -622,19 +558,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,23 +583,12 @@ 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%); - } - - .counterNode.marked { - border-color : @color-accent-marked; - background : lighten(@color-accent-marked, 60%); - } - .counterNode { font-weight : bold; display : none; - font-size : 9px; + font-size : @font-size-tiny; text-align : center; - border : 1px solid lighten(@color-accent, 5%);; + border : 1px solid lighten(@color-accent, 5%); color : white; background : lighten(@color-accent, 5%); border-radius : 4px; @@ -674,6 +600,23 @@ body.ttrss_main { margin-top : 2px; min-width : 23px; height : 14px; + + &.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%); + } + } + + // fresh + .dijitTreeRow[data-feed-id="-3"][data-is-cat="false"] .counterNode.unread { + background-color: darken(@color-checked, 15%); + border-color: darken(@color-checked, 25%); } .dijitTreeNode .loadingExpando { @@ -735,50 +678,165 @@ body.ttrss_main { font-weight : bold; color : @color-accent; } - } } - #headlines-wrap-inner { - padding : 0px; - margin : 0px; - border-width : 0px; - } + #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; - #headlines-frame[is-vfeed="0"] .header .feed { - display : none; + > * { + /* 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; + } + } + + .cdm.expanded { + .header, .content { + background : @default-bg; + border : 1px solid @border-default; + overflow : hidden; + } + + .content { + border-top-width : 0; + padding : 0 4px 4px 4px; + } + + .header[data-is-stuck] { + top : -@cdm-grid-padding; + border-bottom-width: 1px; + } + + .header { + border-bottom-width : 0; + padding : 4px; + + .icon-grid-span { + display : inline; + } + + .feed { + display : none; + } + } + + .footer { + border : 0; + padding : 4px; + + .left, .right { + white-space: nowrap; + } + + .left { + overflow: hidden; + text-overflow: ellipsis; + } + } + + .content-inner, + .intermediate { + a { + word-break: break-all; + } + } + } } #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; + } + } } - div.feed-title a.title { - color: @default-text; - font-weight: bold; + &[data-auto-catchup="true"] #headlines-spacer { + height : 100vh; } - div.feed-title a { - color: @default-text; + .dijitCheckBox { + margin-right : 4px; } - div.feed-title a:hover { - color: @color-link; + &[data-is-wide-screen="true"] { + .title { + overflow: visible; + white-space: normal; + } + + .hl .feed { + display: none; + } + } + + #headlines-spacer { + margin-left : 1px; + text-align : center; + color : @default-text; + font-size : @font-size-small; + font-style : italic; + + 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 +845,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 +861,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 +884,7 @@ body.ttrss_main { } #toolbar-headlines { - font-size : 12px; + font-size : @font-size-toolbar; background: transparent; padding-right : 4px; flex-grow : 2; @@ -840,6 +898,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 +924,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 +971,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 +986,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 +1035,6 @@ body.ttrss_main { color : #cc90cc; } - #headlines-frame .dijitCheckBox { - margin-right : 4px; - } - #feedEditDlg img.feedIcon { border : 1px solid #ccc; padding : 5px; @@ -1110,6 +1123,7 @@ body.ttrss_main { border: 1px solid @color-published; border-radius: 4px; } + #feed_current_unread { margin-left : 8px; font-weight : bold; @@ -1148,11 +1162,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,6 +1216,14 @@ body.ttrss_main { text-align : center; } + .text-right { + text-align : right; + } + + .text-left { + text-align : left; + } + #prefFilterTestResultList { .preview { margin : 8px; @@ -1212,7 +1244,6 @@ 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 +1285,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 +1339,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,7 +1364,7 @@ body.ttrss_main, body.ttrss_utility { padding : 2px; cursor : pointer; } - } + }*/ } @@ -1354,7 +1385,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..c88e89ba9 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 { 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..39a50b9fa 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; } -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%; @@ -218,6 +228,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 +240,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,25 +270,18 @@ 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; @@ -288,10 +298,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 +323,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 +379,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 +392,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,13 +400,6 @@ 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 { @@ -528,11 +484,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 +492,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); @@ -560,16 +512,6 @@ body.ttrss_main #feeds-holder #feedTree { text-rendering: optimizelegibility; font-family: "Segoe UI", Ubuntu, "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 .counterNode.marked { - border-color: #b87d2c; - background: #ffffff; -} body.ttrss_main #feeds-holder #feedTree .counterNode { font-weight: bold; display: none; @@ -588,6 +530,20 @@ body.ttrss_main #feeds-holder #feedTree .counterNode { min-width: 23px; height: 14px; } +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 .counterNode.marked { + border-color: #b87d2c; + background: #ffffff; +} +body.ttrss_main #feeds-holder #feedTree .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; @@ -636,54 +592,146 @@ body.ttrss_main #feeds-holder #feedTree 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[data-is-wide-screen="true"] .hl .feed { + display: none; } -body.ttrss_main #headlines-frame div.feed-title { +body.ttrss_main #headlines-frame #headlines-spacer { + margin-left: 1px; + text-align: center; + color: #ccc; + font-size: 11px; + font-style: italic; +} +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 +739,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 +759,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 +774,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 +794,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 +832,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 +846,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 +886,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 +943,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 +984,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,6 +1023,12 @@ body.ttrss_main ul.list-unstyled { 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 #prefFilterTestResultList .preview { margin: 8px; } @@ -1014,11 +1038,39 @@ body.ttrss_main #prefFilterTestResultList .title { body.ttrss_main #prefFilterTestResultList .feed { color: #b87d2c; } +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 +1111,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 +1170,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 +1183,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 +1200,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 +1232,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 +1241,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 +1273,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,10 +1316,10 @@ 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; @@ -1269,61 +1327,43 @@ div.cdm.expanded div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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 +1372,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,10 +1409,10 @@ 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; @@ -1391,32 +1420,32 @@ div.cdm.expandable div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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; } -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; @@ -1504,14 +1533,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 +1560,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; @@ -1604,6 +1634,9 @@ body.ttrss_prefs .event-log tr .errstr { word-break: break-all; white-space: pre-wrap; } +body.ttrss_prefs .event-log tr .filename { + word-break: break-all; +} body.ttrss_prefs .event-log tr .filename, body.ttrss_prefs .event-log tr .login, body.ttrss_prefs .event-log tr .timestamp { @@ -1690,7 +1723,8 @@ body.ttrss_utility fieldset > label.checkbox { } .flat .dijitToolbar { font-size: 13px; - padding: 0px; + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0; } .flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner { line-height: 10px; @@ -1713,12 +1747,13 @@ body.ttrss_utility fieldset > label.checkbox { .flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel { padding: 4px 8px; font-size: 13px; + font-family: "Segoe UI", Ubuntu, "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,6 +1763,10 @@ body.ttrss_utility fieldset > label.checkbox { content: "\f00c"; color: white; } +.flat .dijitTab, +.flat .dijitAccordionTitle { + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; +} .flat .dijitTab i.material-icons, .flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons { color: #b87d2c; @@ -1777,6 +1816,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 { @@ -1940,11 +1980,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 +1994,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; @@ -2043,6 +2087,11 @@ body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLab body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox { color: #999999; } +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 +2100,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; diff --git a/themes/night_base.less b/themes/night_base.less index 76ea04a7f..78056d710 100644 --- a/themes/night_base.less +++ b/themes/night_base.less @@ -9,7 +9,7 @@ @default-fg: @default-text; @border-default: #222; @default-bg : #333; - +@color-icon: #999; @border-light : #666; @default-text: #ccc; @@ -102,9 +102,9 @@ body.flat.ttrss_main { background : @color-panel-bg; } - .cdm.expanded { + /*.cdm.expanded { background: @default-bg; - } + }*/ .hl.Unread .title, .cdm.Unread .title { diff --git a/themes/night_blue.css b/themes/night_blue.css index 8a3d7f8a5..031456b01 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; } -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%; @@ -218,6 +228,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 +240,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,25 +270,18 @@ 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; @@ -288,10 +298,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 +323,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 +379,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 +392,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,13 +400,6 @@ 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 { @@ -528,11 +484,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 +492,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); @@ -560,16 +512,6 @@ body.ttrss_main #feeds-holder #feedTree { text-rendering: optimizelegibility; font-family: "Segoe UI", Ubuntu, "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 .counterNode.marked { - border-color: #257aa7; - background: #ffffff; -} body.ttrss_main #feeds-holder #feedTree .counterNode { font-weight: bold; display: none; @@ -588,6 +530,20 @@ body.ttrss_main #feeds-holder #feedTree .counterNode { min-width: 23px; height: 14px; } +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 .counterNode.marked { + border-color: #257aa7; + background: #ffffff; +} +body.ttrss_main #feeds-holder #feedTree .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; @@ -636,54 +592,146 @@ body.ttrss_main #feeds-holder #feedTree 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[data-is-wide-screen="true"] .hl .feed { + display: none; } -body.ttrss_main #headlines-frame div.feed-title { +body.ttrss_main #headlines-frame #headlines-spacer { + margin-left: 1px; + text-align: center; + color: #ccc; + font-size: 11px; + font-style: italic; +} +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 +739,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 +759,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 +774,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 +794,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 +832,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 +846,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 +886,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 +943,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 +984,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,6 +1023,12 @@ body.ttrss_main ul.list-unstyled { 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 #prefFilterTestResultList .preview { margin: 8px; } @@ -1014,11 +1038,39 @@ body.ttrss_main #prefFilterTestResultList .title { body.ttrss_main #prefFilterTestResultList .feed { color: #257aa7; } +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 +1111,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 +1170,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 +1183,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 +1200,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 +1232,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 +1241,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 +1273,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,10 +1316,10 @@ 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; @@ -1269,61 +1327,43 @@ div.cdm.expanded div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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 +1372,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,10 +1409,10 @@ 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; @@ -1391,32 +1420,32 @@ div.cdm.expandable div.header a.title { text-rendering: optimizelegibility; font-family: "Segoe WP Semibold", "Segoe UI Semibold", "Segoe UI Web Semibold", "Segoe UI", Ubuntu, "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; } -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; @@ -1504,14 +1533,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 +1560,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; @@ -1604,6 +1634,9 @@ body.ttrss_prefs .event-log tr .errstr { word-break: break-all; white-space: pre-wrap; } +body.ttrss_prefs .event-log tr .filename { + word-break: break-all; +} body.ttrss_prefs .event-log tr .filename, body.ttrss_prefs .event-log tr .login, body.ttrss_prefs .event-log tr .timestamp { @@ -1690,7 +1723,8 @@ body.ttrss_utility fieldset > label.checkbox { } .flat .dijitToolbar { font-size: 13px; - padding: 0px; + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 0; } .flat .dijitToolbar .dijitTextBox .dijitInputContainer .dijitInputInner { line-height: 10px; @@ -1713,12 +1747,13 @@ body.ttrss_utility fieldset > label.checkbox { .flat .dijitMenu .dijitMenuItem .dijitMenuItemLabel { padding: 4px 8px; font-size: 13px; + font-family: "Segoe UI", Ubuntu, "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,6 +1763,10 @@ body.ttrss_utility fieldset > label.checkbox { content: "\f00c"; color: white; } +.flat .dijitTab, +.flat .dijitAccordionTitle { + font-family: "Segoe UI", Ubuntu, "Helvetica Neue", Helvetica, Arial, sans-serif; +} .flat .dijitTab i.material-icons, .flat .dijitAccordionInnerContainer:not(.dijitSelected) i.material-icons { color: #257aa7; @@ -1777,6 +1816,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 { @@ -1940,11 +1980,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 +1994,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; @@ -2043,6 +2087,11 @@ body.flat.ttrss_main #feeds-holder #feedTree .dijitTreeRowSelected .dijitTreeLab body.flat.ttrss_main #feeds-holder #feedTree i.icon.icon-inbox { color: #999999; } +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 +2100,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; 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..."); |