Kaynağa Gözat

Grosse mise à jour du design, pas mal de trucs cassés au niveau du panneau de configuration

Marien Fressinaud 13 yıl önce
ebeveyn
işleme
c62ec2a144

+ 49 - 28
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');

+ 35 - 41
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>

+ 0 - 3
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>

+ 28 - 0
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>

+ 5 - 1
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>

+ 29 - 13
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);

+ 77 - 43
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);
 		}

+ 30 - 26
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']);

+ 7 - 1
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"' : ''; ?>>

+ 3 - 3
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 (); ?>">

+ 129 - 151
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;
+	}
+}

+ 32 - 0
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>

+ 28 - 0
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>

+ 31 - 0
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>

+ 0 - 0
public/theme/non-starred.svg → public/theme/icons/non-starred.svg


+ 0 - 0
public/theme/read.svg → public/theme/icons/read.svg


+ 0 - 0
public/theme/refresh.svg → public/theme/icons/refresh.svg


+ 32 - 0
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>

+ 0 - 0
public/theme/starred.svg → public/theme/icons/starred.svg


+ 0 - 0
public/theme/unread.svg → public/theme/icons/unread.svg


+ 0 - 0
public/theme/website.svg → public/theme/icons/website.svg


BIN
public/theme/read_mode.png