aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Marien Fressinaud <dev@marienfressinaud.fr> 2013-03-12 23:24:52 +0100
committerGravatar Marien Fressinaud <dev@marienfressinaud.fr> 2013-03-12 23:24:52 +0100
commitc62ec2a14428b528e20896d4e62fa08891e1399c (patch)
treecdf6cbbd2d1b9182d385db36ec0c86b08bcf442e
parent8c562972062fbf3d750bd62893de248022850c23 (diff)
Grosse mise à jour du design, pas mal de trucs cassés au niveau du panneau de configuration
-rwxr-xr-xapp/controllers/indexController.php77
-rw-r--r--app/layout/aside.phtml76
-rw-r--r--app/layout/configure_aside.phtml3
-rw-r--r--app/layout/header.phtml28
-rw-r--r--app/layout/layout.phtml6
-rwxr-xr-xapp/models/Category.php42
-rwxr-xr-xapp/models/Entry.php120
-rw-r--r--app/models/Feed.php56
-rw-r--r--app/views/configure/feed.phtml8
-rw-r--r--app/views/index/index.phtml6
-rw-r--r--public/theme/base.css280
-rw-r--r--public/theme/icons/all.svg32
-rw-r--r--public/theme/icons/close.svg28
-rw-r--r--public/theme/icons/configure.svg31
-rw-r--r--public/theme/icons/non-starred.svg (renamed from public/theme/non-starred.svg)0
-rw-r--r--public/theme/icons/read.svg (renamed from public/theme/read.svg)0
-rw-r--r--public/theme/icons/refresh.svg (renamed from public/theme/refresh.svg)0
-rw-r--r--public/theme/icons/search.svg32
-rw-r--r--public/theme/icons/starred.svg (renamed from public/theme/starred.svg)0
-rw-r--r--public/theme/icons/unread.svg (renamed from public/theme/unread.svg)0
-rw-r--r--public/theme/icons/website.svg (renamed from public/theme/website.svg)0
-rw-r--r--public/theme/read_mode.pngbin3543 -> 0 bytes
22 files changed, 515 insertions, 310 deletions
diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php
index bd5f31b08..916f77c98 100755
--- a/app/controllers/indexController.php
+++ b/app/controllers/indexController.php
@@ -5,15 +5,16 @@ class indexController extends ActionController {
View::appendScript (Url::display ('/scripts/smoothscroll.js'));
View::appendScript (Url::display ('/scripts/shortcut.js'));
View::appendScript (Url::display (array ('c' => 'javascript', 'a' => 'main')));
-
+
$entryDAO = new EntryDAO ();
+ $feedDAO = new FeedDAO ();
$catDAO = new CategoryDAO ();
-
+
// pour optimiser
$page = Request::param ('page', 1);
$entryDAO->_nbItemsPerPage ($this->view->conf->postsPerPage ());
$entryDAO->_currentPage ($page);
-
+
$default_view = $this->view->conf->defaultView ();
$mode = Session::param ('mode');
if ($mode == false) {
@@ -23,67 +24,87 @@ class indexController extends ActionController {
$mode = $default_view;
}
}
-
+
$get = Request::param ('get');
$order = $this->view->conf->sortOrder ();
-
+
+ $error = false;
+
// Récupère les flux par catégorie, favoris ou tous
if ($get == 'favoris') {
$entries = $entryDAO->listFavorites ($mode, $order);
View::prependTitle ('Vos favoris - ');
} elseif ($get != false) {
- $entries = $entryDAO->listByCategory ($get, $mode, $order);
- $cat = $catDAO->searchById ($get);
-
- if ($cat) {
- View::prependTitle ($cat->name () . ' - ');
+ $typeGet = $get[0];
+ $get = substr ($get, 2);
+
+ if ($typeGet == 'c') {
+ $entries = $entryDAO->listByCategory ($get, $mode, $order);
+ $cat = $catDAO->searchById ($get);
+
+ if ($cat) {
+ View::prependTitle ($cat->name () . ' - ');
+ } else {
+ $error = true;
+ }
+ } elseif ($typeGet == 'f') {
+ $entries = $entryDAO->listByFeed ($get, $mode, $order);
+ $feed = $feedDAO->searchById ($get);
+
+ if ($feed) {
+ View::prependTitle ($feed->name () . ' - ');
+ } else {
+ $error = true;
+ }
} else {
- Error::error (
- 404,
- array ('error' => array ('La page que vous cherchez n\'existe pas'))
- );
+ $error = true;
}
} else {
View::prependTitle ('Vos flux RSS - ');
}
+
$this->view->get = $get;
$this->view->mode = $mode;
-
+
// Cas où on ne choisie ni catégorie ni les favoris
// ou si la catégorie ne correspond à aucune
if (!isset ($entries)) {
$entries = $entryDAO->listEntries ($mode, $order);
}
-
+
try {
$this->view->entryPaginator = $entryDAO->getPaginator ($entries);
} catch (CurrentPagePaginationException $e) {
+ $error = true;
+ }
+
+ $this->view->cat_aside = $catDAO->listCategories ();
+ $this->view->nb_favorites = $entryDAO->countFavorites ();
+ $this->view->nb_total = $entryDAO->count ();
+
+ if ($error) {
Error::error (
404,
array ('error' => array ('La page que vous cherchez n\'existe pas'))
);
}
-
- $this->view->cat_aside = $catDAO->listCategories ();
- $this->view->nb_favorites = $entryDAO->countFavorites ();
- $this->view->nb_total = $entryDAO->count ();
}
-
+
public function changeModeAction () {
$mode = Request::param ('mode');
-
+
if ($mode == 'not_read') {
Session::_param ('mode', 'not_read');
} else {
Session::_param ('mode', 'all');
}
-
+
Request::forward (array (), true);
}
-
+
public function loginAction () {
$this->view->_useLayout (false);
-
+
$url = 'https://verifier.login.persona.org/verify';
$assert = Request::param ('assertion');
$params = 'assertion=' . $assert . '&audience=' .
@@ -98,7 +119,7 @@ class indexController extends ActionController {
curl_setopt_array ($ch, $options);
$result = curl_exec ($ch);
curl_close ($ch);
-
+
$res = json_decode ($result, true);
if ($res['status'] == 'okay' && $res['email'] == $this->view->conf->mailLogin ()) {
Session::_param ('mail', $res['email']);
@@ -107,10 +128,10 @@ class indexController extends ActionController {
$res['status'] = 'failure';
$res['reason'] = 'L\'identifiant est invalide';
}
-
+
$this->view->res = json_encode ($res);
}
-
+
public function logoutAction () {
$this->view->_useLayout (false);
Session::_param ('mail');
diff --git a/app/layout/aside.phtml b/app/layout/aside.phtml
index 1432c10ca..f1f14cfc0 100644
--- a/app/layout/aside.phtml
+++ b/app/layout/aside.phtml
@@ -1,50 +1,44 @@
-<div id="main_aside" class="aside">
- <?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
- <form id="add_rss" method="post" action="<?php echo Url::display (array ('c' => 'feed', 'a' => 'add')); ?>">
- <input type="url" name="url_rss" placeholder="Ajouter un flux RSS" /><!--
- --><input type="submit" value="+" />
- </form>
- <?php } ?>
-
- <ul id="menu">
- <li <?php echo Request::controllerName () == 'index' ? 'class="active"' : ''; ?>>
- <a href="<?php echo Url::display (array ()); ?>">Flux RSS</a>
- </li>
-
- <?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
- <li <?php echo Request::controllerName () == 'configure' ? 'class="active"' : ''; ?>>
- <a href="<?php echo Url::display (array ('c' => 'configure', 'a' => 'display')); ?>">Configurer</a>
- </li>
- <?php } ?>
-
- <?php if (login_is_conf ($this->conf)) { ?>
- <li>
- <?php if (!is_logged ()) { ?>
- <a id="signin" href="#">Connexion</a>
- <?php } else { ?>
- <a id="signout" href="#">Déconnexion</a>
- <?php } ?>
- </li>
- <?php } ?>
- </ul>
-
+<div class="aside">
<?php if (isset ($this->cat_aside)) { ?>
- <ul id="categories">
- <li class="all<?php echo !$this->get ? ' active' : ''; ?>">
- <a href="<?php echo Url::display (array ()); ?>">
- Tous
- <span><?php echo $this->nb_total; ?> article<?php echo $this->nb_total > 1 ? 's' : ''; ?> (<span class="nb_not_read"><?php echo $this->nb_not_read; ?></span>)</span>
+ <ul class="categories">
+ <li><a class="btn btn-important" href="<?php echo _url ('configure', 'feed'); ?>">Gestion des abonnements</a></li>
+
+ <li class="all">
+ <a class="btn category<?php echo !$this->get ? ' active' : ''; ?>" href="<?php echo _url ('index', 'index'); ?>">
+ <i class="icon all"></i>
+ Tous (<?php echo $this->nb_total; ?>)
+ <span class="notRead"><?php echo $this->nb_not_read; ?> non lu<?php echo $this->nb_not_read > 1 ? 's' : ''; ?></span>
+ </a>
+ </li>
+
+ <li class="favorites">
+ <a class="btn category<?php echo $this->get == 'favoris' ? ' active' : ''; ?>" href="<?php echo _url ('index', 'index', 'get', 'favoris'); ?>">
+ <i class="icon bookmark"></i>
+ Favoris (<?php echo $this->nb_favorites; ?>)
</a>
</li>
-
- <li class="favorites<?php echo $this->get == 'favoris' ? ' active' : ''; ?>"><a href="<?php echo Url::display (array ('params' => array ('get' => 'favoris'))); ?>">Favoris <span><?php echo $this->nb_favorites; ?> article<?php echo $this->nb_favorites > 1 ? 's' : ''; ?></span></a></li>
-
+
<?php foreach ($this->cat_aside as $cat) { ?>
- <li class="category<?php echo $this->get == $cat->id () ? ' active' : ''; ?>">
- <a href="<?php echo Url::display (array ('params' => array ('get' => $cat->id ()))); ?>">
+ <?php $feeds = $cat->feeds (); $catNotRead = $cat->nbNotRead (); ?>
+ <li>
+ <a class="btn category<?php echo $this->get == $cat->id () ? ' active' : ''; ?>" href="<?php echo _url ('index', 'index', 'get', 'c_' . $cat->id ()); ?>">
<?php echo $cat->name (); ?>
- <span><?php echo $cat->nbNotRead (); ?> non lu</span>
+ <span class="notRead"><?php echo $catNotRead ?> non lu<?php echo $catNotRead > 1 ? 's' : ''; ?></span>
</a>
+
+ <?php if (!empty ($feeds)) { ?>
+ <ul class="feeds">
+ <?php foreach ($feeds as $feed) { ?>
+ <li>
+ <img src="http://www.google.com/s2/favicons?domain=<?php echo get_domain ($feed->website ()); ?>" alt="" />
+ <a class="feed" href="<?php echo _url ('index', 'index', 'get', 'f_' . $feed->id ()); ?>">
+ <?php echo $feed->name(); ?>
+ <!--<span>X non lu</span>-->
+ </a>
+ </li>
+ <?php } ?>
+ </ul>
+ <?php } ?>
</li>
<?php } ?>
</ul>
diff --git a/app/layout/configure_aside.phtml b/app/layout/configure_aside.phtml
index b7a8fdeef..26a111045 100644
--- a/app/layout/configure_aside.phtml
+++ b/app/layout/configure_aside.phtml
@@ -4,9 +4,6 @@
<li <?php echo Request::actionName () == 'display' ? 'class="active"' : ''; ?>>
<a href="<?php echo Url::display (array ('c' => 'configure', 'a' => 'display')); ?>">Général et affichage</a>
</li>
- <li <?php echo Request::actionName () == 'feed' ? 'class="active"' : ''; ?>>
- <a href="<?php echo Url::display (array ('c' => 'configure', 'a' => 'feed')); ?>">Flux RSS</a>
- </li>
<li <?php echo Request::actionName () == 'categorize' ? 'class="active"' : ''; ?>>
<a href="<?php echo Url::display (array ('c' => 'configure', 'a' => 'categorize')); ?>">Catégories</a>
</li>
diff --git a/app/layout/header.phtml b/app/layout/header.phtml
new file mode 100644
index 000000000..d158e6353
--- /dev/null
+++ b/app/layout/header.phtml
@@ -0,0 +1,28 @@
+<div class="header">
+ <div class="item title">
+ <h1><a href="<?php echo _url ('index', 'index'); ?>">FreshRSS</a></h1>
+ </div>
+
+ <div class="item search">
+ <form action="<?php echo _url ('index', 'index'); ?>" method="get">
+ <input type="text" name="search" id="search" placeholder="Rechercher (non fonctionnel)" />
+ <button class="btn"><i class="icon search"></i></button>
+ </form>
+ </div>
+
+ <?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
+ <div class="item configure">
+ <a class="btn" href="<?php echo _url ('configure', 'display'); ?>"><i class="icon configure"></i></a>
+ </div>
+ <?php } ?>
+
+ <!--<?php if (login_is_conf ($this->conf)) { ?>
+ <li>
+ <?php if (!is_logged ()) { ?>
+ <a id="signin" href="#">Connexion</a>
+ <?php } else { ?>
+ <a id="signout" href="#">Déconnexion</a>
+ <?php } ?>
+ </li>
+ <?php } ?>-->
+</div>
diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml
index 5b2adae1e..4adcbef45 100644
--- a/app/layout/layout.phtml
+++ b/app/layout/layout.phtml
@@ -8,8 +8,12 @@
<?php echo self::headScript (); ?>
</head>
<body>
+<?php $this->partial ('header'); ?>
+
<div id="global">
+ <?php if (Request::controllerName () != 'configure') { ?>
<?php $this->partial ('aside'); ?>
+ <?php } ?>
<div id="main">
<?php $this->render (); ?>
@@ -21,7 +25,7 @@
<?php if (isset ($this->notification)) { ?>
<div class="notification <?php echo $this->notification['type']; ?>">
<?php echo $this->notification['content']; ?>
- <a class="close" href="">X</a>
+ <a class="close" href=""><i class="icon close"></i></a>
</div>
<?php } ?>
</body>
diff --git a/app/models/Category.php b/app/models/Category.php
index ceecea453..ef214137e 100755
--- a/app/models/Category.php
+++ b/app/models/Category.php
@@ -4,12 +4,13 @@ class Category extends Model {
private $id = false;
private $name;
private $color;
-
+ private $feeds = null;
+
public function __construct ($name = '', $color = '#0062BE') {
$this->_name ($name);
$this->_color ($color);
}
-
+
public function id () {
if (!$this->id) {
return small_hash ($this->name . Configuration::selApplication ());
@@ -31,7 +32,15 @@ class Category extends Model {
$catDAO = new CategoryDAO ();
return $catDAO->countNotRead ($this->id ());
}
-
+ public function feeds () {
+ if (is_null ($this->feeds)) {
+ $feedDAO = new FeedDAO ();
+ return $feedDAO->listByCategory ($this->id ());
+ } else {
+ return $this->feeds;
+ }
+ }
+
public function _id ($value) {
$this->id = $value;
}
@@ -45,6 +54,13 @@ class Category extends Model {
$this->color = '#0062BE';
}
}
+ public function _feeds ($values) {
+ if (!is_array ($values)) {
+ $values = array ($values);
+ }
+
+ $this->feeds = $values;
+ }
}
class CategoryDAO extends Model_pdo {
@@ -64,7 +80,7 @@ class CategoryDAO extends Model_pdo {
return false;
}
}
-
+
public function updateCategory ($id, $valuesTmp) {
$sql = 'UPDATE category SET name=?, color=? WHERE id=?';
$stm = $this->bd->prepare ($sql);
@@ -81,7 +97,7 @@ class CategoryDAO extends Model_pdo {
return false;
}
}
-
+
public function deleteCategory ($id) {
$sql = 'DELETE FROM category WHERE id=?';
$stm = $this->bd->prepare ($sql);
@@ -94,24 +110,24 @@ class CategoryDAO extends Model_pdo {
return false;
}
}
-
+
public function searchById ($id) {
$sql = 'SELECT * FROM category WHERE id=?';
$stm = $this->bd->prepare ($sql);
-
+
$values = array ($id);
-
+
$stm->execute ($values);
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$cat = HelperCategory::daoToCategory ($res);
-
+
if (isset ($cat[0])) {
return $cat[0];
} else {
return false;
}
}
-
+
public function listCategories () {
$sql = 'SELECT * FROM category ORDER BY name';
$stm = $this->bd->prepare ($sql);
@@ -119,7 +135,7 @@ class CategoryDAO extends Model_pdo {
return HelperCategory::daoToCategory ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function count () {
$sql = 'SELECT COUNT(*) AS count FROM category';
$stm = $this->bd->prepare ($sql);
@@ -128,7 +144,7 @@ class CategoryDAO extends Model_pdo {
return $res[0]['count'];
}
-
+
public function countFeed ($id) {
$sql = 'SELECT COUNT(*) AS count FROM feed WHERE category=?';
$stm = $this->bd->prepare ($sql);
@@ -138,7 +154,7 @@ class CategoryDAO extends Model_pdo {
return $res[0]['count'];
}
-
+
public function countNotRead ($id) {
$sql = 'SELECT COUNT(*) AS count FROM entry e INNER JOIN feed f ON e.id_feed = f.id WHERE category=? AND e.is_read=0';
$stm = $this->bd->prepare ($sql);
diff --git a/app/models/Entry.php b/app/models/Entry.php
index 4790a1681..f2aebbd24 100755
--- a/app/models/Entry.php
+++ b/app/models/Entry.php
@@ -11,7 +11,7 @@ class Entry extends Model {
private $is_read;
private $is_favorite;
private $feed;
-
+
public function __construct ($feed = '', $guid = '', $title = '', $author = '', $content = '',
$link = '', $pubdate = 0, $is_read = false, $is_favorite = false) {
$this->_guid ($guid);
@@ -24,7 +24,7 @@ class Entry extends Model {
$this->_isFavorite ($is_favorite);
$this->_feed ($feed);
}
-
+
public function id () {
if(is_null($this->id)) {
return small_hash ($this->guid . Configuration::selApplication ());
@@ -125,21 +125,21 @@ class EntryDAO extends Model_pdo {
return false;
}
}
-
+
public function updateEntry ($id, $valuesTmp) {
if (isset ($valuesTmp['content'])) {
$valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content'])));
}
-
+
$set = '';
foreach ($valuesTmp as $key => $v) {
$set .= $key . '=?, ';
}
$set = substr ($set, 0, -2);
-
+
$sql = 'UPDATE entry SET ' . $set . ' WHERE id=?';
$stm = $this->bd->prepare ($sql);
-
+
foreach ($valuesTmp as $v) {
$values[] = $v;
}
@@ -151,21 +151,21 @@ class EntryDAO extends Model_pdo {
return false;
}
}
-
+
public function updateEntries ($valuesTmp) {
if (isset ($valuesTmp['content'])) {
$valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content'])));
}
-
+
$set = '';
foreach ($valuesTmp as $key => $v) {
$set .= $key . '=?, ';
}
$set = substr ($set, 0, -2);
-
+
$sql = 'UPDATE entry SET ' . $set;
$stm = $this->bd->prepare ($sql);
-
+
foreach ($valuesTmp as $v) {
$values[] = $v;
}
@@ -176,7 +176,7 @@ class EntryDAO extends Model_pdo {
return false;
}
}
-
+
public function cleanOldEntries ($nb_month) {
$date = 60 * 60 * 24 * 30 * $nb_month;
$sql = 'DELETE FROM entry WHERE date <= ? AND is_favorite = 0';
@@ -185,52 +185,52 @@ class EntryDAO extends Model_pdo {
$values = array (
time () - $date
);
-
+
if ($stm && $stm->execute ($values)) {
return true;
} else {
return false;
}
}
-
+
public function searchById ($id) {
$sql = 'SELECT * FROM entry WHERE id=?';
$stm = $this->bd->prepare ($sql);
-
+
$values = array ($id);
-
+
$stm->execute ($values);
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$entry = HelperEntry::daoToEntry ($res);
-
+
if (isset ($entry[0])) {
return $entry[0];
} else {
return false;
}
}
-
+
public function listEntries ($mode, $order = 'high_to_low') {
$where = '';
if ($mode == 'not_read') {
$where = ' WHERE is_read=0';
}
-
+
if ($order == 'low_to_high') {
$order = ' DESC';
} else {
$order = '';
}
-
+
$sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
$stm = $this->bd->prepare ($sql);
$stm->execute ();
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$this->nbItems = $res[0]['count'];
-
+
$deb = ($this->currentPage - 1) * $this->nbItemsPerPage;
$fin = $this->nbItemsPerPage;
-
+
$sql = 'SELECT * FROM entry' . $where
. ' ORDER BY date' . $order
. ' LIMIT ' . $deb . ', ' . $fin;
@@ -239,77 +239,111 @@ class EntryDAO extends Model_pdo {
return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function listFavorites ($mode, $order = 'high_to_low') {
$where = ' WHERE is_favorite=1';
if ($mode == 'not_read') {
$where .= ' AND is_read=0';
}
-
+
if ($order == 'low_to_high') {
$order = ' DESC';
} else {
$order = '';
}
-
+
$sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
$stm = $this->bd->prepare ($sql);
$stm->execute ();
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$this->nbItems = $res[0]['count'];
-
+
if($this->nbItemsPerPage < 0) {
$sql = 'SELECT * FROM entry' . $where
. ' ORDER BY date' . $order;
} else {
$deb = ($this->currentPage - 1) * $this->nbItemsPerPage;
$fin = $this->nbItemsPerPage;
-
+
$sql = 'SELECT * FROM entry' . $where
. ' ORDER BY date' . $order
. ' LIMIT ' . $deb . ', ' . $fin;
}
$stm = $this->bd->prepare ($sql);
-
+
$stm->execute ();
return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function listByCategory ($cat, $mode, $order = 'high_to_low') {
$where = ' WHERE category=?';
if ($mode == 'not_read') {
$where .= ' AND is_read=0';
}
-
+
if ($order == 'low_to_high') {
$order = ' DESC';
} else {
$order = '';
}
-
+
$sql = 'SELECT COUNT(*) AS count FROM entry e INNER JOIN feed f ON e.id_feed = f.id' . $where;
$stm = $this->bd->prepare ($sql);
$values = array ($cat);
$stm->execute ($values);
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$this->nbItems = $res[0]['count'];
-
+
$deb = ($this->currentPage - 1) * $this->nbItemsPerPage;
$fin = $this->nbItemsPerPage;
$sql = 'SELECT * FROM entry e INNER JOIN feed f ON e.id_feed = f.id' . $where
. ' ORDER BY date' . $order
. ' LIMIT ' . $deb . ', ' . $fin;
-
+
$stm = $this->bd->prepare ($sql);
-
+
$values = array ($cat);
-
+
+ $stm->execute ($values);
+
+ return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
+ }
+
+ public function listByFeed ($feed, $mode, $order = 'high_to_low') {
+ $where = ' WHERE id_feed=?';
+ if ($mode == 'not_read') {
+ $where .= ' AND is_read=0';
+ }
+
+ if ($order == 'low_to_high') {
+ $order = ' DESC';
+ } else {
+ $order = '';
+ }
+
+ $sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
+ $stm = $this->bd->prepare ($sql);
+ $values = array ($feed);
+ $stm->execute ($values);
+ $res = $stm->fetchAll (PDO::FETCH_ASSOC);
+ $this->nbItems = $res[0]['count'];
+
+ $deb = ($this->currentPage - 1) * $this->nbItemsPerPage;
+ $fin = $this->nbItemsPerPage;
+ $sql = 'SELECT * FROM entry e' . $where
+ . ' ORDER BY date' . $order
+ . ' LIMIT ' . $deb . ', ' . $fin;
+
+ $stm = $this->bd->prepare ($sql);
+
+ $values = array ($feed);
+
$stm->execute ($values);
return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function count () {
$sql = 'SELECT COUNT(*) AS count FROM entry';
$stm = $this->bd->prepare ($sql);
@@ -318,25 +352,25 @@ class EntryDAO extends Model_pdo {
return $res[0]['count'];
}
-
+
public function countNotRead () {
$sql = 'SELECT COUNT(*) AS count FROM entry WHERE is_read=0';
$stm = $this->bd->prepare ($sql);
$stm->execute ();
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-
+
return $res[0]['count'];
}
-
+
public function countFavorites () {
$sql = 'SELECT COUNT(*) AS count FROM entry WHERE is_favorite=1';
$stm = $this->bd->prepare ($sql);
$stm->execute ();
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-
+
return $res[0]['count'];
}
-
+
// gestion de la pagination directement via le DAO
private $nbItemsPerPage = 1;
private $currentPage = 1;
@@ -347,13 +381,13 @@ class EntryDAO extends Model_pdo {
public function _currentPage ($value) {
$this->currentPage = $value;
}
-
+
public function getPaginator ($entries) {
$paginator = new Paginator ($entries);
$paginator->_nbItems ($this->nbItems);
$paginator->_nbItemsPerPage ($this->nbItemsPerPage);
$paginator->_currentPage ($this->currentPage);
-
+
return $paginator;
}
}
@@ -361,7 +395,7 @@ class EntryDAO extends Model_pdo {
class HelperEntry {
public static function daoToEntry ($listDAO, $mode = 'all', $favorite = false) {
$list = array ();
-
+
if (!is_array ($listDAO)) {
$listDAO = array ($listDAO);
}
diff --git a/app/models/Feed.php b/app/models/Feed.php
index db051c948..046e5af92 100644
--- a/app/models/Feed.php
+++ b/app/models/Feed.php
@@ -9,11 +9,11 @@ class Feed extends Model {
private $website = '';
private $description = '';
private $lastUpdate = 0;
-
+
public function __construct ($url) {
$this->_url ($url);
}
-
+
public function id () {
if(is_null($this->id)) {
return small_hash ($this->url . Configuration::selApplication ());
@@ -58,7 +58,7 @@ class Feed extends Model {
if (!is_null ($value) && !preg_match ('#^https?://#', $value)) {
$value = 'http://' . $value;
}
-
+
if (!is_null ($value) && filter_var ($value, FILTER_VALIDATE_URL)) {
$this->url = $value;
} else {
@@ -89,7 +89,7 @@ class Feed extends Model {
public function _lastUpdate ($value) {
$this->lastUpdate = $value;
}
-
+
public function load () {
if (!is_null ($this->url)) {
if (CACHE_PATH === false) {
@@ -113,13 +113,13 @@ class Feed extends Model {
}
private function loadEntries ($feed) {
$entries = array ();
-
+
foreach ($feed->get_items () as $item) {
$title = $item->get_title ();
$author = $item->get_author ();
$link = $item->get_permalink ();
$date = strtotime ($item->get_date ());
-
+
// Gestion du contenu
// On cherche à récupérer les articles en entier... même si le flux ne le propose pas
$path = get_path ($this->website ());
@@ -132,7 +132,7 @@ class Feed extends Model {
} else {
$content = $item->get_content ();
}
-
+
$entry = new Entry (
$this->id (),
$item->get_id (),
@@ -142,10 +142,10 @@ class Feed extends Model {
!is_null ($link) ? $link : '',
$date ? $date : time ()
);
-
+
$entries[$entry->id ()] = $entry;
}
-
+
$this->entries = $entries;
}
}
@@ -171,14 +171,14 @@ class FeedDAO extends Model_pdo {
return false;
}
}
-
+
public function updateFeed ($id, $valuesTmp) {
$set = '';
foreach ($valuesTmp as $key => $v) {
$set .= $key . '=?, ';
}
$set = substr ($set, 0, -2);
-
+
$sql = 'UPDATE feed SET ' . $set . ' WHERE id=?';
$stm = $this->bd->prepare ($sql);
@@ -193,7 +193,7 @@ class FeedDAO extends Model_pdo {
return false;
}
}
-
+
public function updateLastUpdate ($id) {
$sql = 'UPDATE feed SET lastUpdate=? WHERE id=?';
$stm = $this->bd->prepare ($sql);
@@ -209,7 +209,7 @@ class FeedDAO extends Model_pdo {
return false;
}
}
-
+
public function deleteFeed ($id) {
$sql = 'DELETE FROM feed WHERE id=?';
$stm = $this->bd->prepare ($sql);
@@ -222,24 +222,24 @@ class FeedDAO extends Model_pdo {
return false;
}
}
-
+
public function searchById ($id) {
$sql = 'SELECT * FROM feed WHERE id=?';
$stm = $this->bd->prepare ($sql);
-
+
$values = array ($id);
-
+
$stm->execute ($values);
$res = $stm->fetchAll (PDO::FETCH_ASSOC);
$feed = HelperFeed::daoToFeed ($res);
-
- if (isset ($feed[0])) {
- return $feed[0];
+
+ if (isset ($feed[$id])) {
+ return $feed[$id];
} else {
return false;
}
}
-
+
public function listFeeds () {
$sql = 'SELECT * FROM feed ORDER BY name';
$stm = $this->bd->prepare ($sql);
@@ -247,7 +247,7 @@ class FeedDAO extends Model_pdo {
return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function listFeedsOrderUpdate () {
$sql = 'SELECT * FROM feed ORDER BY lastUpdate';
$stm = $this->bd->prepare ($sql);
@@ -255,18 +255,18 @@ class FeedDAO extends Model_pdo {
return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function listByCategory ($cat) {
$sql = 'SELECT * FROM feed WHERE category=? ORDER BY name';
$stm = $this->bd->prepare ($sql);
-
+
$values = array ($cat);
-
+
$stm->execute ($values);
return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC));
}
-
+
public function count () {
$sql = 'SELECT COUNT(*) AS count FROM feed';
$stm = $this->bd->prepare ($sql);
@@ -275,7 +275,7 @@ class FeedDAO extends Model_pdo {
return $res[0]['count'];
}
-
+
public function countEntries ($id) {
$sql = 'SELECT COUNT(*) AS count FROM entry WHERE id_feed=?';
$stm = $this->bd->prepare ($sql);
@@ -296,6 +296,10 @@ class HelperFeed {
}
foreach ($listDAO as $key => $dao) {
+ if (isset ($dao['id'])) {
+ $key = $dao['id'];
+ }
+
$list[$key] = new Feed ($dao['url']);
$list[$key]->_category ($dao['category']);
$list[$key]->_name ($dao['name']);
diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml
index 0acec1872..1b8d77595 100644
--- a/app/views/configure/feed.phtml
+++ b/app/views/configure/feed.phtml
@@ -1,9 +1,15 @@
<div class="table">
- <?php $this->partial ('configure_aside'); ?>
+ <?php /* $this->partial ('configure_aside'); */ ?>
<div class="aside">
<ul>
<li><h2>Vox flux RSS</h2></li>
+ <?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
+ <li><form id="add_rss" method="post" action="<?php echo Url::display (array ('c' => 'feed', 'a' => 'add')); ?>">
+ <input type="url" name="url_rss" placeholder="Ajouter un flux RSS" />
+ <input type="submit" value="+" />
+ </form></li>
+ <?php } ?>
<?php if (!empty ($this->feeds)) { ?>
<?php foreach ($this->feeds as $feed) { ?>
<li <?php echo ($this->flux && $this->flux->id () == $feed->id ()) ? 'class="active"' : ''; ?>>
diff --git a/app/views/index/index.phtml b/app/views/index/index.phtml
index 429792b71..127a09ddd 100644
--- a/app/views/index/index.phtml
+++ b/app/views/index/index.phtml
@@ -1,8 +1,6 @@
<?php $items = $this->entryPaginator->items (true); ?>
-
-<?php if (!empty ($items)) { ?>
<div id="top">
- <a class="btn" href="<?php echo Url::display (array ('c' => 'feed', 'a' => 'actualize')); ?>"><i class="refresh"></i></a>
+ <a class="btn" href="<?php echo Url::display (array ('c' => 'feed', 'a' => 'actualize')); ?>"><i class="icon refresh"></i></a>
<?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
<a class="read_all btn" href="<?php echo Url::display (array ('c' => 'entry', 'a' => 'read', 'params' => array ('is_read' => 1))); ?>">Tout marquer comme lu</a><?php } ?><!--
@@ -13,6 +11,8 @@
<?php } ?>
</div>
+<?php if (!empty ($items)) { ?>
+
<div id="stream">
<?php foreach ($items as $item) { ?>
<div class="post flux<?php echo !$item->isRead () ? ' not_read' : ''; ?><?php echo $item->isFavorite () ? ' favorite' : ''; ?>" id="flux_<?php echo $item->id (); ?>">
diff --git a/public/theme/base.css b/public/theme/base.css
index b3e462353..80b8ca230 100644
--- a/public/theme/base.css
+++ b/public/theme/base.css
@@ -40,70 +40,14 @@ img {
}
/* FORMULAIRES */
-form {
- width: 450px;
- max-width: 100%;
- margin: 20px auto;
- padding: 20px;
- background: #f0f0f0;
- border: 1px solid #ddd;
- border-radius: 3px;
- box-shadow: 0 1px 3px #aaa;
-}
- label {
- display: block;
- margin: 20px 0 0;
- padding: 0 20px 0 0;
- font-weight: bold;
- }
- input:focus, textarea:focus {
- color: #3366cc !important;
- border: 1px solid #3366cc !important;
- }
- input[type="text"], input[type="url"], input[type="email"], input[type="number"], textarea {
- display: block;
- height: 30px;
- width: 430px;
- max-width: 95%;
- margin: 5px 0 5px;
- padding: 5px 10px;
- background: #fff;
- border: 1px solid #ccc;
- border-radius: 5px;
- font-size: 90%;
- }
- textarea {
- min-height: 100px;
- font-size: 110%;
- line-height: 150%;
- font-family: Monospace;
- }
- input[type="submit"], button {
- display: block;
- height: 40px;
- width: 100%;
- margin: 5px 0 5px;
- padding: 5px 0;
- }
- select {
- width: 100%;
- padding: 5px;
- }
- .radio_group, .checkbox_group {
- line-height: 35px;
- }
- .radio_group label, .checkbox_group label {
- display: inline-block;
- margin: 0;
- padding: 0 0 0 5px;
- font-weight: normal;
- }
.btn {
display: inline-block;
- height: 30px;
+ min-height: 30px;
+ min-width: 20px;
padding: 5px 10px;
+ background: #fff;
background: linear-gradient(#fff, #eee);
- border-radius: 3px;
+ border-radius: 5px;
border: 1px solid #ddd;
border-bottom: 1px solid #aaa;
border-right: 1px solid #aaa;
@@ -113,20 +57,56 @@ form {
vertical-align: middle;
}
.btn:hover {
+ background: #f4f4f4;
background: linear-gradient(#fafafa, #f0f0f0);
text-decoration: none;
}
+ .btn.active,
.btn:active {
box-shadow: 0px 2px 4px #e0e0e0 inset, 0px 1px 2px #fafafa;
+ background: #eee;
+ }
+
+ .btn.btn-important {
+ background: #0084CC;
+ background: linear-gradient(#0084CC, #0045CC);
+ color: #fff;
+ border: 1px solid #0062B7;
+ text-shadow: 0px 1px 1px #aaa;
}
+ .btn.btn-important:hover {
+ background: linear-gradient(#0066CC, #0045CC);
+ }
+ .btn.btn-important:active {
+ background: #0044CB;
+ box-shadow: none;
+ }
-/* *** */
-.refresh {
+/* ICONES */
+.icon {
display: inline-block;
- width: 30px;
- height: 30px;
- background: url("refresh.svg") center center no-repeat;
+ width: 16px;
+ height: 16px;
+ vertical-align: middle;
}
+ .icon.refresh {
+ background: url("icons/refresh.svg") center center no-repeat;
+ }
+ .icon.bookmark {
+ background: url("icons/starred.svg") center center no-repeat;
+ }
+ .icon.all {
+ background: url("icons/all.svg") center center no-repeat;
+ }
+ .icon.close {
+ background: url("icons/close.svg") center center no-repeat;
+ }
+ .icon.search {
+ background: url("icons/search.svg") center center no-repeat;
+ }
+ .icon.configure {
+ background: url("icons/configure.svg") center center no-repeat;
+ }
/* STRUCTURE */
#global {
@@ -135,88 +115,41 @@ form {
height: 100%;
background: #fafafa;
}
+ .header {
+ display: table;
+ width: 100%;
+ background: #f4f4f4;
+ table-layout: fixed;
+ }
+ .header .item {
+ display: table-cell;
+ padding: 10px 0;
+ border-bottom: 1px solid #aaa;
+ vertical-align: middle;
+ text-align: center;
+ }
+ .header .item.title {
+ width: 250px;
+ }
+ .header .item.title h1 {
+ padding: 0;
+ }
+ .header .item.title a:hover {
+ text-decoration: none;
+ }
+ .header .item.configure {
+ width: 100px;
+ }
.aside {
display: table-cell;
height: 100%;
width: 250px;
+ padding: 10px 0;
vertical-align: top;
border-right: 1px solid #aaa;
background: #fff;
}
- .aside ul {
- margin: 0;
- list-style: none;
- }
- .aside li {
- width: 100%;
- height: 50px;
- overflow: hidden;
- line-height: 50px;
- }
- .aside li > a, .aside li > span {
- display: block;
- width: 230px;
- padding: 0 10px;
- }
- .aside li > a:hover, .aside li > span:hover {
- text-decoration: none;
- background: #fafafa;
- }
- .aside li.disable > span {
- background: #fff;
- }
- .aside li > a > span {
- float: right;
- padding: 0 5px;
- font-size: 80%;
- }
- .aside li.active > a {
- background: #0062BE;
- color: #fff;
- }
- .aside li > h2 {
- height: 50px;
- padding: 0;
- text-align: center;
- background: #eee;
- line-height: 50px;
- }
-
- .aside form {
- display: table;
- width: 250px;
- margin: 0;
- padding: 0;
- background: #f0f0f0;
- border: none;
- border-bottom: 1px solid #aaa;
- border-radius: 0;
- box-shadow: none;
- }
- .aside form input {
- display: inline-block;
- height: 48px;
- line-height: 48px;
- }
- .aside form input[type="url"] {
- width: 200px;
- margin: 0;
- padding: 0;
- border: none !important;
- border-radius: 0;
- }
- .aside form input[type="submit"] {
- width: 50px;
- margin: 0;
- padding: 0;
- border: none;
- border-radius: 0;
- }
- #categories {
- height: 69%;
- overflow: auto;
- border-top: 1px solid #aaa;
- }
+
#main {
display: table-cell;
height: 100%;
@@ -248,6 +181,48 @@ form {
text-align: center;
}
+.categories {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ list-style: none;
+}
+ .categories .feeds .feed,
+ .categories .category {
+ display: block;
+ width: 200px;
+ margin: 5px auto;
+ text-align: left;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ .categories .feeds {
+ width: 200px;
+ margin: 0 auto;
+ list-style: none;
+ }
+ .categories .feeds .feed {
+ display: inline-block;
+ margin: 0;
+ width: 170px;
+ line-height: 35px;
+ font-size: 90%;
+ vertical-align: middle;
+ }
+ .categories .notRead {
+ padding: 5px;
+ background: #bbb;
+ color: #fff;
+ font-size: 90%;
+ border: 1px solid #bbb;
+ border-right: 1px solid #999;
+ border-bottom: 1px solid #999;
+ border-radius: 5px;
+ box-shadow: 0 3px 3px #999 inset;
+ text-shadow: 0 0 1px #aaa;
+ }
+
.post {
}
.post.flux {
@@ -327,27 +302,27 @@ form {
display: inline-block;
width: 25px;
height: 25px;
- background: url("read.svg") center center no-repeat;
+ background: url("icons/read.svg") center center no-repeat;
vertical-align: middle;
}
.flux_header .item.manage .read:hover {
text-decoration: none;
}
.post.flux.not_read .flux_header .item.manage .read {
- background: url("unread.svg") center center no-repeat;
+ background: url("icons/unread.svg") center center no-repeat;
}
.flux_header .item.manage .bookmark {
display: inline-block;
width: 25px;
height: 25px;
- background: url("non-starred.svg") center center no-repeat;
+ background: url("icons/non-starred.svg") center center no-repeat;
vertical-align: middle;
}
.flux_header .item.manage .bookmark:hover {
text-decoration: none;
}
.post.flux.favorite .flux_header .item.manage .bookmark {
- background: url("starred.svg") center center no-repeat;
+ background: url("icons/starred.svg") center center no-repeat;
}
.flux_header .item.website {
width: 200px;
@@ -439,25 +414,23 @@ form {
}
.notification a.close {
display: inline-block;
- width: 25px;
- height: 25px;
+ width: 16px;
+ height: 16px;
float: right;
margin: -10px -60px 0 0;
+ padding: 5px;
background: #fff;
border-radius: 50px;
border: 1px solid #aaa;
- line-height: 25px;
- color: #666;
+ line-height: 16px;
}
- .notification a.close:hover {
- text-decoration: none;
- }
@media(max-width: 840px) {
#global {
table-layout: fixed;
}
- #main_aside {
+ .header,
+ .aside {
display: none;
}
#main {
@@ -485,3 +458,8 @@ form {
display: none;
}
}
+@media(max-width: 450px) {
+ #top {
+ display: none;
+ }
+}
diff --git a/public/theme/icons/all.svg b/public/theme/icons/all.svg
new file mode 100644
index 000000000..2180f7a4b
--- /dev/null
+++ b/public/theme/icons/all.svg
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:svg='http://www.w3.org/2000/svg' id='svg7384' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' sodipodi:docname='view-list-symbolic.svg' version='1.1' inkscape:version='0.48.1 r9760' height='16' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns='http://www.w3.org/2000/svg' width='16'>
+ <metadata id='metadata90'>
+ <rdf:RDF>
+ <cc:Work rdf:about=''>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview inkscape:cy='71.95215' pagecolor='#555753' borderopacity='1' showborder='false' inkscape:bbox-paths='false' guidetolerance='10' inkscape:object-paths='true' inkscape:window-width='1198' showguides='true' inkscape:object-nodes='true' inkscape:snap-bbox='true' inkscape:pageshadow='2' inkscape:guide-bbox='true' inkscape:snap-nodes='false' bordercolor='#666666' objecttolerance='10' id='namedview88' showgrid='false' inkscape:window-maximized='0' inkscape:window-x='1582' inkscape:snap-global='true' inkscape:window-y='85' gridtolerance='10' inkscape:window-height='1079' inkscape:snap-to-guides='true' inkscape:current-layer='layer12' inkscape:snap-bbox-midpoints='false' inkscape:zoom='1' inkscape:cx='244.57499' inkscape:snap-grids='true' inkscape:pageopacity='1'>
+ <inkscape:grid spacingx='1px' spacingy='1px' id='grid4866' empspacing='2' enabled='true' type='xygrid' snapvisiblegridlinesonly='true' visible='true'/>
+ </sodipodi:namedview>
+ <title id='title9167'>Gnome Symbolic Icon Theme</title>
+ <defs id='defs7386'/>
+ <g inkscape:label='status' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer9' style='display:inline'/>
+ <g inkscape:label='devices' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer10'/>
+ <g inkscape:label='apps' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer11'/>
+ <g inkscape:label='actions' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer12'>
+
+ <rect inkscape:label='a' x='43.000397' y='748.99976' id='rect7356' height='2.0002136' width='9.9996014' style='color:#bebebe;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible'/>
+ <rect inkscape:label='a' x='43.000397' y='752.99976' id='rect7358' height='2.0002136' width='9.9996014' style='color:#bebebe;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible'/>
+ <rect inkscape:label='a' x='43.000397' y='756.99976' id='rect7360' height='2.0002136' width='9.9996014' style='color:#bebebe;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible'/>
+ </g>
+ <g inkscape:label='places' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer13'/>
+ <g inkscape:label='mimetypes' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer14'/>
+ <g inkscape:label='emblems' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='layer15' style='display:inline'/>
+ <g inkscape:label='categories' transform='translate(-40.0002,-746)' inkscape:groupmode='layer' id='g4953' style='display:inline'/>
+</svg>
diff --git a/public/theme/icons/close.svg b/public/theme/icons/close.svg
new file mode 100644
index 000000000..c0c786fd6
--- /dev/null
+++ b/public/theme/icons/close.svg
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:svg='http://www.w3.org/2000/svg' id='svg7384' version='1.1' height='16' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns='http://www.w3.org/2000/svg' width='16'>
+ <title id='title9167'>Gnome Symbolic Icon Theme</title>
+ <metadata id='metadata90'>
+ <rdf:RDF>
+ <cc:Work rdf:about=''>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs id='defs7386'/>
+ <g transform='translate(-60,-518)' id='layer9' style='display:inline'/>
+ <g transform='translate(-60,-518)' id='layer10'/>
+ <g transform='translate(-60,-518)' id='layer11'/>
+ <g transform='translate(-60,-518)' id='layer12'>
+ <g transform='translate(19,-242)' id='layer4-4-1' style='display:inline'>
+
+ <path inkscape:connector-curvature='0' d='m 45,764 1,0 c 0.01037,-1.2e-4 0.02079,-4.6e-4 0.03125,0 0.254951,0.0112 0.50987,0.12858 0.6875,0.3125 L 49,766.59375 51.3125,764.3125 C 51.578125,764.082 51.759172,764.007 52,764 l 1,0 0,1 c 0,0.28647 -0.03434,0.55065 -0.25,0.75 l -2.28125,2.28125 2.25,2.25 C 52.906938,770.46942 52.999992,770.7347 53,771 l 0,1 -1,0 c -0.265301,-10e-6 -0.530586,-0.0931 -0.71875,-0.28125 L 49,769.4375 46.71875,771.71875 C 46.530586,771.90694 46.26529,772 46,772 l -1,0 0,-1 c -3e-6,-0.26529 0.09306,-0.53058 0.28125,-0.71875 l 2.28125,-2.25 L 45.28125,765.75 C 45.070508,765.55537 44.97809,765.28075 45,765 l 0,-1 z' id='path10839-9' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#bebebe;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.78124988;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Andale Mono;-inkscape-font-specification:Andale Mono'/>
+ </g>
+ </g>
+ <g transform='translate(-60,-518)' id='layer13'/>
+ <g transform='translate(-60,-518)' id='layer14'/>
+ <g transform='translate(-60,-518)' id='layer15'/>
+</svg>
diff --git a/public/theme/icons/configure.svg b/public/theme/icons/configure.svg
new file mode 100644
index 000000000..52df8bca7
--- /dev/null
+++ b/public/theme/icons/configure.svg
@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns='http://www.w3.org/2000/svg' id='svg7384' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:cc='http://creativecommons.org/ns#' xmlns:svg='http://www.w3.org/2000/svg' width='16' sodipodi:docname='emblem-system-symbolic.svg' height='16' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' version='1.1' inkscape:version='0.48.1 r9760'>
+ <metadata id='metadata90'>
+ <rdf:RDF>
+ <cc:Work rdf:about=''>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview inkscape:window-height='967' inkscape:snap-bbox-midpoints='false' inkscape:snap-grids='true' inkscape:object-paths='false' pagecolor='#555753' inkscape:zoom='1' inkscape:current-layer='layer15' borderopacity='1' inkscape:snap-others='false' inkscape:window-x='2259' inkscape:window-y='356' inkscape:snap-to-guides='true' gridtolerance='10' id='namedview88' inkscape:snap-global='true' inkscape:cx='9.30971' inkscape:cy='-0.23089111' bordercolor='#666666' inkscape:window-width='1226' inkscape:snap-bbox='true' guidetolerance='10' showguides='true' showborder='false' inkscape:guide-bbox='true' inkscape:object-nodes='false' inkscape:pageopacity='1' inkscape:window-maximized='0' objecttolerance='10' showgrid='false' inkscape:snap-nodes='true' inkscape:bbox-paths='false' inkscape:pageshadow='2'>
+ <inkscape:grid visible='true' spacingx='1px' spacingy='1px' id='grid4866' type='xygrid' empspacing='2' enabled='true' snapvisiblegridlinesonly='true'/>
+ </sodipodi:namedview>
+ <title id='title9167'>Gnome Symbolic Icon Theme</title>
+ <defs id='defs7386'/>
+ <g inkscape:label='status' id='layer9' style='display:inline' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='devices' id='layer10' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='apps' id='layer11' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='places' id='layer13' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='mimetypes' id='layer14' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='emblems' id='layer15' style='display:inline' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'>
+
+ <path id='path35543-6-4' d='m 449.0004,402.00002 c -0.22065,0 -0.44081,0.0113 -0.65625,0.0312 l -0.40625,2.09375 c -0.33446,0.0733 -0.66305,0.17589 -0.96875,0.3125 l -1.53125,-1.46875 c -0.38863,0.23011 -0.72695,0.51408 -1.0625,0.8125 l 0.90625,1.90625 c -0.22242,0.24899 -0.42425,0.5225 -0.59375,0.8125 l -2.09375,-0.28125 c -0.17772,0.40877 -0.30872,0.83637 -0.40625,1.28125 l 1.84375,1 c -0.0171,0.16809 -0.0312,0.3274 -0.0312,0.5 0,0.1726 0.0142,0.33191 0.0312,0.5 l -1.84375,1 c 0.0975,0.44488 0.22853,0.87248 0.40625,1.28125 l 2.09375,-0.28125 c 0.1695,0.29 0.37133,0.56351 0.59375,0.8125 l -0.90625,1.90625 c 0.33555,0.29842 0.67387,0.58239 1.0625,0.8125 l 1.53125,-1.46875 c 0.3057,0.13661 0.63429,0.23916 0.96875,0.3125 l 0.40625,2.09375 c 0.21544,0.02 0.4356,0.0312 0.65625,0.0312 0.22065,0 0.44081,-0.0113 0.65625,-0.0312 l 0.40625,-2.09375 c 0.33446,-0.0733 0.66305,-0.17589 0.96875,-0.3125 l 1.53125,1.46875 c 0.38863,-0.23011 0.72695,-0.51408 1.0625,-0.8125 l -0.90625,-1.90625 c 0.22242,-0.24899 0.42425,-0.5225 0.59375,-0.8125 l 2.09375,0.28125 c 0.17772,-0.40877 0.30872,-0.83637 0.40625,-1.28125 l -1.84375,-1 c 0.0171,-0.16809 0.0312,-0.3274 0.0312,-0.5 0,-0.1726 -0.0142,-0.33191 -0.0312,-0.5 l 1.84375,-1 c -0.0975,-0.44488 -0.22853,-0.87248 -0.40625,-1.28125 l -2.09375,0.28125 c -0.1695,-0.29 -0.37133,-0.56351 -0.59375,-0.8125 l 0.90625,-1.90625 c -0.33555,-0.29842 -0.67387,-0.58239 -1.0625,-0.8125 l -1.53125,1.46875 c -0.3057,-0.13661 -0.63429,-0.23916 -0.96875,-0.3125 l -0.40625,-2.09375 c -0.21544,-0.02 -0.4356,-0.0312 -0.65625,-0.0312 z m 0,4 c 1.65685,0 3,1.34315 3,3 0,1.65685 -1.34315,3 -3,3 -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 z' style='color:#666666;fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate' inkscape:connector-curvature='0' sodipodi:nodetypes='sccccccccccsccccccccccsccccccccccsccccccccccssssss'/>
+ </g>
+ <g inkscape:label='emotes' id='g71291' style='display:inline' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='categories' id='g4953' style='display:inline' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+ <g inkscape:label='actions' id='layer12' style='display:inline' transform='translate(-441.0002,-400.99999)' inkscape:groupmode='layer'/>
+</svg>
diff --git a/public/theme/non-starred.svg b/public/theme/icons/non-starred.svg
index 346717f78..346717f78 100644
--- a/public/theme/non-starred.svg
+++ b/public/theme/icons/non-starred.svg
diff --git a/public/theme/read.svg b/public/theme/icons/read.svg
index 932bfd860..932bfd860 100644
--- a/public/theme/read.svg
+++ b/public/theme/icons/read.svg
diff --git a/public/theme/refresh.svg b/public/theme/icons/refresh.svg
index 11728fc5d..11728fc5d 100644
--- a/public/theme/refresh.svg
+++ b/public/theme/icons/refresh.svg
diff --git a/public/theme/icons/search.svg b/public/theme/icons/search.svg
new file mode 100644
index 000000000..acfb364cc
--- /dev/null
+++ b/public/theme/icons/search.svg
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:dc='http://purl.org/dc/elements/1.1/' sodipodi:docname='folder-saved-search-symbolic.svg' height='16' id='svg7384' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:svg='http://www.w3.org/2000/svg' inkscape:version='0.48.2 r9819' version='1.1' width='16.000002' xmlns='http://www.w3.org/2000/svg'>
+ <metadata id='metadata90'>
+ <rdf:RDF>
+ <cc:Work rdf:about=''>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview inkscape:bbox-paths='false' bordercolor='#666666' borderopacity='1' inkscape:current-layer='layer13' inkscape:cx='-151.02446' inkscape:cy='0.353386' gridtolerance='10' inkscape:guide-bbox='true' guidetolerance='10' id='namedview88' inkscape:object-nodes='false' inkscape:object-paths='false' objecttolerance='10' pagecolor='#555753' inkscape:pageopacity='1' inkscape:pageshadow='2' showborder='false' showgrid='false' showguides='true' inkscape:snap-bbox='true' inkscape:snap-bbox-midpoints='false' inkscape:snap-global='true' inkscape:snap-grids='true' inkscape:snap-nodes='false' inkscape:snap-others='false' inkscape:snap-to-guides='true' inkscape:window-height='1168' inkscape:window-maximized='1' inkscape:window-width='1600' inkscape:window-x='0' inkscape:window-y='0' inkscape:zoom='1'>
+ <inkscape:grid empspacing='2' enabled='true' id='grid4866' snapvisiblegridlinesonly='true' spacingx='1px' spacingy='1px' type='xygrid' visible='true'/>
+ </sodipodi:namedview>
+ <title id='title9167'>Gnome Symbolic Icon Theme</title>
+ <defs id='defs7386'/>
+ <g inkscape:groupmode='layer' id='layer9' inkscape:label='status' style='display:inline' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='layer10' inkscape:label='devices' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='layer11' inkscape:label='apps' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='layer13' inkscape:label='places' transform='translate(-441.0004,-195)'>
+ <path inkscape:connector-curvature='0' d='m 447.50781,195.99554 c -3.02886,0 -5.51073,2.47905 -5.51073,5.50447 0,3.02541 2.48187,5.50446 5.51073,5.50446 3.02885,0 5.51072,-2.47905 5.51072,-5.50446 0,-3.02542 -2.48187,-5.50447 -5.51072,-5.50447 z m 0,2.00893 c 1.94735,0 3.49951,1.55039 3.49951,3.49554 0,1.94514 -1.55216,3.49553 -3.49951,3.49553 -1.94736,0 -3.49952,-1.55039 -3.49952,-3.49553 0,-1.94515 1.55216,-3.49554 3.49952,-3.49554 z' id='path5079' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#666666;fill:#666666;fill-opacity:1;stroke:none;stroke-width:1.55467153;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Sans;-inkscape-font-specification:Sans'/>
+ <path inkscape:connector-curvature='0' d='m 450.8125,204 a 1.0001,1.0001 0 0 0 -0.5,1.71875 l 4,4 a 1.0054782,1.0054782 0 1 0 1.40625,-1.4375 l -4,-4 A 1.0001,1.0001 0 0 0 450.8125,204 z' id='path5081' style='font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#666666;fill:#666666;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Sans;-inkscape-font-specification:Sans'/>
+
+ </g>
+ <g inkscape:groupmode='layer' id='layer14' inkscape:label='mimetypes' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='layer15' inkscape:label='emblems' style='display:inline' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='g71291' inkscape:label='emotes' style='display:inline' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='g4953' inkscape:label='categories' style='display:inline' transform='translate(-441.0004,-195)'/>
+ <g inkscape:groupmode='layer' id='layer12' inkscape:label='actions' style='display:inline' transform='translate(-441.0004,-195)'/>
+</svg>
diff --git a/public/theme/starred.svg b/public/theme/icons/starred.svg
index 0944a7726..0944a7726 100644
--- a/public/theme/starred.svg
+++ b/public/theme/icons/starred.svg
diff --git a/public/theme/unread.svg b/public/theme/icons/unread.svg
index 9219b5083..9219b5083 100644
--- a/public/theme/unread.svg
+++ b/public/theme/icons/unread.svg
diff --git a/public/theme/website.svg b/public/theme/icons/website.svg
index ddc8e0706..ddc8e0706 100644
--- a/public/theme/website.svg
+++ b/public/theme/icons/website.svg
diff --git a/public/theme/read_mode.png b/public/theme/read_mode.png
deleted file mode 100644
index 881399237..000000000
--- a/public/theme/read_mode.png
+++ /dev/null
Binary files differ