diff options
| author | 2014-10-24 15:17:07 +0200 | |
|---|---|---|
| committer | 2014-10-24 15:17:07 +0200 | |
| commit | 3e2d34c8671acae33568fdeb1398afad8296d9bf (patch) | |
| tree | 6a8fa1430115d12e78855362e093dae9667008f8 | |
| parent | 5d7d01be296a23058026e0dc610b2e2077b3262c (diff) | |
| parent | 83d95ca4b894a84de467a97c7f413c1d04c43631 (diff) | |
Merge branch '634-refactor-with-context' into dev
34 files changed, 1415 insertions, 1280 deletions
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 8a9dcdc62..cafd0e8a8 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -104,7 +104,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { if (Minz_Request::isPost()) { FreshRSS_Context::$conf->_posts_per_page(Minz_Request::param('posts_per_page', 10)); FreshRSS_Context::$conf->_view_mode(Minz_Request::param('view_mode', 'normal')); - FreshRSS_Context::$conf->_default_view((int)Minz_Request::param('default_view', FreshRSS_Entry::STATE_ALL)); + FreshRSS_Context::$conf->_default_view(Minz_Request::param('default_view', 'adaptive')); FreshRSS_Context::$conf->_auto_load_more(Minz_Request::param('auto_load_more', false)); FreshRSS_Context::$conf->_display_posts(Minz_Request::param('display_posts', false)); FreshRSS_Context::$conf->_display_categories(Minz_Request::param('display_categories', false)); @@ -338,9 +338,6 @@ class FreshRSS_configure_Controller extends Minz_ActionController { unset($query[$key]); } } - if (!empty($query['state']) && $query['state'] & FreshRSS_Entry::STATE_STRICT) { - $query['state'] -= FreshRSS_Entry::STATE_STRICT; - } $queries[] = $query; FreshRSS_Context::$conf->_queries($queries); FreshRSS_Context::$conf->save(); diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index 449029648..d11f3a520 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -17,14 +17,6 @@ class FreshRSS_entry_Controller extends Minz_ActionController { ); } - // Keep parameter information (output) to do a correct redirection at - // the end. - $this->params = array(); - $output = Minz_Request::param('output', ''); - if ($output != '' && FreshRSS_Context::$conf->view_mode !== $output) { - $this->params['output'] = $output; - } - // If ajax request, we do not print layout $this->ajax = Minz_Request::param('ajax'); if ($this->ajax) { @@ -53,6 +45,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController { $get = Minz_Request::param('get'); $next_get = Minz_Request::param('nextGet', $get); $id_max = Minz_Request::param('idMax', 0); + $params = array(); $entryDAO = FreshRSS_Factory::createEntryDao(); if ($id === false) { @@ -86,7 +79,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController { // Redirect to the correct page (category, feed or starred) // Not "a" because it is the default value if nothing is // given. - $this->params['get'] = $next_get; + $params['get'] = $next_get; } } } else { @@ -98,7 +91,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController { Minz_Request::good(_t('feeds_marked_read'), array( 'c' => 'index', 'a' => 'index', - 'params' => $this->params, + 'params' => $params, ), true); } } @@ -123,7 +116,6 @@ class FreshRSS_entry_Controller extends Minz_ActionController { Minz_Request::forward(array( 'c' => 'index', 'a' => 'index', - 'params' => $this->params, ), true); } } diff --git a/app/Controllers/errorController.php b/app/Controllers/errorController.php index 76ab930e0..6c080bea8 100644 --- a/app/Controllers/errorController.php +++ b/app/Controllers/errorController.php @@ -37,7 +37,7 @@ class FreshRSS_error_Controller extends Minz_ActionController { if ($this->view->errorMessage == '') { switch($code_int) { case 403: - $this->view->errorMessage = _t('forbidden_access'); + $this->view->errorMessage = _t('access_denied'); break; case 404: default: diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index f994e257c..1cf618f7f 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -1,217 +1,220 @@ <?php +/** + * This class handles main actions of FreshRSS. + */ class FreshRSS_index_Controller extends Minz_ActionController { - private $nb_not_read_cat = 0; + /** + * This action only redirect on the default view mode (normal or global) + */ public function indexAction() { - $output = Minz_Request::param('output'); - $token = FreshRSS_Context::$conf->token; + $prefered_output = FreshRSS_Context::$conf->view_mode; + Minz_Request::forward(array( + 'c' => 'index', + 'a' => $prefered_output + )); + } - // check if user is logged in + /** + * This action displays the normal view of FreshRSS. + */ + public function normalAction() { if (!FreshRSS_Auth::hasAccess() && !Minz_Configuration::allowAnonymous()) { - $token_param = Minz_Request::param('token', ''); - $token_is_ok = ($token != '' && $token === $token_param); - if ($output === 'rss' && !$token_is_ok) { - Minz_Error::error( - 403, - array('error' => array(_t('access_denied'))) - ); - return; - } elseif ($output !== 'rss') { - // "hard" redirection is not required, just ask dispatcher to - // forward to the login form without 302 redirection - Minz_Request::forward(array('c' => 'auth', 'a' => 'login')); - return; - } + Minz_Request::forward(array('c' => 'auth', 'a' => 'login')); + return; } - $params = Minz_Request::params(); - if (isset($params['search'])) { - $params['search'] = urlencode($params['search']); + try { + $this->updateContext(); + } catch (FreshRSS_Context_Exception $e) { + Minz_Error::error(404); } - $this->view->url = array( - 'c' => 'index', - 'a' => 'index', - 'params' => $params - ); + try { + $entries = $this->listEntriesByContext(); + + $nb_entries = count($entries); + if ($nb_entries > FreshRSS_Context::$number) { + // We have more elements for pagination + $last_entry = array_pop($entries); + FreshRSS_Context::$next_id = $last_entry->id(); + } + + $first_entry = $nb_entries > 0 ? $entries[0] : null; + FreshRSS_Context::$id_max = $first_entry === null ? + (time() - 1) . '000000' : + $first_entry->id(); + if (FreshRSS_Context::$order === 'ASC') { + // In this case we do not know but we guess id_max + $id_max = (time() - 1) . '000000'; + if (strcmp($id_max, FreshRSS_Context::$id_max) > 0) { + FreshRSS_Context::$id_max = $id_max; + } + } + + $this->view->entries = $entries; + } catch (FreshRSS_EntriesGetter_Exception $e) { + Minz_Log::notice($e->getMessage()); + Minz_Error::error(404); + } + + $this->view->categories = FreshRSS_Context::$categories; - if ($output === 'rss') { - // no layout for RSS output - $this->view->_useLayout(false); - header('Content-Type: application/rss+xml; charset=utf-8'); - } elseif ($output === 'global') { - Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $title = FreshRSS_Context::$name; + if (FreshRSS_Context::$get_unread > 0) { + $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title; } + Minz_View::prependTitle($title . ' · '); + } - $catDAO = new FreshRSS_CategoryDAO(); - $entryDAO = FreshRSS_Factory::createEntryDao(); + /** + * This action displays the reader view of FreshRSS. + * + * @todo: change this view into specific CSS rules? + */ + public function readerAction() { + $this->normalAction(); + } - $this->view->cat_aside = $catDAO->listCategories(); - $this->view->nb_favorites = $entryDAO->countUnreadReadFavorites(); - $this->view->nb_not_read = FreshRSS_CategoryDAO::CountUnreads($this->view->cat_aside, 1); - $this->view->currentName = ''; - - $this->view->get_c = ''; - $this->view->get_f = ''; - - $get = Minz_Request::param('get', 'a'); - $getType = $get[0]; - $getId = substr($get, 2); - if (!$this->checkAndProcessType($getType, $getId)) { - Minz_Log::debug('Not found [' . $getType . '][' . $getId . ']'); - Minz_Error::error( - 404, - array('error' => array(_t('page_not_found'))) - ); + /** + * This action displays the global view of FreshRSS. + */ + public function globalAction() { + if (!FreshRSS_Auth::hasAccess() && !Minz_Configuration::allowAnonymous()) { + Minz_Request::forward(array('c' => 'auth', 'a' => 'login')); return; } - // mise à jour des titres - $this->view->rss_title = $this->view->currentName . ' | ' . Minz_View::title(); - Minz_View::prependTitle( - ($this->nb_not_read_cat > 0 ? '(' . formatNumber($this->nb_not_read_cat) . ') ' : '') . - $this->view->currentName . - ' · ' - ); + Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); - // On récupère les différents éléments de filtrage - $this->view->state = Minz_Request::param('state', FreshRSS_Context::$conf->default_view); - $state_param = Minz_Request::param('state', null); - $filter = Minz_Request::param('search', ''); - $this->view->order = $order = Minz_Request::param('order', FreshRSS_Context::$conf->sort_order); - $nb = Minz_Request::param('nb', FreshRSS_Context::$conf->posts_per_page); - $first = Minz_Request::param('next', ''); - - $ajax_request = Minz_Request::param('ajax', false); - if ($output === 'reader') { - $nb = max(1, round($nb / 2)); + try { + $this->updateContext(); + } catch (FreshRSS_Context_Exception $e) { + Minz_Error::error(404); } - if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ) { //Any unread article in this category at all? - switch ($getType) { - case 'a': - $hasUnread = $this->view->nb_not_read > 0; - break; - case 's': - // This is deprecated. The favorite button does not exist anymore - $hasUnread = $this->view->nb_favorites['unread'] > 0; - break; - case 'c': - $hasUnread = (!isset($this->view->cat_aside[$getId]) || - $this->view->cat_aside[$getId]->nbNotRead() > 0); - break; - case 'f': - $myFeed = FreshRSS_CategoryDAO::findFeed($this->view->cat_aside, $getId); - $hasUnread = ($myFeed === null) || ($myFeed->nbNotRead() > 0); - break; - default: - $hasUnread = true; - break; - } - if (!$hasUnread && ($state_param === null)) { - $this->view->state = FreshRSS_Entry::STATE_ALL; - } + $this->view->categories = FreshRSS_Context::$categories; + + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $title = _t('gen.title.global_view'); + if (FreshRSS_Context::$get_unread > 0) { + $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title; } + Minz_View::prependTitle($title . ' · '); + } - $this->view->today = @strtotime('today'); + /** + * This action displays the RSS feed of FreshRSS. + */ + public function rssAction() { + $token = FreshRSS_Context::$conf->token; + $token_param = Minz_Request::param('token', ''); + $token_is_ok = ($token != '' && $token === $token_param); + + // Check if user has access. + if (!FreshRSS_Auth::hasAccess() && + !Minz_Configuration::allowAnonymous() && + !$token_is_ok) { + Minz_Error::error(403); + } try { - $entries = $entryDAO->listWhere($getType, $getId, $this->view->state, $order, $nb + 1, $first, $filter); - - // Si on a récupéré aucun article "non lus" - // on essaye de récupérer tous les articles - if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ && empty($entries) && ($state_param === null) && ($filter == '')) { - Minz_Log::debug('Conflicting information about nbNotRead!'); - $feedDAO = FreshRSS_Factory::createFeedDao(); - try { - $feedDAO->updateCachedValues(); - } catch (Exception $ex) { - Minz_Log::notice('Failed to automatically correct nbNotRead! ' + $ex->getMessage()); - } - $this->view->state = FreshRSS_Entry::STATE_ALL; - $entries = $entryDAO->listWhere($getType, $getId, $this->view->state, $order, $nb, $first, $filter); - } - Minz_Request::_param('state', $this->view->state); - - if (count($entries) <= $nb) { - $this->view->nextId = ''; - } else { //We have more elements for pagination - $lastEntry = array_pop($entries); - $this->view->nextId = $lastEntry->id(); - } + $this->updateContext(); + } catch (FreshRSS_Context_Exception $e) { + Minz_Error::error(404); + } - $this->view->entries = $entries; + try { + $this->view->entries = $this->listEntriesByContext(); } catch (FreshRSS_EntriesGetter_Exception $e) { Minz_Log::notice($e->getMessage()); - Minz_Error::error( - 404, - array('error' => array(_t('page_not_found'))) - ); + Minz_Error::error(404); } + + // No layout for RSS output. + $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); + $this->view->_useLayout(false); + header('Content-Type: application/rss+xml; charset=utf-8'); } - /* - * Vérifie que la catégorie / flux sélectionné existe - * + Initialise correctement les variables de vue get_c et get_f - * + Met à jour la variable $this->nb_not_read_cat + /** + * This action updates the Context object by using request parameters. + * + * Parameters are: + * - state (default: conf->default_view) + * - search (default: empty string) + * - order (default: conf->sort_order) + * - nb (default: conf->posts_per_page) + * - next (default: empty string) */ - private function checkAndProcessType($getType, $getId) { - switch($getType) { - case 'a': - $this->view->currentName = _t('your_rss_feeds'); - $this->nb_not_read_cat = $this->view->nb_not_read; - $this->view->get_c = $getType; - return true; - case 's': - $this->view->currentName = _t('your_favorites'); - $this->nb_not_read_cat = $this->view->nb_favorites['unread']; - $this->view->get_c = $getType; - return true; - case 'c': - $cat = isset($this->view->cat_aside[$getId]) ? $this->view->cat_aside[$getId] : null; - if ($cat === null) { - $catDAO = new FreshRSS_CategoryDAO(); - $cat = $catDAO->searchById($getId); - } - if ($cat) { - $this->view->currentName = $cat->name(); - $this->nb_not_read_cat = $cat->nbNotRead(); - $this->view->get_c = $getId; - return true; - } else { - return false; - } - case 'f': - $feed = FreshRSS_CategoryDAO::findFeed($this->view->cat_aside, $getId); - if (empty($feed)) { - $feedDAO = FreshRSS_Factory::createFeedDao(); - $feed = $feedDAO->searchById($getId); - } - if ($feed) { - $this->view->currentName = $feed->name(); - $this->nb_not_read_cat = $feed->nbNotRead(); - $this->view->get_f = $getId; - $this->view->get_c = $feed->category(); - return true; - } else { - return false; - } - default: - return false; + private function updateContext() { + // Update number of read / unread variables. + $entryDAO = FreshRSS_Factory::createEntryDao(); + FreshRSS_Context::$total_starred = $entryDAO->countUnreadReadFavorites(); + FreshRSS_Context::$total_unread = FreshRSS_CategoryDAO::CountUnreads( + FreshRSS_Context::$categories, 1 + ); + + FreshRSS_Context::_get(Minz_Request::param('get', 'a')); + + FreshRSS_Context::$state = Minz_Request::param( + 'state', FreshRSS_Context::$conf->default_state + ); + $state_forced_by_user = Minz_Request::param('state', false) !== false; + if (FreshRSS_Context::$conf->default_view === 'adaptive' && + FreshRSS_Context::$get_unread <= 0 && + !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ) && + !$state_forced_by_user) { + FreshRSS_Context::$state |= FreshRSS_Entry::STATE_READ; } + + FreshRSS_Context::$search = Minz_Request::param('search', ''); + FreshRSS_Context::$order = Minz_Request::param( + 'order', FreshRSS_Context::$conf->sort_order + ); + FreshRSS_Context::$number = Minz_Request::param( + 'nb', FreshRSS_Context::$conf->posts_per_page + ); + FreshRSS_Context::$first_id = Minz_Request::param('next', ''); } - + + /** + * This method returns a list of entries based on the Context object. + */ + private function listEntriesByContext() { + $entryDAO = FreshRSS_Factory::createEntryDao(); + + $get = FreshRSS_Context::currentGet(true); + if (count($get) > 1) { + $type = $get[0]; + $id = $get[1]; + } else { + $type = $get; + $id = ''; + } + + return $entryDAO->listWhere( + $type, $id, FreshRSS_Context::$state, FreshRSS_Context::$order, + FreshRSS_Context::$number + 1, FreshRSS_Context::$first_id, + FreshRSS_Context::$search + ); + } + + /** + * This action displays the about page of FreshRSS. + */ public function aboutAction() { Minz_View::prependTitle(_t('about') . ' · '); } + /** + * This action displays logs of FreshRSS for the current user. + */ public function logsAction() { if (!FreshRSS_Auth::hasAccess()) { - Minz_Error::error( - 403, - array('error' => array(_t('access_denied'))) - ); + Minz_Error::error(403); } Minz_View::prependTitle(_t('logs') . ' · '); diff --git a/app/Exceptions/ContextException.php b/app/Exceptions/ContextException.php new file mode 100644 index 000000000..357751b7c --- /dev/null +++ b/app/Exceptions/ContextException.php @@ -0,0 +1,10 @@ +<?php + +/** + * An exception raised when a context is invalid + */ +class FreshRSS_Context_Exception extends Exception { + public function __construct($message) { + parent::__construct($message); + } +} diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 752b14e31..6114a5d1a 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -26,21 +26,15 @@ class FreshRSS extends Minz_FrontController { // Load context and configuration. FreshRSS_Context::init(); - $this->loadParamsView(); + // Init i18n. + Minz_Session::_param('language', FreshRSS_Context::$conf->language); + Minz_Translate::init(); + $this->loadStylesAndScripts(); $this->loadNotifications(); $this->loadExtensions(); } - private function loadParamsView() { - // TODO: outputs should be different actions. - $output = Minz_Request::param('output', ''); - if (($output === '') || ($output !== 'normal' && $output !== 'rss' && $output !== 'reader' && $output !== 'global')) { - $output = FreshRSS_Context::$conf->view_mode; - Minz_Request::_param('output', $output); - } - } - private function loadStylesAndScripts() { $theme = FreshRSS_Themes::load(FreshRSS_Context::$conf->theme); if ($theme) { diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php index 2f208e509..53f136513 100644 --- a/app/Models/Configuration.php +++ b/app/Models/Configuration.php @@ -14,7 +14,8 @@ class FreshRSS_Configuration { 'apiPasswordHash' => '', //CRYPT_BLOWFISH 'posts_per_page' => 20, 'view_mode' => 'normal', - 'default_view' => FreshRSS_Entry::STATE_NOT_READ, + 'default_view' => 'adaptive', + 'default_state' => FreshRSS_Entry::STATE_NOT_READ, 'auto_load_more' => true, 'display_posts' => false, 'display_categories' => false, @@ -153,18 +154,22 @@ class FreshRSS_Configuration { } public function _default_view($value) { switch ($value) { - case FreshRSS_Entry::STATE_ALL: - // left blank on purpose - case FreshRSS_Entry::STATE_NOT_READ: - // left blank on purpose - case FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ: + case 'all': $this->data['default_view'] = $value; + $this->data['default_state'] = (FreshRSS_Entry::STATE_READ + + FreshRSS_Entry::STATE_NOT_READ); break; + case 'adaptive': + case 'unread': default: - $this->data['default_view'] = FreshRSS_Entry::STATE_ALL; - break; + $this->data['default_view'] = $value; + $this->data['default_state'] = FreshRSS_Entry::STATE_NOT_READ; } } + public function _default_state($value) { + $this->data['default_state'] = (int)$value; + } + public function _display_posts($value) { $this->data['display_posts'] = ((bool)$value) && $value !== 'no'; } diff --git a/app/Models/Context.php b/app/Models/Context.php index d984fece7..36c4087eb 100644 --- a/app/Models/Context.php +++ b/app/Models/Context.php @@ -6,8 +6,39 @@ */ class FreshRSS_Context { public static $conf = null; + public static $categories = array(); + + public static $name = ''; + + public static $total_unread = 0; + public static $total_starred = array( + 'all' => 0, + 'read' => 0, + 'unread' => 0, + ); + + public static $get_unread = 0; + public static $current_get = array( + 'all' => false, + 'starred' => false, + 'feed' => false, + 'category' => false, + ); + public static $next_get = 'a'; + public static $state = 0; + public static $order = 'DESC'; + public static $number = 0; + public static $search = ''; + public static $first_id = ''; + public static $next_id = ''; + public static $id_max = ''; + /** + * Initialize the context. + * + * Set the correct $conf and $categories variables. + */ public static function init() { // Init configuration. $current_user = Minz_Session::param('currentUser'); @@ -18,15 +49,220 @@ class FreshRSS_Context { die($e->getMessage()); } - // Init i18n. - Minz_Session::_param('language', self::$conf->language); - Minz_Translate::init(); - - // Get the current state. - self::$state = self::$conf->default_view; + $catDAO = new FreshRSS_CategoryDAO(); + self::$categories = $catDAO->listCategories(); } - public static function stateEnabled($state) { + /** + * Returns if the current state includes $state parameter. + */ + public static function isStateEnabled($state) { return self::$state & $state; } + + /** + * Returns the current state with or without $state parameter. + */ + public static function getRevertState($state) { + if (self::$state & $state) { + return self::$state & ~$state; + } else { + return self::$state | $state; + } + } + + /** + * Return the current get as a string or an array. + * + * If $array is true, the first item of the returned value is 'f' or 'c' and + * the second is the id. + */ + public static function currentGet($array = false) { + if (self::$current_get['all']) { + return 'a'; + } elseif (self::$current_get['starred']) { + return 's'; + } elseif (self::$current_get['feed']) { + if ($array) { + return array('f', self::$current_get['feed']); + } else { + return 'f_' . self::$current_get['feed']; + } + } elseif (self::$current_get['category']) { + if ($array) { + return array('c', self::$current_get['category']); + } else { + return 'c_' . self::$current_get['category']; + } + } + } + + /** + * Return true if $get parameter correspond to the $current_get attribute. + */ + public static function isCurrentGet($get) { + $type = $get[0]; + $id = substr($get, 2); + + switch($type) { + case 'a': + return self::$current_get['all']; + case 's': + return self::$current_get['starred']; + case 'f': + return self::$current_get['feed'] == $id; + case 'c': + return self::$current_get['category'] == $id; + default: + return false; + } + } + + /** + * Set the current $get attribute. + * + * Valid $get parameter are: + * - a + * - s + * - f_<feed id> + * - c_<category id> + * + * $name and $get_unread attributes are also updated as $next_get + * Raise an exception if id or $get is invalid. + */ + public static function _get($get) { + $type = $get[0]; + $id = substr($get, 2); + $nb_unread = 0; + + switch($type) { + case 'a': + self::$current_get['all'] = true; + self::$name = _t('your_rss_feeds'); + self::$get_unread = self::$total_unread; + break; + case 's': + self::$current_get['starred'] = true; + self::$name = _t('your_favorites'); + self::$get_unread = self::$total_starred['unread']; + + // Update state if favorite is not yet enabled. + self::$state = self::$state | FreshRSS_Entry::STATE_FAVORITE; + break; + case 'f': + // We try to find the corresponding feed. + $feed = FreshRSS_CategoryDAO::findFeed(self::$categories, $id); + if ($feed === null) { + $feedDAO = FreshRSS_Factory::createFeedDao(); + $feed = $feedDAO->searchById($id); + + if (!$feed) { + throw new FreshRSS_Context_Exception('Invalid feed: ' . $id); + } + } + + self::$current_get['feed'] = $id; + self::$current_get['category'] = $feed->category(); + self::$name = $feed->name(); + self::$get_unread = $feed->nbNotRead(); + break; + case 'c': + // We try to find the corresponding category. + self::$current_get['category'] = $id; + if (!isset(self::$categories[$id])) { + $catDAO = new FreshRSS_CategoryDAO(); + $cat = $catDAO->searchById($id); + + if (!$cat) { + throw new FreshRSS_Context_Exception('Invalid category: ' . $id); + } + } else { + $cat = self::$categories[$id]; + } + + self::$name = $cat->name(); + self::$get_unread = $cat->nbNotRead(); + break; + default: + throw new FreshRSS_Context_Exception('Invalid getter: ' . $get); + } + + self::_nextGet(); + } + + /** + * Set the value of $next_get attribute. + */ + public static function _nextGet() { + $get = self::currentGet(); + // By default, $next_get == $get + self::$next_get = $get; + + if (self::$conf->onread_jump_next && strlen($get) > 2) { + $another_unread_id = ''; + $found_current_get = false; + switch ($get[0]) { + case 'f': + // We search the next feed with at least one unread article in + // same category as the currend feed. + foreach (self::$categories as $cat) { + if ($cat->id() != self::$current_get['category']) { + // We look into the category of the current feed! + continue; + } + + foreach ($cat->feeds() as $feed) { + if ($feed->id() == self::$current_get['feed']) { + // Here is our current feed! Fine, the next one will + // be a potential candidate. + $found_current_get = true; + continue; + } + + if ($feed->nbNotRead() > 0) { + $another_unread_id = $feed->id(); + if ($found_current_get) { + // We have found our current feed and now we + // have an feed with unread articles. Leave the + // loop! + break; + } + } + } + break; + } + + // If no feed have been found, next_get is the current category. + self::$next_get = empty($another_unread_id) ? + 'c_' . self::$current_get['category'] : + 'f_' . $another_unread_id; + break; + case 'c': + // We search the next category with at least one unread article. + foreach (self::$categories as $cat) { + if ($cat->id() == self::$current_get['category']) { + // Here is our current category! Next one could be our + // champion if it has unread articles. + $found_current_get = true; + continue; + } + + if ($cat->nbNotRead() > 0) { + $another_unread_id = $cat->id(); + if ($found_current_get) { + // Unread articles and the current category has + // already been found? Leave the loop! + break; + } + } + } + + // No unread category? The main stream will be our destination! + self::$next_get = empty($another_unread_id) ? + 'a' : + 'c_' . $another_unread_id; + break; + } + } + } } diff --git a/app/Models/Entry.php b/app/Models/Entry.php index ee94d1110..346c98a92 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -1,12 +1,11 @@ <?php class FreshRSS_Entry extends Minz_Model { - const STATE_ALL = 0; const STATE_READ = 1; const STATE_NOT_READ = 2; + const STATE_ALL = 3; const STATE_FAVORITE = 4; const STATE_NOT_FAVORITE = 8; - const STATE_STRICT = 16; private $id = 0; private $guid; diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 5a136499a..5d2909c62 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -333,8 +333,6 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { if ($state & FreshRSS_Entry::STATE_NOT_READ) { if (!($state & FreshRSS_Entry::STATE_READ)) { $where .= 'AND e1.is_read=0 '; - } elseif ($state & FreshRSS_Entry::STATE_STRICT) { - $where .= 'AND e1.is_read=0 '; } } elseif ($state & FreshRSS_Entry::STATE_READ) { diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml new file mode 100644 index 000000000..3c23e0178 --- /dev/null +++ b/app/layout/aside_feed.phtml @@ -0,0 +1,95 @@ +<?php + $class = ''; + if (FreshRSS_Context::$conf->hide_read_feeds && + FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && + !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { + $class = ' state_unread'; + } +?> + +<div class="aside aside_feed<?php echo $class; ?>" id="aside_feed"> + <a class="toggle_aside" href="#close"><?php echo _i('close'); ?></a> + + <?php if (FreshRSS_Auth::hasAccess()) { ?> + <div class="stick configure-feeds no-mobile"> + <a class="btn btn-important" href="<?php echo _url('subscription', 'index'); ?>"><?php echo _t('subscription_management'); ?></a> + <a class="btn btn-important" href="<?php echo _url('importExport', 'index'); ?>"><?php echo _i('import'); ?></a> + </div> + <?php } elseif (Minz_Configuration::needsLogin()) { ?> + <a href="<?php echo _url('index', 'about'); ?>"><?php echo _t('about_freshrss'); ?></a> + <?php } ?> + + <form id="mark-read-aside" method="post" style="display: none"></form> + + <ul class="tree"> + <li class="tree-folder category all<?php echo FreshRSS_Context::isCurrentGet('a') ? ' active' : ''; ?>"> + <div class="tree-folder-title"> + <?php echo _i('all'); ?> <a class="title" data-unread="<?php echo format_number(FreshRSS_Context::$total_unread); ?>" href="<?php echo _url('index', 'index'); ?>"><?php echo _t('main_stream'); ?></a> + </div> + </li> + + <li class="tree-folder category favorites<?php echo FreshRSS_Context::isCurrentGet('s') ? ' active' : ''; ?>"> + <div class="tree-folder-title"> + <?php echo _i('bookmark'); ?> <a class="title" data-unread="<?php echo format_number(FreshRSS_Context::$total_starred['unread']); ?>" href="<?php echo _url('index', 'index', 'get', 's'); ?>"><?php echo _t('favorite_feeds', format_number(FreshRSS_Context::$total_starred['all'])); ?></a> + </div> + </li> + + <?php + foreach ($this->categories as $cat) { + $feeds = $cat->feeds(); + if (!empty($feeds)) { + $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); + $c_show = $c_active && (!FreshRSS_Context::$conf->display_categories || + FreshRSS_Context::$current_get['feed']); + ?> + <li class="tree-folder category<?php echo $c_active ? ' active' : ''; ?>" data-unread="<?php echo $cat->nbNotRead(); ?>"> + <div class="tree-folder-title"> + <a class="dropdown-toggle" href="#"><?php echo _i($c_show ? 'up' : 'down'); ?></a> + <a class="title" data-unread="<?php echo format_number($cat->nbNotRead()); ?>" href="<?php echo _url('index', 'index', 'get', 'c_' . $cat->id()); ?>"><?php echo $cat->name(); ?></a> + </div> + + <ul class="tree-folder-items<?php echo $c_show ? ' active' : ''; ?>"> + <?php + foreach ($feeds as $feed) { + $f_active = FreshRSS_Context::isCurrentGet('f_' . $feed->id()); + ?> + <li id="f_<?php echo $feed->id(); ?>" class="item feed<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError() ? ' error' : ''; ?><?php echo $feed->nbEntries() <= 0 ? ' empty' : ''; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>" data-priority="<?php echo $feed->priority(); ?>"> + <div class="dropdown no-mobile"> + <div class="dropdown-target"></div> + <a class="dropdown-toggle" data-fweb="<?php echo $feed->website(); ?>"><?php echo _i('configure'); ?></a> + <?php /* feed_config_template */ ?> + </div> + <img class="favicon" src="<?php echo $feed->favicon(); ?>" alt="✇" /> <a class="item-title" data-unread="<?php echo format_number($feed->nbNotRead()); ?>" href="<?php echo _url('index', 'index', 'get', 'f_' . $feed->id()); ?>"><?php echo $feed->name(); ?></a> + </li> + <?php } ?> + </ul> + </li> + <?php + } + } + ?> + </ul> +</div> + +<script id="feed_config_template" type="text/html"> + <ul class="dropdown-menu"> + <li class="dropdown-close"><a href="#close">❌</a></li> + <li class="item"><a href="<?php echo _url('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo _t('filter'); ?></a></li> + <?php if (FreshRSS_Auth::hasAccess()) { ?> + <li class="item"><a href="<?php echo _url('stats', 'repartition', 'id', '!!!!!!'); ?>"><?php echo _t('stats'); ?></a></li> + <?php } ?> + <li class="item"><a target="_blank" href="http://example.net/"><?php echo _t('see_website'); ?></a></li> + <?php if (FreshRSS_Auth::hasAccess()) { ?> + <li class="separator"></li> + <li class="item"><a href="<?php echo _url('subscription', 'index', 'id', '!!!!!!'); ?>"><?php echo _t('administration'); ?></a></li> + <li class="item"><a href="<?php echo _url('feed', 'actualize', 'id', '!!!!!!'); ?>"><?php echo _t('actualize'); ?></a></li> + <li class="item"> + <?php $confirm = FreshRSS_Context::$conf->reading_confirm ? 'confirm' : ''; ?> + <button class="read_all as-link <?php echo $confirm; ?>" + form="mark-read-aside" + formaction="<?php echo _url('entry', 'read', 'get', 'f_!!!!!!'); ?>" + type="submit"><?php echo _t('mark_read'); ?></button> + </li> + <?php } ?> + </ul> +</script> diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml deleted file mode 100644 index 114ccbf56..000000000 --- a/app/layout/aside_flux.phtml +++ /dev/null @@ -1,103 +0,0 @@ -<div class="aside aside_flux<?php if (FreshRSS_Context::$conf->hide_read_feeds && ($this->state & FreshRSS_Entry::STATE_NOT_READ) && !($this->state & FreshRSS_Entry::STATE_READ)) echo ' state_unread'; ?>" id="aside_flux"> - <a class="toggle_aside" href="#close"><?php echo _i('close'); ?></a> - - <ul class="categories"> - <?php if (FreshRSS_Auth::hasAccess()) { ?> - <form id="mark-read-aside" method="post" style="display: none"></form> - - <li> - <div class="stick configure-feeds"> - <a class="btn btn-important" href="<?php echo _url('subscription', 'index'); ?>"><?php echo _t('subscription_management'); ?></a> - <a class="btn btn-important" href="<?php echo _url('importExport', 'index'); ?>"><?php echo _i('import'); ?></a> - </div> - </li> - <?php } elseif (Minz_Configuration::needsLogin()) { ?> - <li><a href="<?php echo _url('index', 'about'); ?>"><?php echo _t('about_freshrss'); ?></a></li> - <?php } ?> - - <?php - $arUrl = array('c' => 'index', 'a' => 'index', 'params' => array()); - if (FreshRSS_Context::$conf->view_mode !== Minz_Request::param('output', 'normal')) { - $arUrl['params']['output'] = 'normal'; - } - ?> - <li> - <div class="category all<?php echo $this->get_c == 'a' ? ' active' : ''; ?>"> - <a data-unread="<?php echo formatNumber($this->nb_not_read); ?>" class="btn<?php echo $this->get_c == 'a' ? ' active' : ''; ?>" href="<?php echo Minz_Url::display($arUrl); ?>"> - <?php echo _i('all'); ?> - <?php echo _t('main_stream'); ?> - </a> - </div> - </li> - - <li> - <div class="category favorites<?php echo $this->get_c == 's' ? ' active' : ''; ?>"> - <a data-unread="<?php echo formatNumber($this->nb_favorites['unread']); ?>" class="btn<?php echo $this->get_c == 's' ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 's'; echo Minz_Url::display($arUrl); ?>"> - <?php echo _i('bookmark'); ?> - <?php echo _t('favorite_feeds', formatNumber($this->nb_favorites['all'])); ?> - </a> - </div> - </li> - - <?php - foreach ($this->cat_aside as $cat) { - $feeds = $cat->feeds(); - if (!empty($feeds)) { - $c_active = false; - $c_show = false; - if ($this->get_c == $cat->id()) { - $c_active = true; - if (!FreshRSS_Context::$conf->display_categories || $this->get_f) { - $c_show = true; - } - } - ?><li data-unread="<?php echo $cat->nbNotRead(); ?>"<?php if ($c_active) echo ' class="active"'; ?>><?php - ?><div class="category stick<?php echo $c_active ? ' active' : ''; ?>"><?php - ?><a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn<?php echo $c_active ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"><?php echo $cat->name(); ?></a><?php - ?><a class="btn dropdown-toggle" href="#"><?php echo _i($c_show ? 'up' : 'down'); ?></a><?php - ?></div><?php - ?><ul class="feeds<?php echo $c_show ? ' active' : ''; ?>"><?php - foreach ($feeds as $feed) { - $feed_id = $feed->id(); - $nbEntries = $feed->nbEntries(); - $f_active = ($this->get_f == $feed_id); - ?><li id="f_<?php echo $feed_id; ?>" class="item<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError() ? ' error' : ''; ?><?php echo $nbEntries == 0 ? ' empty' : ''; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>"><?php - ?><div class="dropdown"><?php - ?><div class="dropdown-target"></div><?php - ?><a class="dropdown-toggle" data-fweb="<?php echo $feed->website(); ?>"><?php echo _i('configure'); ?></a><?php - /* feed_config_template */ - ?></div><?php - ?> <img class="favicon" src="<?php echo $feed->favicon(); ?>" alt="✇" /> <?php - ?><a class="feed" data-unread="<?php echo formatNumber($feed->nbNotRead()); ?>" data-priority="<?php echo $feed->priority(); ?>" href="<?php $arUrl['params']['get'] = 'f_' . $feed_id; echo Minz_Url::display($arUrl); ?>"><?php echo $feed->name(); ?></a><?php - ?></li><?php - } - ?></ul><?php - ?></li><?php - } - } ?> - </ul> - <span class="aside_flux_ender"><!-- For fixed menu --></span> -</div> - -<script id="feed_config_template" type="text/html"> - <ul class="dropdown-menu"> - <li class="dropdown-close"><a href="#close">❌</a></li> - <li class="item"><a href="<?php echo _url('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo _t('filter'); ?></a></li> - <?php if (FreshRSS_Auth::hasAccess()) { ?> - <li class="item"><a href="<?php echo _url('stats', 'repartition', 'id', '!!!!!!'); ?>"><?php echo _t('stats'); ?></a></li> - <?php } ?> - <li class="item"><a target="_blank" href="http://example.net/"><?php echo _t('see_website'); ?></a></li> - <?php if (FreshRSS_Auth::hasAccess()) { ?> - <li class="separator"></li> - <li class="item"><a href="<?php echo _url('subscription', 'index', 'id', '!!!!!!'); ?>"><?php echo _t('administration'); ?></a></li> - <li class="item"><a href="<?php echo _url('feed', 'actualize', 'id', '!!!!!!'); ?>"><?php echo _t('actualize'); ?></a></li> - <li class="item"> - <?php $confirm = FreshRSS_Context::$conf->reading_confirm ? 'confirm' : ''; ?> - <button class="read_all as-link <?php echo $confirm; ?>" - form="mark-read-aside" - formaction="<?php echo _url('entry', 'read', 'get', 'f_!!!!!!'); ?>" - type="submit"><?php echo _t('mark_read'); ?></button> - </li> - <?php } ?> - </ul> -</script> diff --git a/app/layout/aside_subscription.phtml b/app/layout/aside_subscription.phtml index 9a95763c3..cbf5df67d 100644 --- a/app/layout/aside_subscription.phtml +++ b/app/layout/aside_subscription.phtml @@ -1,4 +1,4 @@ -<ul class="nav nav-list aside aside_feed"> +<ul class="nav nav-list aside"> <li class="nav-header"><?php echo _t('subscription_management'); ?></li> <li class="item<?php echo Minz_Request::controllerName() == 'subscription' ? ' active' : ''; ?>"> diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index a8c70ec64..1827d6c26 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -10,21 +10,22 @@ <?php $this->renderHelper('javascript_vars'); ?> //]]></script> <?php - if (!empty($this->nextId)) { - $params = Minz_Request::params(); - $params['next'] = $this->nextId; - $params['ajax'] = 1; + $url_base = Minz_Request::currentRequest(); + if (FreshRSS_Context::$next_id !== '') { + $url_next = $url_base; + $url_next['params']['next'] = FreshRSS_Context::$next_id; + $url_next['params']['ajax'] = 1; ?> - <link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display(array('c' => Minz_Request::controllerName(), 'a' => Minz_Request::actionName(), 'params' => $params)); ?>" /> + <link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display($url_next); ?>" /> <?php } ?> <link rel="shortcut icon" id="favicon" type="image/x-icon" sizes="16x16 64x64" href="<?php echo Minz_Url::display('/favicon.ico'); ?>" /> <link rel="icon msapplication-TileImage apple-touch-icon" type="image/png" sizes="256x256" href="<?php echo Minz_Url::display('/themes/icons/favicon-256.png'); ?>" /> <?php - if (isset($this->url)) { - $rss_url = $this->url; - $rss_url['params']['output'] = 'rss'; + if (isset($this->rss_title)) { + $url_rss = $url_base; + $url_rss['a'] = 'rss'; ?> - <link rel="alternate" type="application/rss+xml" title="<?php echo $this->rss_title; ?>" href="<?php echo Minz_Url::display($rss_url); ?>" /> + <link rel="alternate" type="application/rss+xml" title="<?php echo $this->rss_title; ?>" href="<?php echo Minz_Url::display($url_rss); ?>" /> <?php } ?> <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('starred', true); ?>"> <link rel="prefetch" href="<?php echo FreshRSS_Themes::icon('non-starred', true); ?>"> diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index bb9468ab1..775daf088 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -1,90 +1,31 @@ -<?php - $actual_view = Minz_Request::param('output', 'normal'); -?> +<?php $actual_view = Minz_Request::actionName(); ?> + <div class="nav_menu"> <?php if ($actual_view === 'normal') { ?> - <a class="btn toggle_aside" href="#aside_flux"><?php echo _i('category'); ?></a> + <a class="btn toggle_aside" href="#aside_feed"><?php echo _i('category'); ?></a> <?php } ?> <?php if (FreshRSS_Auth::hasAccess()) { ?> <div id="nav_menu_actions" class="stick"> <?php - $url_state = $this->url; - - if ($this->state & FreshRSS_Entry::STATE_READ) { - $url_state['params']['state'] = $this->state & ~FreshRSS_Entry::STATE_READ; - $checked = 'true'; - $class = 'active'; - } else { - $url_state['params']['state'] = $this->state | FreshRSS_Entry::STATE_READ; - $checked = 'false'; - $class = ''; - } - ?> - <a id="toggle-read" - class="btn <?php echo $class; ?>" - aria-checked="<?php echo $checked; ?>" - href="<?php echo Minz_Url::display($url_state); ?>" - title="<?php echo _t('show_read'); ?>"> - <?php echo _i('read'); ?> - </a> - - <?php - if ($this->state & FreshRSS_Entry::STATE_NOT_READ) { - $url_state['params']['state'] = $this->state & ~FreshRSS_Entry::STATE_NOT_READ; - $checked = 'true'; - $class = 'active'; - } else { - $url_state['params']['state'] = $this->state | FreshRSS_Entry::STATE_NOT_READ; - $checked = 'false'; - $class = ''; - } - ?> - <a id="toggle-unread" - class="btn <?php echo $class; ?>" - aria-checked="<?php echo $checked; ?>" - href="<?php echo Minz_Url::display($url_state); ?>" - title="<?php echo _t('show_not_reads'); ?>"> - <?php echo _i('unread'); ?> - </a> - - <?php - if ($this->state & FreshRSS_Entry::STATE_FAVORITE || $this->get_c == 's') { - $url_state['params']['state'] = $this->state & ~FreshRSS_Entry::STATE_FAVORITE; - $checked = 'true'; - $class = 'active'; - } else { - $url_state['params']['state'] = $this->state | FreshRSS_Entry::STATE_FAVORITE; - $checked = 'false'; - $class = ''; - } - ?> - <a id="toggle-favorite" - class="btn <?php echo $class; ?>" - aria-checked="<?php echo $checked; ?>" - href="<?php echo Minz_Url::display($url_state); ?>" - title="<?php echo _t('show_favorite'); ?>"> - <?php echo _i('starred'); ?> - </a> - - <?php - if ($this->state & FreshRSS_Entry::STATE_NOT_FAVORITE) { - $url_state['params']['state'] = $this->state & ~FreshRSS_Entry::STATE_NOT_FAVORITE; - $checked = 'true'; - $class = 'active'; - } else { - $url_state['params']['state'] = $this->state | FreshRSS_Entry::STATE_NOT_FAVORITE; - $checked = 'false'; - $class = ''; - } + $states = array( + 'read' => FreshRSS_Entry::STATE_READ, + 'unread' => FreshRSS_Entry::STATE_NOT_READ, + 'starred' => FreshRSS_Entry::STATE_FAVORITE, + 'non-starred' => FreshRSS_Entry::STATE_NOT_FAVORITE, + ); + + foreach ($states as $state_str => $state) { + $state_enabled = FreshRSS_Context::isStateEnabled($state); + $url_state = Minz_Request::currentRequest(); + $url_state['params']['state'] = FreshRSS_Context::getRevertState($state); ?> - <a id="toggle-not-favorite" - class="btn <?php echo $class; ?>" - aria-checked="<?php echo $checked; ?>" - href="<?php echo Minz_Url::display($url_state); ?>" - title="<?php echo _t('show_not_favorite'); ?>"> - <?php echo _i('non-starred'); ?> - </a> + <a id="toggle-<?php echo $state_str; ?>" + class="btn <?php echo $state_enabled ? 'active' : ''; ?>" + aria-checked="<?php echo $state_enabled ? 'true' : 'false'; ?>" + title="<?php echo _t($state_str); ?>" + href="<?php echo Minz_Url::display($url_state); ?>"><?php echo _i($state_str); ?></a> + <?php } ?> <div class="dropdown"> <div id="dropdown-query" class="dropdown-target"></div> @@ -109,7 +50,7 @@ <?php } ?> <?php - $url_query = $this->url; + $url_query = Minz_Request::currentRequest();; $url_query['c'] = 'configure'; $url_query['a'] = 'addQuery'; ?> @@ -117,74 +58,25 @@ </ul> </div> </div> + <?php - $get = false; + $get = FreshRSS_Context::currentGet(); $string_mark = _t('mark_all_read'); - if ($this->get_f) { - $get = 'f_' . $this->get_f; + if ($get[0] == 'f') { $string_mark = _t('mark_feed_read'); - } elseif ($this->get_c && $this->get_c != 'a') { - if ($this->get_c === 's') { - $get = 's'; - } else { - $get = 'c_' . $this->get_c; - } + } elseif ($get[0] == 'c') { $string_mark = _t('mark_cat_read'); } - $nextGet = $get; - if (FreshRSS_Context::$conf->onread_jump_next && strlen($get) > 2) { - $anotherUnreadId = ''; - $foundCurrent = false; - switch ($get[0]) { - case 'c': - foreach ($this->cat_aside as $cat) { - if ($cat->id() == $this->get_c) { - $foundCurrent = true; - continue; - } - if ($cat->nbNotRead() <= 0) continue; - $anotherUnreadId = $cat->id(); - if ($foundCurrent) break; - } - $nextGet = empty($anotherUnreadId) ? 'a' : 'c_' . $anotherUnreadId; - break; - case 'f': - foreach ($this->cat_aside as $cat) { - if ($cat->id() == $this->get_c) { - foreach ($cat->feeds() as $feed) { - if ($feed->id() == $this->get_f) { - $foundCurrent = true; - continue; - } - if ($feed->nbNotRead() <= 0) continue; - $anotherUnreadId = $feed->id(); - if ($foundCurrent) break; - } - break; - } - } - $nextGet = empty($anotherUnreadId) ? 'c_' . $this->get_c : 'f_' . $anotherUnreadId; - break; - } - } - $p = isset($this->entries[0]) ? $this->entries[0] : null; - $idMax = $p === null ? (time() - 1) . '000000' : $p->id(); - - if ($this->order === 'ASC') { //In this case we do not know but we guess idMax - $idMax2 = (time() - 1) . '000000'; - if (strcmp($idMax2, $idMax) > 0) { - $idMax = $idMax2; - } - } - - $arUrl = array('c' => 'entry', 'a' => 'read', 'params' => array('get' => $get, 'nextGet' => $nextGet, 'idMax' => $idMax)); - $output = Minz_Request::param('output', ''); - if ($output != '' && FreshRSS_Context::$conf->view_mode !== $output) { - $arUrl['params']['output'] = $output; - } - $markReadUrl = Minz_Url::display($arUrl); - Minz_Session::_param('markReadUrl', $markReadUrl); + $mark_read_url = array( + 'c' => 'entry', + 'a' => 'read', + 'params' => array( + 'get' => $get, + 'nextGet' => FreshRSS_Context::$next_get, + 'idMax' => FreshRSS_Context::$id_max, + ) + ); ?> <form id="mark-read-menu" method="post" style="display: none"></form> @@ -193,7 +85,7 @@ <?php $confirm = FreshRSS_Context::$conf->reading_confirm ? 'confirm' : ''; ?> <button class="read_all btn <?php echo $confirm; ?>" form="mark-read-menu" - formaction="<?php echo $markReadUrl; ?>" + formaction="<?php echo Minz_Url::display($mark_read_url); ?>" type="submit"><?php echo _t('mark_read'); ?></button> <div class="dropdown"> @@ -206,15 +98,16 @@ <li class="item"> <button class="as-link <?php echo $confirm; ?>" form="mark-read-menu" - formaction="<?php echo $markReadUrl; ?>" + formaction="<?php echo Minz_Url::display($mark_read_url); ?>" type="submit"><?php echo $string_mark; ?></button> </li> <li class="separator"></li> <?php - $mark_before_today = $arUrl; - $mark_before_today['params']['idMax'] = $this->today . '000000'; - $mark_before_one_week = $arUrl; - $mark_before_one_week['params']['idMax'] = ($this->today - 604800) . '000000'; + $today = @strtotime('today'); + $mark_before_today = $mark_read_url; + $mark_before_today['params']['idMax'] = $today . '000000'; + $mark_before_one_week = $mark_read_url; + $mark_before_one_week['params']['idMax'] = ($today - 604800) . '000000'; ?> <li class="item"> <button class="as-link <?php echo $confirm; ?>" @@ -233,25 +126,25 @@ </div> <?php } ?> - <?php $url_output = $this->url; ?> + <?php $url_output = Minz_Request::currentRequest(); ?> <div class="stick" id="nav_menu_views"> - <?php $url_output['params']['output'] = 'normal'; ?> + <?php $url_output['a'] = 'normal'; ?> <a class="view_normal btn <?php echo $actual_view == 'normal'? 'active' : ''; ?>" title="<?php echo _t('normal_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>"> <?php echo _i("view-normal"); ?> </a> - <?php $url_output['params']['output'] = 'global'; ?> + <?php $url_output['a'] = 'global'; ?> <a class="view_global btn <?php echo $actual_view == 'global'? 'active' : ''; ?>" title="<?php echo _t('global_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>"> <?php echo _i("view-global"); ?> </a> - <?php $url_output['params']['output'] = 'reader'; ?> - <a class="view_reader btn <?php echo $actual_view == 'reader'? 'active' : ''; ?>" title="<?php echo _t('reader_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>"> + <?php $url_output['a'] = 'reader'; ?> + <a class="view_reader btn <?php echo $actual_view == 'reader'? 'active' : ''; ?>" title="<?php echo _t('global_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>"> <?php echo _i("view-reader"); ?> </a> <?php - $url_output['params']['output'] = 'rss'; + $url_output['a'] = 'rss'; if (FreshRSS_Context::$conf->token) { $url_output['params']['token'] = FreshRSS_Context::$conf->token; } @@ -284,7 +177,7 @@ </div> <?php - if ($this->order === 'DESC') { + if (FreshRSS_Context::$order === 'DESC') { $order = 'ASC'; $icon = 'up'; $title = 'older_first'; @@ -293,7 +186,7 @@ $icon = 'down'; $title = 'newer_first'; } - $url_order = $this->url; + $url_order = Minz_Request::currentRequest(); $url_order['params']['order'] = $order; ?> <a id="toggle-order" class="btn" href="<?php echo Minz_Url::display($url_order); ?>" title="<?php echo _t($title); ?>"> diff --git a/app/views/configure/reading.phtml b/app/views/configure/reading.phtml index ef775b4b1..b8f673466 100644 --- a/app/views/configure/reading.phtml +++ b/app/views/configure/reading.phtml @@ -39,9 +39,9 @@ <label class="group-name" for="view_mode"><?php echo _t('articles_to_display'); ?></label> <div class="group-controls"> <select name="default_view" id="default_view"> - <option value="<?php echo FreshRSS_Entry::STATE_NOT_READ; ?>"<?php echo FreshRSS_Context::$conf->default_view === FreshRSS_Entry::STATE_NOT_READ ? ' selected="selected"' : ''; ?>><?php echo _t('show_adaptive'); ?></option> - <option value="<?php echo FreshRSS_Entry::STATE_ALL; ?>"<?php echo FreshRSS_Context::$conf->default_view === FreshRSS_Entry::STATE_ALL ? ' selected="selected"' : ''; ?>><?php echo _t('show_all_articles'); ?></option> - <option value="<?php echo FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ; ?>"<?php echo FreshRSS_Context::$conf->default_view === FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ ? ' selected="selected"' : ''; ?>><?php echo _t('show_not_reads'); ?></option> + <option value="adaptive"<?php echo FreshRSS_Context::$conf->default_view === 'adaptive' ? ' selected="selected"' : ''; ?>><?php echo _t('show_adaptive'); ?></option> + <option value="all"<?php echo FreshRSS_Context::$conf->default_view === 'all' ? ' selected="selected"' : ''; ?>><?php echo _t('show_all_articles'); ?></option> + <option value="unread"<?php echo FreshRSS_Context::$conf->default_view === 'unread' ? ' selected="selected"' : ''; ?>><?php echo _t('show_not_reads'); ?></option> </select> </div> </div> diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml index d642443a8..3ea6c3582 100755 --- a/app/views/helpers/pagination.phtml +++ b/app/views/helpers/pagination.phtml @@ -1,28 +1,32 @@ <?php - $c = Minz_Request::controllerName(); - $a = Minz_Request::actionName(); - $params = Minz_Request::params(); - $markReadUrl = Minz_Session::param('markReadUrl'); - Minz_Session::_param('markReadUrl', false); + $url_next = Minz_Request::currentRequest(); + $url_next['params']['next'] = FreshRSS_Context::$next_id; + $url_next['params']['ajax'] = 1; + + $url_mark_read = array( + 'c' => 'entry', + 'a' => 'read', + 'params' => array( + 'get' => FreshRSS_Context::currentGet(), + 'nextGet' => FreshRSS_Context::$next_get, + 'idMax' => FreshRSS_Context::$id_max, + ) + ); ?> <form id="mark-read-pagination" method="post" style="display: none"></form> <ul class="pagination"> <li class="item pager-next"> - <?php if (!empty($this->nextId)) { ?> - <?php - $params['next'] = $this->nextId; - $params['ajax'] = 1; - ?> - <a id="load_more" href="<?php echo Minz_Url::display(array('c' => $c, 'a' => $a, 'params' => $params)); ?>"> + <?php if (FreshRSS_Context::$next_id) { ?> + <a id="load_more" href="<?php echo Minz_Url::display($url_next); ?>"> <?php echo _t('load_more'); ?> </a> - <?php } elseif ($markReadUrl) { ?> + <?php } elseif ($url_mark_read) { ?> <button id="bigMarkAsRead" class="as-link <?php echo FreshRSS_Context::$conf->reading_confirm ? 'confirm' : ''; ?>" form="mark-read-pagination" - formaction="<?php echo $markReadUrl; ?>" + formaction="<?php echo Minz_Url::display($url_mark_read); ?>" type="submit"> <?php echo _t('nothing_to_load'); ?><br /> <span class="bigTick">✓</span><br /> diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml deleted file mode 100644 index ae8af820d..000000000 --- a/app/views/helpers/view/global_view.phtml +++ /dev/null @@ -1,53 +0,0 @@ -<?php $this->partial('nav_menu'); ?> - -<?php if (!empty($this->entries)) { ?> -<div id="stream" class="global categories"> -<?php - $arUrl = array('c' => 'index', 'a' => 'index', 'params' => array()); - if (FreshRSS_Context::$conf->view_mode !== 'normal') { - $arUrl['params']['output'] = 'normal'; - } - $p = Minz_Request::param('state', ''); - if (($p != '') && (FreshRSS_Context::$conf->default_view !== $p)) { - $arUrl['params']['state'] = $p; - } - - foreach ($this->cat_aside as $cat) { - $feeds = $cat->feeds(); - if (!empty($feeds)) { -?> - <div class="box-category"> - <div class="category"> - <a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"> - <?php echo $cat->name(); ?> - </a> - </div> - <ul class="feeds"> - <?php foreach ($feeds as $feed) { ?> - <?php $not_read = $feed->nbNotRead(); ?> - <li id="f_<?php echo $feed->id(); ?>" class="item<?php echo $feed->inError() ? ' error' : ''; ?><?php echo $feed->nbEntries() == 0 ? ' empty' : ''; ?>"> - <img class="favicon" src="<?php echo $feed->favicon(); ?>" alt="✇" /> - <a class="feed" data-unread="<?php echo formatNumber($feed->nbNotRead()); ?>" data-priority="<?php echo $feed->priority(); ?>" href="<?php $arUrl['params']['get'] = 'f_' . $feed->id(); echo Minz_Url::display($arUrl); ?>"> - <?php echo $feed->name(); ?> - </a> - </li> - <?php } ?> - </ul> - </div> -<?php - } - } -?> -</div> - -<div id="overlay"></div> -<div id="panel"<?php echo FreshRSS_Context::$conf->display_posts ? '' : ' class="hide_posts"'; ?>> - <a class="close" href="#"><?php echo _i('close'); ?></a> -</div> - -<?php } else { ?> -<div id="stream" class="prompt alert alert-warn global"> - <h2><?php echo _t('no_feed_to_display'); ?></h2> - <a href="<?php echo _url('subscription', 'index'); ?>"><?php echo _t('think_to_add'); ?></a><br /><br /> -</div> -<?php } ?> diff --git a/app/views/index/global.phtml b/app/views/index/global.phtml new file mode 100644 index 000000000..0975a5a00 --- /dev/null +++ b/app/views/index/global.phtml @@ -0,0 +1,53 @@ +<?php + $this->partial('nav_menu'); + + $class = ''; + if (FreshRSS_Context::$conf->hide_read_feeds && + FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && + !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { + $class = ' state_unread'; + } +?> + +<div id="stream" class="global<?php echo $class; ?>"> +<?php + $url_base = array( + 'c' => 'index', + 'a' => 'index', + 'params' => Minz_Request::params() + ); + + foreach ($this->categories as $cat) { + $feeds = $cat->feeds(); + $url_base['params']['get'] = 'c_' . $cat->id(); + + if (!empty($feeds)) { +?> + <div class="box category" data-unread="<?php echo $cat->nbNotRead(); ?>"> + <div class="box-title"><a class="title" data-unread="<?php echo format_number($cat->nbNotRead()); ?>" href="<?php echo Minz_Url::display($url_base); ?>"><?php echo $cat->name(); ?></a></div> + + <ul class="box-content"> + <?php + foreach ($feeds as $feed) { + $nb_not_read = $feed->nbNotRead(); + $error = $feed->inError() ? ' error' : ''; + $empty = $feed->nbEntries() === 0 ? ' empty' : ''; + $url_base['params']['get'] = 'f_' . $feed->id(); + ?> + <li id="f_<?php echo $feed->id(); ?>" class="item feed<?php echo $error, $empty; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>" data-priority="<?php echo $feed->priority(); ?>"> + <img class="favicon" src="<?php echo $feed->favicon(); ?>" alt="✇" /> + <a class="item-title" data-unread="<?php echo format_number($feed->nbNotRead()); ?>" href="<?php echo Minz_Url::display($url_base); ?>"><?php echo $feed->name(); ?></a> + </li> + <?php } ?> + </ul> + </div> +<?php + } + } +?> +</div> + +<div id="overlay"></div> +<div id="panel"<?php echo FreshRSS_Context::$conf->display_posts ? '' : ' class="hide_posts"'; ?>> + <a class="close" href="#"><?php echo _i('close'); ?></a> +</div> diff --git a/app/views/index/index.phtml b/app/views/index/index.phtml index a59063557..8b93461dd 100644 --- a/app/views/index/index.phtml +++ b/app/views/index/index.phtml @@ -7,8 +7,6 @@ if (FreshRSS_Auth::hasAccess() || Minz_Configuration::allowAnonymous()) { $this->renderHelper('view/normal_view'); } elseif ($output === 'reader') { $this->renderHelper('view/reader_view'); - } elseif ($output === 'global') { - $this->renderHelper('view/global_view'); } elseif ($output === 'rss') { $this->renderHelper('view/rss_view'); } else { diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/index/normal.phtml index afe8ed872..02d621bd0 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/index/normal.phtml @@ -1,6 +1,6 @@ <?php -$this->partial('aside_flux'); +$this->partial('aside_feed'); $this->partial('nav_menu'); if (!empty($this->entries)) { @@ -26,33 +26,35 @@ if (!empty($this->entries)) { $bottomline_link = FreshRSS_Context::$conf->bottomline_link; $content_width = FreshRSS_Context::$conf->content_width; + + $today = @strtotime('today'); ?> <div id="stream" class="normal<?php echo $hidePosts ? ' hide_posts' : ''; ?>"><?php ?><div id="new-article"> - <a href="<?php echo Minz_Url::display($this->url); ?>"><?php echo _t('new_article'); ?></a> + <a href="<?php echo Minz_Url::display(Minz_Request::currentRequest()); ?>"><?php echo _t('new_article'); ?></a> </div><?php foreach ($this->entries as $item) { - if ($display_today && $item->isDay(FreshRSS_Days::TODAY, $this->today)) { + if ($display_today && $item->isDay(FreshRSS_Days::TODAY, $today)) { ?><div class="day" id="day_today"><?php echo _t('today'); ?><span class="date"> — <?php echo timestamptodate(time(), false); ?></span><?php - ?><span class="name"><?php echo $this->currentName; ?></span><?php + ?><span class="name"><?php echo FreshRSS_Context::$name; ?></span><?php ?></div><?php $display_today = false; } - if ($display_yesterday && $item->isDay(FreshRSS_Days::YESTERDAY, $this->today)) { + if ($display_yesterday && $item->isDay(FreshRSS_Days::YESTERDAY, $today)) { ?><div class="day" id="day_yesterday"><?php echo _t('yesterday'); ?><span class="date"> — <?php echo timestamptodate(time() - 86400, false); ?></span><?php - ?><span class="name"><?php echo $this->currentName; ?></span><?php + ?><span class="name"><?php echo FreshRSS_Context::$name; ?></span><?php ?></div><?php $display_yesterday = false; } - if ($display_others && $item->isDay(FreshRSS_Days::BEFORE_YESTERDAY, $this->today)) { + if ($display_others && $item->isDay(FreshRSS_Days::BEFORE_YESTERDAY, $today)) { ?><div class="day" id="day_before_yesterday"><?php echo _t('before_yesterday'); - ?><span class="name"><?php echo $this->currentName; ?></span><?php + ?><span class="name"><?php echo FreshRSS_Context::$name; ?></span><?php ?></div><?php $display_others = false; } @@ -80,7 +82,7 @@ if (!empty($this->entries)) { ?></li><?php } } - $feed = FreshRSS_CategoryDAO::findFeed($this->cat_aside, $item->feed()); //We most likely already have the feed object in cache + $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $item->feed()); //We most likely already have the feed object in cache if ($feed == null) { $feed = $item->feed(true); if ($feed == null) { diff --git a/app/views/helpers/view/reader_view.phtml b/app/views/index/reader.phtml index 821a50f7f..f07868488 100644 --- a/app/views/helpers/view/reader_view.phtml +++ b/app/views/index/reader.phtml @@ -13,7 +13,7 @@ if (!empty($this->entries)) { <div class="flux_content"> <div class="content <?php echo $content_width; ?>"> <?php - $feed = FreshRSS_CategoryDAO::findFeed($this->cat_aside, $item->feed()); //We most likely already have the feed object in cache + $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $item->feed()); //We most likely already have the feed object in cache if (empty($feed)) $feed = $item->feed(true); ?> <a href="<?php echo $item->link(); ?>"> diff --git a/app/views/helpers/view/rss_view.phtml b/app/views/index/rss.phtml index e34b15ab1..e34b15ab1 100755 --- a/app/views/helpers/view/rss_view.phtml +++ b/app/views/index/rss.phtml diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index f7a24c026..4b97a3caf 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -45,6 +45,13 @@ class Minz_Request { public static function defaultActionName() { return self::$default_action_name; } + public static function currentRequest() { + return array( + 'c' => self::$controller_name, + 'a' => self::$action_name, + 'params' => self::$params, + ); + } /** * Setteurs diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 9abdf18ce..80eb206d2 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -60,6 +60,10 @@ function formatNumber($n, $precision = 0) { return str_replace(' ', ' ', //Espace insécable //TODO: remplacer par une espace _fine_ insécable number_format($n, $precision, '.', ' ')); //number_format does not seem to be Unicode-compatible } +function format_number($n, $precision = 0) { + // TODO: coding style, prefer THIS function. Remove formatNumber. + return formatNumber($n, $precision); +} function formatBytes($bytes, $precision = 2, $system = 'IEC') { if ($system === 'IEC') { diff --git a/p/scripts/global_view.js b/p/scripts/global_view.js index 6e1f61066..14909f44e 100644 --- a/p/scripts/global_view.js +++ b/p/scripts/global_view.js @@ -9,7 +9,7 @@ function load_panel(link) { panel_loading = true; $.get(link, function (data) { - $("#panel").append($(".nav_menu, #stream .day, #stream .flux, #stream .pagination", data)); + $("#panel").append($(".nav_menu, #stream .day, #stream .flux, #stream .pagination, #stream.prompt", data)); $("#panel .nav_menu").children().not("#nav_menu_read_all").remove(); @@ -50,7 +50,8 @@ function init_close_panel() { } function init_global_view() { - $("#stream .box-category a").click(function () { + // TODO: should be based on generic classes. + $(".box a").click(function () { var link = $(this).attr("href"); load_panel(link); diff --git a/p/scripts/main.js b/p/scripts/main.js index 1e13ff16a..b6370866f 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -56,31 +56,31 @@ function incLabel(p, inc, spaceAfter) { function incUnreadsFeed(article, feed_id, nb) { //Update unread: feed - var elem = $('#' + feed_id + '>.feed').get(0), + var elem = $('#' + feed_id).get(0), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0, feed_priority = elem ? str2int(elem.getAttribute('data-priority')) : 0; if (elem) { - elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); - elem = $(elem).closest('li').get(0); + elem.setAttribute('data-unread', feed_unreads + nb); + elem = $(elem).children('.item-title').get(0); if (elem) { - elem.setAttribute('data-unread', feed_unreads + nb); + elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); } } //Update unread: category - elem = $('#' + feed_id).parent().prevAll('.category').children(':first').get(0); + elem = $('#' + feed_id).parents('.category').get(0); feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if (elem) { - elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); - elem = $(elem).closest('li').get(0); + elem.setAttribute('data-unread', feed_unreads + nb); + elem = $(elem).find('.title').get(0); if (elem) { - elem.setAttribute('data-unread', feed_unreads + nb); + elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); } } //Update unread: all if (feed_priority > 0) { - elem = $('#aside_flux .all').children(':first').get(0); + elem = $('#aside_feed .all .title').get(0); if (elem) { feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); @@ -89,7 +89,7 @@ function incUnreadsFeed(article, feed_id, nb) { //Update unread: favourites if (article && article.closest('div').hasClass('favorite')) { - elem = $('#aside_flux .favorites').children(':first').get(0); + elem = $('#aside_feed .favorites .title').get(0); if (elem) { feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); @@ -97,7 +97,7 @@ function incUnreadsFeed(article, feed_id, nb) { } var isCurrentView = false; - //Update unread: title + // Update unread: title document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)/, function (m, p1) { var $feed = $('#' + feed_id); if (article || ($feed.closest('.active').length > 0 && $feed.siblings('.active').length === 0)) { @@ -194,7 +194,7 @@ function mark_favorite(active) { } $b.find('.icon').replaceWith(data.icon); - var favourites = $('.favorites>a').contents().last().get(0); + var favourites = $('#aside_feed .favorites .title').contents().last().get(0); if (favourites && favourites.textContent) { favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) { return incLabel(p1, inc, false); @@ -202,7 +202,7 @@ function mark_favorite(active) { } if (active.closest('div').hasClass('not_read')) { - var elem = $('#aside_flux .favorites').children(':first').get(0), + var elem = $('#aside_feed .favorites .title').get(0), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if (elem) { elem.setAttribute('data-unread', numberFormat(feed_unreads + inc)); @@ -292,42 +292,42 @@ function next_entry() { } function prev_feed() { - var active_feed = $("#aside_flux .feeds li.active"); + var active_feed = $("#aside_feed .tree-folder-items .item.active"); if (active_feed.length > 0) { - active_feed.prevAll(':visible:first').find('a.feed').each(function(){this.click();}); + active_feed.prevAll(':visible:first').find('a').each(function(){this.click();}); } else { last_feed(); } } function next_feed() { - var active_feed = $("#aside_flux .feeds li.active"); + var active_feed = $("#aside_feed .tree-folder-items .item.active"); if (active_feed.length > 0) { - active_feed.nextAll(':visible:first').find('a.feed').each(function(){this.click();}); + active_feed.nextAll(':visible:first').find('a').each(function(){this.click();}); } else { first_feed(); } } function first_feed() { - var feed = $("#aside_flux .feeds.active li:visible:first"); + var feed = $("#aside_feed .tree-folder-items.active .item:visible:first"); if (feed.length > 0) { feed.find('a')[1].click(); } } function last_feed() { - var feed = $("#aside_flux .feeds.active li:visible:last"); + var feed = $("#aside_feed .tree-folder-items.active .item:visible:last"); if (feed.length > 0) { feed.find('a')[1].click(); } } function prev_category() { - var active_cat = $("#aside_flux .category.stick.active"); + var active_cat = $("#aside_feed .tree-folder.active"); if (active_cat.length > 0) { - var prev_cat = active_cat.parent('li').prevAll(':visible:first').find('.category.stick a.btn'); + var prev_cat = active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); if (prev_cat.length > 0) { prev_cat[0].click(); } @@ -338,10 +338,10 @@ function prev_category() { } function next_category() { - var active_cat = $("#aside_flux .category.stick.active"); + var active_cat = $("#aside_feed .tree-folder.active"); if (active_cat.length > 0) { - var next_cat = active_cat.parent('li').nextAll(':visible:first').find('.category.stick a.btn'); + var next_cat = active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); if (next_cat.length > 0) { next_cat[0].click(); } @@ -352,16 +352,16 @@ function next_category() { } function first_category() { - var cat = $("#aside_flux .category.stick:visible:first"); + var cat = $("#aside_feed .tree-folder:visible:first"); if (cat.length > 0) { - cat.find('a.btn')[0].click(); + cat.find('.tree-folder-title .title')[0].click(); } } function last_category() { - var cat = $("#aside_flux .category.stick:visible:last"); + var cat = $("#aside_feed .tree-folder:visible:last"); if (cat.length > 0) { - cat.find('a.btn')[0].click(); + cat.find('.tree-folder-title .title')[0].click(); } } @@ -487,7 +487,8 @@ function init_column_categories() { if (context['current_view'] !== 'normal') { return; } - $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () { + + $('#aside_feed').on('click', '.tree-folder>.tree-folder-title>a.dropdown-toggle', function () { $(this).children().each(function() { if (this.alt === '▽') { this.src = this.src.replace('/icons/down.', '/icons/up.'); @@ -497,12 +498,12 @@ function init_column_categories() { this.alt = '▽'; } }); - $(this).parent().next(".feeds").slideToggle(); + $(this).parent().next(".tree-folder-items").slideToggle(); return false; }); - $('#aside_flux').on('click', '.feeds .dropdown-toggle', function () { + $('#aside_feed').on('click', '.tree-folder-items .item .dropdown-toggle', function () { if ($(this).nextAll('.dropdown-menu').length === 0) { - var feed_id = $(this).closest('li').attr('id').substr(2), + var feed_id = $(this).closest('.item').attr('id').substr(2), feed_web = $(this).data('fweb'), template = $('#feed_config_template').html().replace(/!!!!!!/g, feed_id).replace('http://example.net/', feed_web); $(this).attr('href', '#dropdown-' + feed_id).prev('.dropdown-target').attr('id', 'dropdown-' + feed_id).parent().append(template); @@ -875,12 +876,12 @@ function init_notifs_html5() { function refreshUnreads() { $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) { - var isAll = $('.category.all > .active').length > 0, + var isAll = $('.category.all.active').length > 0, new_articles = false; $.each(data, function(feed_id, nbUnreads) { feed_id = 'f_' + feed_id; - var elem = $('#' + feed_id + '>.feed').get(0), + var elem = $('#' + feed_id).get(0), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view? @@ -890,7 +891,7 @@ function refreshUnreads() { }; }); - var nb_unreads = str2int($('.category.all>a').attr('data-unread')); + var nb_unreads = str2int($('.category.all .title').attr('data-unread')); if (nb_unreads > 0 && new_articles) { faviconNbUnread(nb_unreads); @@ -1135,7 +1136,7 @@ function init_password_observers() { function faviconNbUnread(n) { if (typeof n === 'undefined') { - n = str2int($('.category.all>a').attr('data-unread')); + n = str2int($('.category.all .title').attr('data-unread')); } //http://remysharp.com/2010/08/24/dynamic-favicons/ var canvas = document.createElement('canvas'), diff --git a/p/themes/Dark/dark.css b/p/themes/Dark/dark.css index f3790614e..e551aa9c0 100644 --- a/p/themes/Dark/dark.css +++ b/p/themes/Dark/dark.css @@ -464,6 +464,48 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + padding: 0 10px; + line-height: 2.5rem; + font-size: 1rem; + background: #1c1c1c; + font-weight: bold; +} +.tree-folder-title .title { + background: inherit; + color: #888; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + background: #2c2c2c; +} +.tree-folder-items { + border-top: 1px solid #222; + border-bottom: 1px solid #222; + background: #161616; +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { + background: #1c1c1c; +} +.tree-folder-items > .item > a { + text-decoration: none; +} +.tree-folder-items > .item.active > a { + color: #888; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -500,81 +542,60 @@ a.btn { border-right: 1px solid #333; background: #1c1c1c; } -.aside.aside_flux { - padding: 10px 0 50px; - border-right: 1px solid #333; - background: #1c1c1c; -} - -/*=== Aside main page (categories) */ -.categories { +.aside.aside_feed { + padding: 10px 0; text-align: center; } -.category { - width: 235px; - margin: 10px auto; - text-align: left; -} -.category .btn:first-child { - position: relative; - width: 213px; -} -.category.stick .btn:first-child { - width: 176px; +.aside.aside_feed .tree { + position: sticky; + top: 0; + margin: 10px 0 50px; } -.category .btn:first-child:not([data-unread="0"]):after { + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"]):after { position: absolute; - top: 3px; right: 3px; - padding: 1px 5px; - background: #111; - color: #888; - border: 1px solid #000; - border-radius: 5px; + right: 0; + margin: 10px 0; + padding: 0 10px; + font-size: 0.9rem; + line-height: 1.5rem; + background: inherit; + border-left: 1px solid #666; } /*=== Aside main page (feeds) */ -.categories .feeds .item.active { - background: #333; +.feed.item.empty.active { + background: #c95; } -.categories .feeds .item.active .feed { - color: #888; +.feed.item.error.active { + background: #a44; } -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { color: #c95; } -.categories .feeds .item.empty.active { - background: #c95; -} -.categories .feeds .item.error .feed { +.feed.item.error, +.feed.item.error > a { color: #a44; } -.categories .feeds .item.error.active { - background: #a44; +.feed.item.empty.active, +.feed.item.empty.active > a { + color: #111; } -.categories .feeds .item.empty.active .feed, -.categories .feeds .item.error.active .feed { +.feed.item.error.active, +.feed.item.error.active > a { color: #fff; } -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; -} -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; -} -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; vertical-align: middle; background-color: #111; - border-radius: 3px; } /*=== Configuration pages */ @@ -825,46 +846,34 @@ a.btn { /*=== GLOBAL VIEW */ /*================*/ -#stream.global .box-category { - text-align: left; - background: #1a1a1a; - border: 1px solid #000; - border-radius: 5px; +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; text-align: left; + color: #888; } -#stream.global .category { - margin: 0; +.box.category:not([data-unread="0"]) .box-title { + background: #34495E; } -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; - line-height: 2em; - font-size: 1.2rem; +.box.category:not([data-unread="0"]) .box-title:active { background: #26303F; - border: none; - border-bottom: 1px solid #000; - border-radius: 5px 5px 0 0; } -#stream.global .btn:not([data-unread="0"]) { - font-weight: bold; - background: #34495e; +.box.category:not([data-unread="0"]) .box-title .title { color: #fff; -} -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; right: 5px; font-weight: bold; +} +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; border: 0; background: none; - color: #fff; -} -#stream.global .box-category .feeds { - max-height: 250px; + font-weight: bold; + box-shadow: none; + text-shadow: none; } -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; + font-size: 0.8rem; } /*=== Panel */ @@ -963,17 +972,20 @@ a.btn { } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 30px; - height: 30px; - line-height: 30px; + width: 100%; + height: 50px; + line-height: 50px; text-align: center; background: #111; - border-left: 1px solid #333; border-bottom: 1px solid #333; - border-radius: 0 0 0 5px; + } + + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; } .nav_menu .btn { diff --git a/p/themes/Flat/flat.css b/p/themes/Flat/flat.css index e2151b1f9..eb7737c5d 100644 --- a/p/themes/Flat/flat.css +++ b/p/themes/Flat/flat.css @@ -473,6 +473,44 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + padding: 0 10px; + background: #34495e; + line-height: 2.5rem; + font-size: 1rem; + font-weight: bold; +} +.tree-folder-title .title { + background: inherit; + color: #fff; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + background: #2980b9; +} +.tree-folder-items { + background: #2c3e50; +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { + background: #2980b9; +} +.tree-folder-items > .item > a { + text-decoration: none; + color: #fff; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -508,77 +546,58 @@ a.btn { .aside { background: #ecf0f1; } -.aside.aside_flux { - padding: 10px 0 50px; - background: #ecf0f1; -} - -/*=== Aside main page (categories) */ -.categories { +.aside.aside_feed { + padding: 10px 0; text-align: center; + background: #34495e; + border-radius: 0 10px 0 0; } -.category { - width: 233px; - margin: 10px auto; - text-align: left; -} -.category .btn:first-child { - position: relative; - width: 212px; -} -.category.stick .btn:first-child { - width: 175px; +.aside.aside_feed .tree { + position: sticky; + top: 0; + margin: 10px 0 50px; } -.category .btn:first-child:not([data-unread="0"]):after { + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"]):after { position: absolute; - top: 5px; right: 5px; - padding: 1px 5px; - background: #3498DB; - color: #fff; - border-radius: 5px; + right: 0; + margin: 10px 0; + padding: 0 10px; + font-size: 0.9rem; + line-height: 1.5rem; + background: inherit; } /*=== Aside main page (feeds) */ -.categories .feeds .item.active { - background: #2980b9; -} -.categories .feeds .item.empty.active { +.feed.item.empty.active { background: #f39c12; } -.categories .feeds .item.error.active { +.feed.item.error.active { background: #bd362f; } -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { color: #e67e22; } -.categories .feeds .item.error .feed { +.feed.item.error, +.feed.item.error > a { color: #bd362f; } -.categories .feeds .item.active .feed, -.categories .feeds .item.empty.active .feed, -.categories .feeds .item.error.active .feed { +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { color: #fff; } -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; -} -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; -} -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { - vertical-align: middle; - background-color: #95a5a6; +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { border-radius: 3px; + vertical-align: middle; } /*=== Configuration pages */ @@ -833,44 +852,33 @@ a.btn { /*=== GLOBAL VIEW */ /*================*/ -#stream.global .box-category { +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; text-align: left; - border: 1px solid #ddd; - border-radius: 5px; } -#stream.global .category { - margin: 0; +.box.category:not([data-unread="0"]) .box-title { + background: #3498db; } -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; - line-height: 2em; - font-size: 1.2rem; - background: #ecf0f1; - color: #333; - border-bottom: 1px solid #ddd; - border-radius: 5px 5px 0 0; +.box.category:not([data-unread="0"]) .box-title:active { + background: #2980b9; } -#stream.global .btn:not([data-unread="0"]) { +.box.category:not([data-unread="0"]) .box-title .title { font-weight: bold; - background: #3498db; color: #fff; } -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; right: 5px; - font-weight: bold; - background: none; +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; border: 0; - color: #fff; -} -#stream.global .box-category .feeds { - max-height: 250px; + background: none; + font-weight: bold; + box-shadow: none; + text-shadow: none; } -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; + font-size: 0.8rem; } /*=== DIVERS */ @@ -961,15 +969,19 @@ a.btn { } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 32px; - height: 32px; - line-height: 30px; + width: 100%; + height: 50px; + line-height: 50px; text-align: center; - background: #34495e; - border-radius: 0 0 0 5px; + background: #2c3e50; + } + + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; } .nav_menu .btn { diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index b25deab0c..464422a0b 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -498,6 +498,51 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + padding: 0 10px; + background: #fff; + line-height: 2.5rem; + font-size: 1rem; + font-weight: bold; +} +.tree-folder-title .title { + background: inherit; + color: #444; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + background: #f0f0f0; +} +.tree-folder.active .tree-folder-title .title { + color: #0062BE; +} +.tree-folder-items { + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #f6f6f6; +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { + background: #0062be; +} +.tree-folder-items > .item > a { + text-decoration: none; +} +.tree-folder-items > .item.active > a { + color: #fff; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -536,76 +581,56 @@ a.btn { border-right: 1px solid #aaa; background: #fff; } -.aside.aside_flux { - padding: 10px 0 50px; -} - -/*=== Aside main page (categories) */ -.categories { +.aside.aside_feed { + padding: 10px 0; text-align: center; + background: #fff; } -.category { - width: 235px; - margin: 10px auto; - text-align: left; -} -.category .btn:first-child { - position: relative; - width: 213px; -} -.category.stick .btn:first-child { - width: 176px; +.aside.aside_feed .tree { + position: sticky; + top: 0; + margin: 10px 0 50px; } -.category .btn:first-child:not([data-unread="0"]):after { + +/*=== Aside main page (categories) */ +.aside_feed .category .title:not([data-unread="0"]):after { position: absolute; - top: 3px; right: 3px; - padding: 1px 5px; - background: #ccc; - color: #fff; - border: 1px solid #bbb; - border-radius: 5px; - box-shadow: 1px 3px 3px #aaa inset; - text-shadow: 0 0 1px #aaa; + right: 0; + margin: 10px 0; + padding: 0 10px; + font-size: 0.9rem; + line-height: 1.5rem; + background: inherit; + border-left: 1px solid #aaa; } /*=== Aside main page (feeds) */ -.categories .feeds .item.active { - background: #0062BE; -} -.categories .feeds .item.empty.active { +.feed.item.empty.active { background: #e67e22; } -.categories .feeds .item.error.active { - background: #BD362F; +.feed.item.error.active { + background: #bd362f; } -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { color: #e67e22; } -.categories .feeds .item.error .feed { - color: #BD362F; +.feed.item.error, +.feed.item.error > a { + color: #bd362f; } -.categories .feeds .item.active .feed, -.categories .feeds .item.empty.active .feed, -.categories .feeds .item.error.active .feed { +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { color: #fff; } -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; -} -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; -} -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { background-color: #fff; border-radius: 3px; vertical-align: middle; @@ -873,35 +898,24 @@ a.btn { /*=== GLOBAL VIEW */ /*================*/ -#stream.global .box-category { - background: #fff; - border-radius: 5px; +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; text-align: left; - box-shadow: 0 0 3px #bbb; } -#stream.global .category { - margin: 0; +.box.category:not([data-unread="0"]) .box-title { + background: #0084CC; } -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; - background: #f6f6f6; - border: none; - border-bottom: 1px solid #ddd; - border-radius: 5px 5px 0 0; - line-height: 2em; - font-size: 1.2rem; +.box.category:not([data-unread="0"]) .box-title:active { + background: #3498db; } -#stream.global .btn:not([data-unread="0"]) { - background: #0084CC; +.box.category:not([data-unread="0"]) .box-title .title { color: #fff; font-weight: bold; - text-shadow: none; } -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; right: 5px; +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; border: 0; background: none; color: #fff; @@ -909,12 +923,9 @@ a.btn { box-shadow: none; text-shadow: none; } -#stream.global .box-category .feeds { - max-height: 250px; -} -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; + font-size: 0.8rem; } /*=== DIVERS */ @@ -1008,17 +1019,20 @@ a.btn { } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 30px; - height: 30px; - line-height: 30px; + width: 100%; + height: 50px; + line-height: 50px; text-align: center; background: #f6f6f6; - border-left: 1px solid #ddd; border-bottom: 1px solid #ddd; - border-radius: 0 0 0 5px; + } + + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; } .nav_menu .btn { diff --git a/p/themes/Pafat/pafat.css b/p/themes/Pafat/pafat.css index 28b17e15f..49cb3bc17 100644 --- a/p/themes/Pafat/pafat.css +++ b/p/themes/Pafat/pafat.css @@ -192,48 +192,12 @@ a.btn { text-decoration: none; } - -.category.stick .btn { - background:#5bc0de; - color : #FFF; - border-color :#5bc0de; -} - -.category.stick .btn:first-child:hover, .category.stick .btn:last-child:hover, .category.stick .btn.active:first-child, .category.stick.active .btn:last-child { - background:#39b3d7; - border-color : #39b3d7; -} - - .btn.active, .btn:active, .dropdown-target:target ~ .btn.dropdown-toggle { background: #eee; } -.category.all > .btn { - background: #428bca; - color : #FFF; - border-color : #428bca; -} - -.category.all > .btn:hover { - background: #3276b1; - border-color : #3276b1; -} - -.category.favorites > .btn { - background:#f0ad4e; - border-color: #f0ad4e; - color : #fff; -} - -.category.favorites > .btn:hover { - background: #ed9c28; - border-color : #ed9c28; - color : white; -} - .btn-important { background: #5cb85c; color: #fff; @@ -520,6 +484,51 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + margin: 5px; + padding: 0 10px; + line-height: 2rem; + font-size: 0.9rem; + background: #5bc0de; + color: #fff; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + border-radius: 5px; +} +.tree-folder-title .title { + background: inherit; + color: #fff; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + background: #39b3d7; + font-weight: bold; + font-size: 1rem; + border-top: 1px solid #666; + border-bottom: 1px solid #666; +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { + background: #5cb85c; +} +.tree-folder-items > .item > a { + text-decoration: none; +} +.tree-folder-items > .item.active > a { + color: #fff; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -572,75 +581,69 @@ a.btn { border-right: 1px solid #aaa; background: #fff; } -.aside.aside_flux { - padding: 10px 0 50px; +.aside.aside_feed { + padding: 10px 0; + text-align: center; +} +.aside.aside_feed .tree { + position: sticky; + top: 5px; + margin: 10px 0 50px; } /*=== Aside main page (categories) */ -.categories { - text-align: center; +.aside_feed .tree-folder-title > .title:not([data-unread="0"]):after { + position: absolute; + top: 0.25rem; right: 3px; + padding: 0px 5px; + border: 1px solid #fff; + border-radius: 3px; + font-size: 0.8rem; + line-height: 1.5rem; } -.category { - width: 215px; - margin: 10px auto; - text-align: left; +.aside_feed .tree-folder.all .tree-folder-title { + background: #428bca; } -.category .btn:first-child { - position: relative; - width: 203px; +.aside_feed .tree-folder.all.active .tree-folder-title { + background: #3276b1; } -.category.stick .btn:first-child { - width: 176px; +.aside_feed .tree-folder.favorites .tree-folder-title { + background: #f0ad4e; } -.category .btn:first-child:not([data-unread="0"]):after { - position: absolute; - top: 2px; right: 3px; - padding: 0px 3px; - border: 1px solid ; - border-radius: 3px; - font-size:10pt; - line-height : 20px; +.aside_feed .tree-folder.favorites.active .tree-folder-title { + background: #ed9c28; } /*=== Aside main page (feeds) */ -.categories .feeds .item.active { - background: #5cb85c; +.feed.item.empty.active { + background: #e67e22; } -.categories .feeds .item.active .feed { - color: #fff; +.feed.item.error.active { + background: #bd362f; } -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { color: #e67e22; } -.categories .feeds .item.empty.active { - background: #e67e22; +.feed.item.error, +.feed.item.error > a { + color: #bd362f; } -.categories .feeds .item.empty.active .feed { +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { color: #fff; } -.categories .feeds .item.error .feed { - color: #BD362F; -} -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; -} -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; -} -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { - background-color: #fff; +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { border-radius: 3px; vertical-align: middle; + background-color: #fff; } /*=== Configuration pages */ @@ -906,63 +909,32 @@ a.btn { /*=== GLOBAL VIEW */ /*================*/ -#stream.global .box-category { - background: #fff; - border:none; +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; text-align: left; } - -#stream.global .category { - margin: 0; +.box.category:not([data-unread="0"]) .box-title { + background: #5BC0DE; } - -#stream.global .category:first-child { - margin: 0; -} - - -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; - background: #f6f6f6; - border-bottom: 1px solid #aaa; - border-radius: 5px 5px 0 0; - line-height: 2em; - font-size: 1.2rem; -} - -#stream.global .btn:not([data-unread="0"]) { - background: #5bc0de; - border-color : #5bc0de; - color: #fff; +.box.category:not([data-unread="0"]) .box-title .title { font-weight: bold; - text-shadow: none; - + color: #fff; } - - -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; right: 5px; +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; border: 0; background: none; - color: #fff; font-weight: bold; box-shadow: none; text-shadow: none; + font-size: 0.8rem; + line-height: 1.6rem; } - -#stream.global .box-category .feeds { - max-height: 250px; - width: 302px; - border : solid #aaa 1px; - border-top : none; -} - -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; + font-size: 0.8rem; } /*=== DIVERS */ @@ -1056,17 +1028,20 @@ a.btn { } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 30px; - height: 30px; - line-height: 30px; + width: 100%; + height: 40px; + line-height: 40px; text-align: center; background: #f6f6f6; - border-left: 1px solid #ddd; border-bottom: 1px solid #ddd; - border-radius: 0 0 0 5px; + } + + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; } .nav_menu .btn { diff --git a/p/themes/Screwdriver/screwdriver.css b/p/themes/Screwdriver/screwdriver.css index 6206504d1..4f55d752e 100644 --- a/p/themes/Screwdriver/screwdriver.css +++ b/p/themes/Screwdriver/screwdriver.css @@ -531,6 +531,54 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.9rem; +} +.tree-folder-title .title { + background: inherit; + color: #fff; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + background: linear-gradient(180deg, #222 0%, #171717 100%) #171717; + background: -webkit-linear-gradient(top, #222 0%, #171717 100%); + box-shadow: 0px 1px #171717, 0px 1px rgba(255, 255, 255, 0.08) inset; + text-shadow: 0 0 2px rgba(255,255,255,0.28); + color: #fff; +} +.tree-folder-items { + background: #171717; + padding: 8px 0; + box-shadow: 0 4px 4px #171717 inset, 0 1px rgba(255,255,255,0.08),0 -1px rgba(255,255,255,0.08); +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { + background: linear-gradient(180deg, #222 0%, #171717 100%) #171717; + background: -webkit-linear-gradient(top, #222 0%, #171717 100%); + border-radius: 4px; + margin: 0px 8px; + box-shadow: 0px 1px #171717, 0px 1px rgba(255, 255, 255, 0.08) inset, 0 2px 2px #111; +} +.tree-folder-items > .item > a { + text-decoration: none; + color: #fff; +} +.tree-folder-items > .item.active > a { +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -569,7 +617,7 @@ a.btn { /*=== Body */ #global { background:#EDE7DE; - height: calc(100% - 85px); + height: calc(100% - 60px); } .aside { border-radius: 0px 12px 0px 0px; @@ -578,103 +626,43 @@ a.btn { background: #222; width: 235px; } -.aside.aside_flux { - padding: 10px 0 50px; - background: #222; -} - -/*=== Aside main page (categories) */ -.categories { +.aside.aside_feed { + padding: 10px 0; text-align: center; } -.categories .btn-important { - border: none; -} -.category { - width: 235px; - margin: 10px auto 0; - text-align: left; -} -#aside_flux ul.feeds{ - box-shadow: 0 4px 4px #171717 inset, 0 1px rgba(255,255,255,0.08),0 -1px rgba(255,255,255,0.08); -} -ul.feeds{ - background:#171717; - padding:8px 0; - box-shadow: 0 4px 4px #EDE7DE inset; -} -ul.feeds.active{ - box-shadow: 0 0 0 #171717 inset, 0 -2px 2px #111 inset,0 1px rgba(255,255,255,0.08),0 -1px rgba(255,255,255,0); -} -.category.stick.active{ - background: linear-gradient(180deg, #222 0%, #171717 100%) #171717; - background: -webkit-linear-gradient(top, #222 0%, #171717 100%); - box-shadow: 0px 1px #171717, 0px 1px rgba(255, 255, 255, 0.08) inset; -} -.category .btn { - color: #fff; - border: none; - background: transparent; -} -.category .btn:first-child { - position: relative; - width: 213px; - background: transparent; -} -.category.stick .btn:first-child { - width: 176px; +.aside.aside_feed .tree { + position: sticky; + top: 0; + margin: 10px 0 50px; } -.category .btn:first-child:not([data-unread="0"]):after { + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"]):after { position: absolute; - top: 3px; right: 3px; + right: 3px; padding: 1px 5px; - background: transparent; color: #fff; text-shadow: 0 1px rgba(255,255,255,0.08); } +.aside_feed .btn-important { + border: none; +} /*=== Aside main page (feeds) */ -.categories .feeds .item.active { - background: linear-gradient(180deg, #222 0%, #171717 100%) #171717; - background: -webkit-linear-gradient(top, #222 0%, #171717 100%); - border-radius: 4px; - margin: 0px 8px; - box-shadow: 0px 1px #171717, 0px 1px rgba(255, 255, 255, 0.08) inset, 0 2px 2px #111; -} -.categories .feeds .item.active .feed { - color: #fff; -} -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { color: #e67e22; } -.categories .feeds .item.empty.active { - background: #e67e22; -} -.categories .feeds .item.empty.active .feed { - color: #fff; -} -.categories .feeds .item.error .feed { +.feed.item.error, +.feed.item.error > a { color: #BD362F; } -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; - color:#ccc; -} -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; -} -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { - background-color: transparent; +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { border-radius: 3px; vertical-align: middle; } @@ -968,63 +956,50 @@ opacity: 1; /*=== GLOBAL VIEW */ /*================*/ -#stream.global{ - background:#222; +#stream.global { + background: #222; padding: 24px 0; box-shadow: 0 1px #fff, 0 -2px 2px #171717 inset, 0 2px 2px #171717 inset; } -#stream.global .box-category { - background: #fff; - border-radius: 4px 4px 0 0; - text-align: left; - box-shadow: 0 0 4px #171717; - overflow:hidden; -} -#stream.global .category { - margin: 0; -} -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; + +.box.category .box-title { background: linear-gradient(0deg, #EDE7DE 0%, #fff 100%) #171717; background: -webkit-linear-gradient(bottom, #EDE7DE 0%, #fff 100%); - border: none; box-shadow: 0px -1px #fff inset,0 -2px #ccc inset; border-radius: none; line-height: 2em; font-size: 1.2rem; - color:#888; text-shadow:0 1px #ccc; } -#stream.global .btn:not([data-unread="0"]) { +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; + text-align: left; + color: #888; +} +.box.category:not([data-unread="0"]) .box-title { +} +.box.category:not([data-unread="0"]) .box-title:active { +} +.box.category:not([data-unread="0"]) .box-title .title { color: #222; font-weight: bold; } -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; - right: 5px; +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; border: 0; background: none; - color: #222; font-weight: bold; - box-shadow: none; - text-shadow: none; } -#stream.global .box-category .feeds { - max-height: 250px; - color:#222; - background:#EDE7DE; -} -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; - overflow:hidden; + font-size: 0.8rem; } -#stream.global .box-category .feed { - color:#222; +.box.category .item.feed:not(.empty):not(.error) .item-title { + color: #222; } + /*=== PANEL */ /*===========*/ #panel { @@ -1135,12 +1110,10 @@ opacity: 1; } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 30px; - height: 30px; - line-height: 30px; + width: 100%; + height: 40px; + line-height: 40px; text-align: center; background: #171717; box-shadow: 0 1px rgba(255,255,255,0.08); @@ -1151,6 +1124,13 @@ opacity: 1; margin: 20px 0 0; } + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; + } + .nav_menu .btn { margin: 5px 10px; } diff --git a/p/themes/base-theme/base.css b/p/themes/base-theme/base.css index 3f6ae956d..871a632d8 100644 --- a/p/themes/base-theme/base.css +++ b/p/themes/base-theme/base.css @@ -353,6 +353,42 @@ a.btn { visibility: visible; } +/*=== Tree */ +.tree { + margin: 10px 0; +} +.tree-folder-title { + position: relative; + padding: 0 10px; + line-height: 2.5rem; + font-size: 1rem; +} +.tree-folder-title .title { + background: inherit; +} +.tree-folder-title .title:hover { + text-decoration: none; +} +.tree-folder.active .tree-folder-title { + font-weight: bold; +} +.tree-folder.active .tree-folder-title .title { +} +.tree-folder-items { +} +.tree-folder-items > .item { + padding: 0 10px; + line-height: 2.5rem; + font-size: 0.8rem; +} +.tree-folder-items > .item.active { +} +.tree-folder-items > .item > a { + text-decoration: none; +} +.tree-folder-items > .item.active > a { +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -386,64 +422,49 @@ a.btn { } .aside { } -.aside.aside_flux { - padding: 10px 0 50px; -} - -/*=== Aside main page (categories) */ -.categories { +.aside.aside_feed { + padding: 10px 0; text-align: center; } -.category { - width: 235px; - margin: 10px auto; - text-align: left; -} -.category .btn:first-child { - position: relative; - width: 213px; -} -.category.stick .btn:first-child { - width: 176px; +.aside.aside_feed .tree { + position: sticky; + top: 0; + margin: 10px 0 50px; } -.category .btn:first-child:not([data-unread="0"]):after { + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"]):after { position: absolute; - top: 3px; right: 3px; - padding: 1px 5px; + right: 0; + margin: 10px 0; + padding: 0 10px; + font-size: 0.9rem; + line-height: 1.5rem; } /*=== Aside main page (feeds) */ -.categories .feeds .item.active { -} -.categories .feeds .item.empty.active { +.feed.item.empty.active { } -.categories .feeds .item.error.active { +.feed.item.error.active { } -.categories .feeds .item.empty .feed { +.feed.item.empty, +.feed.item.empty > a { } -.categories .feeds .item.error .feed { -} -.categories .feeds .item.active .feed, -.categories .feeds .item.empty.active .feed, -.categories .feeds .item.error.active .feed { -} -.categories .feeds .item .feed { - margin: 0; - width: 165px; - line-height: 3em; - font-size: 0.8em; - text-align: left; - text-decoration: none; +.feed.item.error, +.feed.item.error > a { } -.categories .feeds .feed:not([data-unread="0"]) { - font-weight: bold; +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { } -.categories .feeds .dropdown-menu:after { +.aside_feed .tree-folder-items .dropdown-menu:after { left: 2px; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; vertical-align: middle; } @@ -645,33 +666,30 @@ a.btn { /*=== GLOBAL VIEW */ /*================*/ -#stream.global .box-category { +.box.category .box-title .title { + font-weight: normal; + text-decoration: none; text-align: left; } -#stream.global .category { - margin: 0; +.box.category:not([data-unread="0"]) .box-title { } -#stream.global .btn { - width: auto; - height: 2em; - margin: 0; - padding: 0 10px; - line-height: 2em; - font-size: 1.2rem; +.box.category:not([data-unread="0"]) .box-title:active { } -#stream.global .btn:not([data-unread="0"]) { +.box.category:not([data-unread="0"]) .box-title .title { font-weight: bold; } -#stream.global .btn:first-child:not([data-unread="0"]):after { - top: 0; right: 5px; +.box.category .title:not([data-unread="0"]):after { + position: absolute; + top: 5px; right: 10px; + border: 0; + background: none; font-weight: bold; + box-shadow: none; + text-shadow: none; } -#stream.global .box-category .feeds { - max-height: 250px; -} -#stream.global .box-category .feeds .item { +.box.category .item.feed { padding: 2px 10px; - font-size: 0.9rem; + font-size: 0.8rem; } /*=== DIVERS */ @@ -750,15 +768,20 @@ a.btn { } .aside .toggle_aside, #panel .close { - position: absolute; display: block; - top: 0; right: 0; - width: 30px; - height: 30px; - line-height: 30px; + width: 100%; + height: 50px; + line-height: 50px; text-align: center; } + .aside.aside_feed { + padding: 0; + } + .aside.aside_feed .tree { + position: static; + } + .nav_menu .btn { margin: 5px 10px; } diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 1a96f1e2f..a79d539d8 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -179,6 +179,7 @@ a.btn { .dropdown { position: relative; display: inline-block; + vertical-align: middle; } .dropdown-target { display: none; @@ -289,10 +290,14 @@ a.btn { vertical-align: top; } .box .box-title { + position: relative; font-size: 1.2rem; font-weight: bold; text-align: center; } +.box .box-title a { + display: block; +} .box .box-title form { margin: 0; } @@ -325,6 +330,39 @@ a.btn { cursor: grab; } +/*=== Tree */ +.tree { + margin: 0; + padding: 0; + list-style: none; + text-align: left; +} +.tree-folder-items { + padding: 0; + list-style: none; +} +.tree-folder-title { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.tree-folder-title .title { + vertical-align: middle; +} +.tree-folder-items > .item { + display: block; + white-space: nowrap; +} +.tree-folder-items > .item > a { + display: inline-block; + vertical-align: middle; + width: calc(100% - 32px); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ @@ -366,57 +404,21 @@ a.btn { width: 250px; vertical-align: top; } -.aside.aside_flux { - background: #fff; -} - -/*=== Aside main page (categories) */ -.categories { - list-style: none; - margin: 0; -} -.state_unread li:not(.active)[data-unread="0"] { - display: none; -} -.category { - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -.category .btn:not([data-unread="0"]):after { - content: attr(data-unread); -} /*=== Aside main page (feeds) */ -.categories .feeds { - width: 100%; - list-style: none; -} -.categories .feeds:not(.active) { +.aside_feed .tree-folder-items:not(.active) { display: none; } -.categories .feeds .feed { - display: inline-block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - vertical-align: middle; -} -.categories .feeds .feed:not([data-unread="0"]):before { - content: "(" attr(data-unread) ") "; -} -.categories .feeds .dropdown-menu { +.aside_feed .tree-folder-items .dropdown-menu { left: 0; } -.categories .feeds .item .dropdown-toggle > .icon { +.aside_feed .tree-folder-items .item .dropdown-toggle > .icon { visibility: hidden; cursor: pointer; - vertical-align: top; } -.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon, -.categories .feeds .item:hover .dropdown-toggle > .icon, -.categories .feeds .item.active .dropdown-toggle > .icon { +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { visibility: visible; } @@ -603,32 +605,13 @@ br + br + br { /*=== GLOBAL VIEW */ /*================*/ -/*=== Category boxes */ - -/* TODO <delete> */ -#stream.global .box-category { - display: inline-block; - width: 19em; - max-width: 95%; - margin: 20px 10px; - border: 1px solid #ccc; - vertical-align: top; -} -#stream.global .category { - width: 100%; -} -#stream.global .btn { - display: block; -} -#stream.global .box-category .feeds { - display: block; - overflow: auto; +#stream.global { + text-align: center; } -#stream.global .box-category .feed { - width: 19em; - max-width: 90%; + +#stream.global .box { + text-align: left; } -/* TODO </delete */ /*=== Panel */ #overlay { @@ -685,39 +668,45 @@ br + br + br { /*=== DIVERS */ /*===========*/ +.category .title:not([data-unread="0"]):after { + content: attr(data-unread); +} +.feed .item-title:not([data-unread="0"]):before { + content: "(" attr(data-unread) ") "; +} +.feed .item-title:not([data-unread="0"]) { + font-weight: bold; +} + +.state_unread .category:not(.active)[data-unread="0"], +.state_unread .feed:not(.active)[data-unread="0"] { + display: none; +} + .nav-login, .nav_menu .search, +.aside .toggle_aside, .nav_menu .toggle_aside { display: none; } -.aside .toggle_aside { - position: absolute; - right: 0; - display: none; - width: 30px; - height: 30px; - line-height: 30px; - text-align: center; -} /*=== MOBILE */ /*===========*/ @media(max-width: 840px) { .header, .aside .btn-important, - .aside .feeds .dropdown, .flux_header .item.website span, .item.date, .day .date, .dropdown-menu > .no-mobile, .no-mobile { display: none; } + .aside .toggle_aside, .nav-login { display: block; } .nav_menu .toggle_aside, - .aside .toggle_aside, .nav_menu .search, #panel .close img { display: inline-block; @@ -735,9 +724,6 @@ br + br + br { width: 90%; overflow: auto; } - .aside .categories { - margin: 10px 0 75px; - } .flux_header .item.website { width: 40px; @@ -759,10 +745,6 @@ br + br + br { width: 100%; } - #stream.global .box-category { - margin: 10px 0; - } - #panel { top: 0; bottom: 0; left: 0; right: 0; |
