From e7dba0ce7cfaf5e84687593a8b0d58d89fbff302 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Sat, 9 Aug 2014 23:29:13 +0200
Subject: Add basic system of update
- Check on update.freshrss.org for new updates
- Download script
- Apply script
- Need translations and verifications
NOTE: current script on server indicates version 0.7.3 is an update
of 0.8-dev ==> IT'S ONLY FOR MY TESTS!
Script just does a backup of ./data actually...
See https://github.com/marienfressinaud/FreshRSS/issues/411
---
app/Controllers/updateController.php | 106 +++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
create mode 100644 app/Controllers/updateController.php
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
new file mode 100644
index 000000000..a15cb9fd5
--- /dev/null
+++ b/app/Controllers/updateController.php
@@ -0,0 +1,106 @@
+view->loginOk && Minz_Configuration::isAdmin($current_user)) {
+ Minz_Error::error(
+ 403,
+ array('error' => array(_t('access_denied')))
+ );
+ }
+
+ Minz_View::prependTitle(_t('update_system') . ' · ');
+ }
+
+ public function indexAction() {
+ if (file_exists(UPDATE_FILENAME)) {
+ // There is an update file to apply!
+ $this->view->message = array(
+ 'status' => 'good',
+ 'title' => _t('ok'),
+ 'body' => _t('update_can_apply', _url('update', 'apply'))
+ );
+
+ return;
+ }
+ }
+
+ public function checkAction() {
+ $this->view->change_view('update', 'index');
+
+ if (file_exists(UPDATE_FILENAME)) {
+ // There is already an update file to apply: we don't need to check
+ // the webserver!
+ $this->view->message = array(
+ 'status' => 'good',
+ 'title' => _t('ok'),
+ 'body' => _t('update_can_apply', _url('update', 'apply'))
+ );
+
+ return;
+ }
+
+ $c = curl_init(FRESHRSS_UPDATE_WEBSITE);
+ curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
+ $result = curl_exec($c);
+
+ if (curl_getinfo($c, CURLINFO_HTTP_CODE) == 200) {
+ $res_array = explode("\n", $result, 2);
+ $status = $res_array[0];
+
+ if (strpos($status, 'UPDATE') === 0) {
+ $script = $res_array[1];
+ if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
+ $this->view->message = array(
+ 'status' => 'good',
+ 'title' => _t('ok'),
+ 'body' => _t('update_can_apply', _url('update', 'apply'))
+ );
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('update_problem')
+ );
+ }
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('no_update')
+ );
+ }
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('update_server_not_found', FRESHRSS_UPDATE_WEBSITE)
+ );
+ }
+ curl_close($c);
+ }
+
+ public function applyAction() {
+ require(UPDATE_FILENAME);
+ $res = apply_update();
+
+ if ($res === true) {
+ @unlink(UPDATE_FILENAME);
+
+ Minz_Session::_param('notification', array(
+ 'type' => 'good',
+ 'content' => Minz_Translate::t('update_finished')
+ ));
+
+ Minz_Request::forward(array(), true);
+ } else {
+ Minz_Session::_param('notification', array(
+ 'type' => 'bad',
+ 'content' => Minz_Translate::t('update_failed', $res)
+ ));
+
+ Minz_Request::forward(array('c' => 'update'), true);
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.2.3
From 7ed111b1bf152613d17254808a4fcf89f5774297 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Sun, 10 Aug 2014 10:35:17 +0200
Subject: Add translations for update system
---
app/Controllers/updateController.php | 7 +++++--
app/i18n/en.php | 9 +++++++++
app/i18n/fr.php | 11 ++++++++++-
app/views/update/index.phtml | 4 +++-
4 files changed, 27 insertions(+), 4 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index a15cb9fd5..a94af4417 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -11,6 +11,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
}
Minz_View::prependTitle(_t('update_system') . ' · ');
+ $this->view->last_update_time = 'unknown'; // TODO
}
public function indexAction() {
@@ -61,7 +62,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
$this->view->message = array(
'status' => 'bad',
'title' => _t('damn'),
- 'body' => _t('update_problem')
+ 'body' => _t('update_problem', 'Cannot save the update script')
);
}
} else {
@@ -88,6 +89,8 @@ class FreshRSS_update_Controller extends Minz_ActionController {
if ($res === true) {
@unlink(UPDATE_FILENAME);
+ // TODO: record last update
+
Minz_Session::_param('notification', array(
'type' => 'good',
'content' => Minz_Translate::t('update_finished')
@@ -97,7 +100,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
} else {
Minz_Session::_param('notification', array(
'type' => 'bad',
- 'content' => Minz_Translate::t('update_failed', $res)
+ 'content' => Minz_Translate::t('update_problem', $res)
));
Minz_Request::forward(array('c' => 'update'), true);
diff --git a/app/i18n/en.php b/app/i18n/en.php
index 6110ccb11..6a0b4a139 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -192,6 +192,7 @@ return array (
'informations' => 'Information',
'damn' => 'Damn!',
+ 'ok' => 'Ok!',
'feed_in_error' => 'This feed has encountered a problem. Please verify that it is always reachable then actualize it.',
'feed_empty' => 'This feed is empty. Please verify that it is still maintained.',
'feed_description' => 'Description',
@@ -409,5 +410,13 @@ return array (
'stats_top_feed' => 'Top ten feeds',
'stats_entry_count' => 'Entry count',
+ 'update' => 'Update',
+ 'update_system' => 'Update system',
+ 'update_check' => 'Check for new updates',
+ 'update_last' => 'Last update: %s',
'update_can_apply' => 'There is an available update. Apply ',
+ 'update_server_not_found' => 'Update server cannot be found. [%s]',
+ 'no_update' => 'No update to apply',
+ 'update_problem' => 'Update has encountered an error: %s',
+ 'update_finished' => 'Update is now finished!',
);
diff --git a/app/i18n/fr.php b/app/i18n/fr.php
index 5f88aa069..d0637b9f7 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -192,6 +192,7 @@ return array (
'informations' => 'Informations',
'damn' => 'Arf !',
+ 'ok' => 'Ok !',
'feed_in_error' => 'Ce flux a rencontré un problème. Veuillez vérifier qu’il est toujours accessible puis actualisez-le.',
'feed_empty' => 'Ce flux est vide. Veuillez vérifier qu’il est toujours maintenu.',
'feed_description' => 'Description',
@@ -409,5 +410,13 @@ return array (
'stats_top_feed' => 'Les dix plus gros flux',
'stats_entry_count' => 'Nombre d’articles',
- 'update_can_apply' => 'Il y’a une mise à jour à appliquer. Appliquer ',
+ 'update' => 'Mise à jour',
+ 'update_system' => 'Système de mise à jour',
+ 'update_check' => 'Vérifier les mises à jour',
+ 'update_last' => 'Dernière mise à jour : %s',
+ 'update_can_apply' => 'Il y’a une mise à jour à appliquer. Appliquer la mise à jour ',
+ 'update_server_not_found' => 'Le serveur de mise à jour n’a pas été trouvé. [%s]',
+ 'no_update' => 'Aucune mise à jour à appliquer',
+ 'update_problem' => 'La mise à jour a rencontré un problème : %s',
+ 'update_finished' => 'La mise à jour est terminée !',
);
diff --git a/app/views/update/index.phtml b/app/views/update/index.phtml
index a1a872845..8f6ee6269 100644
--- a/app/views/update/index.phtml
+++ b/app/views/update/index.phtml
@@ -12,8 +12,10 @@
message) || $this->message['status'] !== 'good') { ?>
-
last_update_time); ?>
+
+
+
--
cgit v1.2.3
From 9a5d6245fbeb413766362fd6b2c4f5f5b6a22a22 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Sun, 10 Aug 2014 10:55:51 +0200
Subject: Improve update API
Update script must implement 4 functions:
- apply_update() to perform the update (most important). Return true if
all is ok, else false.
- need_info_update() returns true if we need more info for update, else
false. If this function always returns false, you don't need to
implement following functions (but it's better to not forget)
- ask_info_update() should be a HTML form to ask infos. Method must be
post and action must point to _url('update', 'apply') (or leave it
blank)
- save_info_update() is called for POST requests (to save form from
ask_info_update())
---
app/Controllers/updateController.php | 37 +++++++++++++++++++++---------------
app/views/update/apply.phtml | 9 +++++++++
app/views/update/index.phtml | 2 ++
3 files changed, 33 insertions(+), 15 deletions(-)
create mode 100644 app/views/update/apply.phtml
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index a94af4417..1095f9da7 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -84,26 +84,33 @@ class FreshRSS_update_Controller extends Minz_ActionController {
public function applyAction() {
require(UPDATE_FILENAME);
- $res = apply_update();
- if ($res === true) {
- @unlink(UPDATE_FILENAME);
+ if (Minz_Request::isPost()) {
+ save_info_update();
+ }
- // TODO: record last update
+ if (!need_info_update()) {
+ $res = apply_update();
- Minz_Session::_param('notification', array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('update_finished')
- ));
+ if ($res === true) {
+ @unlink(UPDATE_FILENAME);
- Minz_Request::forward(array(), true);
- } else {
- Minz_Session::_param('notification', array(
- 'type' => 'bad',
- 'content' => Minz_Translate::t('update_problem', $res)
- ));
+ // TODO: record last update
+
+ Minz_Session::_param('notification', array(
+ 'type' => 'good',
+ 'content' => Minz_Translate::t('update_finished')
+ ));
- Minz_Request::forward(array('c' => 'update'), true);
+ Minz_Request::forward(array(), true);
+ } else {
+ Minz_Session::_param('notification', array(
+ 'type' => 'bad',
+ 'content' => Minz_Translate::t('update_problem', $res)
+ ));
+
+ Minz_Request::forward(array('c' => 'update'), true);
+ }
}
}
}
\ No newline at end of file
diff --git a/app/views/update/apply.phtml b/app/views/update/apply.phtml
new file mode 100644
index 000000000..d7ea466c5
--- /dev/null
+++ b/app/views/update/apply.phtml
@@ -0,0 +1,9 @@
+partial('aside_configure'); ?>
+
+
\ No newline at end of file
diff --git a/app/views/update/index.phtml b/app/views/update/index.phtml
index 8f6ee6269..1824c02b8 100644
--- a/app/views/update/index.phtml
+++ b/app/views/update/index.phtml
@@ -1,6 +1,8 @@
partial('aside_configure'); ?>
+
+
message)) { ?>
--
cgit v1.2.3
From 3ca8c7ec4c55b4fa751fbcdc8e28f28351c4a967 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Sun, 10 Aug 2014 11:52:18 +0200
Subject: Litlle improvements (update system)
- Check UPDATE_FILENAME exists before applying update
- Add empty line at the end of files
---
app/Controllers/updateController.php | 7 ++++++-
app/views/update/apply.phtml | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 1095f9da7..fa62f4a70 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -79,10 +79,15 @@ class FreshRSS_update_Controller extends Minz_ActionController {
'body' => _t('update_server_not_found', FRESHRSS_UPDATE_WEBSITE)
);
}
+
curl_close($c);
}
public function applyAction() {
+ if (!file_exists(UPDATE_FILENAME)) {
+ Minz_Request::forward(array('c' => 'update'), true);
+ }
+
require(UPDATE_FILENAME);
if (Minz_Request::isPost()) {
@@ -113,4 +118,4 @@ class FreshRSS_update_Controller extends Minz_ActionController {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/views/update/apply.phtml b/app/views/update/apply.phtml
index d7ea466c5..30566c7ab 100644
--- a/app/views/update/apply.phtml
+++ b/app/views/update/apply.phtml
@@ -6,4 +6,4 @@
-
\ No newline at end of file
+
--
cgit v1.2.3
From 909d8747ba09f9c9a6ac895f1f4f0763bdb27a55 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Tue, 12 Aug 2014 20:15:46 +0200
Subject: Update system now uses HTTPS connection
- Add some curl checks
- Refactor code
---
app/Controllers/updateController.php | 60 +++++++++++++++++++-----------------
constants.php | 2 +-
2 files changed, 33 insertions(+), 29 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index fa62f4a70..857d975b2 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -44,43 +44,47 @@ class FreshRSS_update_Controller extends Minz_ActionController {
$c = curl_init(FRESHRSS_UPDATE_WEBSITE);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
$result = curl_exec($c);
+ $c_status = curl_getinfo($c, CURLINFO_HTTP_CODE);
+ curl_close($c);
- if (curl_getinfo($c, CURLINFO_HTTP_CODE) == 200) {
- $res_array = explode("\n", $result, 2);
- $status = $res_array[0];
-
- if (strpos($status, 'UPDATE') === 0) {
- $script = $res_array[1];
- if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
- $this->view->message = array(
- 'status' => 'good',
- 'title' => _t('ok'),
- 'body' => _t('update_can_apply', _url('update', 'apply'))
- );
- } else {
- $this->view->message = array(
- 'status' => 'bad',
- 'title' => _t('damn'),
- 'body' => _t('update_problem', 'Cannot save the update script')
- );
- }
- } else {
- $this->view->message = array(
- 'status' => 'bad',
- 'title' => _t('damn'),
- 'body' => _t('no_update')
- );
- }
- } else {
+ if ($c_status !== 200) {
$this->view->message = array(
'status' => 'bad',
'title' => _t('damn'),
'body' => _t('update_server_not_found', FRESHRSS_UPDATE_WEBSITE)
);
+ return;
}
- curl_close($c);
+ $res_array = explode("\n", $result, 2);
+ $status = $res_array[0];
+ if (strpos($status, 'UPDATE') !== 0) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('no_update')
+ );
+
+ return;
+ }
+
+ $script = $res_array[1];
+ if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
+ $this->view->message = array(
+ 'status' => 'good',
+ 'title' => _t('ok'),
+ 'body' => _t('update_can_apply', _url('update', 'apply'))
+ );
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('update_problem', 'Cannot save the update script')
+ );
+ }
}
public function applyAction() {
diff --git a/constants.php b/constants.php
index a968b82f4..ba9c508dc 100644
--- a/constants.php
+++ b/constants.php
@@ -1,7 +1,7 @@
Date: Mon, 1 Sep 2014 20:58:05 -0400
Subject: Add average on repartition charts.
It needs some verification on the value used to calculate the averages.
---
app/Controllers/statsController.php | 3 ++
app/Models/StatsDAO.php | 62 +++++++++++++++++++++++++++++++++++++
app/views/stats/repartition.phtml | 48 ++++++++++++++++++++++++----
3 files changed, 107 insertions(+), 6 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php
index 98f46f0d2..000b41dd2 100644
--- a/app/Controllers/statsController.php
+++ b/app/Controllers/statsController.php
@@ -67,8 +67,11 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
$this->view->days = $statsDAO->getDays();
$this->view->months = $statsDAO->getMonths();
$this->view->repartitionHour = $statsDAO->calculateEntryRepartitionPerFeedPerHour($id);
+ $this->view->averageHour = $statsDAO->calculateEntryAveragePerFeedPerHour($id);
$this->view->repartitionDayOfWeek = $statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id);
+ $this->view->averageDayOfWeek = $statsDAO->calculateEntryAveragePerFeedPerDayOfWeek($id);
$this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id);
+ $this->view->averageMonth = $statsDAO->calculateEntryAveragePerFeedPerMonth($id);
}
public function firstAction() {
diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php
index 89be76a26..bd4271ba8 100644
--- a/app/Models/StatsDAO.php
+++ b/app/Models/StatsDAO.php
@@ -151,6 +151,68 @@ SQL;
return $this->convertToSerie($repartition);
}
+ /**
+ * Calculates the average number of article per hour per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerHour($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(1/24, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per day of week per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerDayOfWeek($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(7, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per month per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerMonth($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(30, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per feed
+ *
+ * @param float $period number used to divide the number of day in the period
+ * @param integer $feed id
+ * @return integer
+ */
+ protected function calculateEntryAveragePerFeedPerPeriod($period, $feed = null) {
+ if ($feed) {
+ $restrict = "WHERE e.id_feed = {$feed}";
+ } else {
+ $restrict = '';
+ }
+ $sql = <<prefix}entry AS e
+{$restrict}
+SQL;
+ $stm = $this->bd->prepare($sql);
+ $stm->execute();
+ $res = $stm->fetch(PDO::FETCH_NAMED);
+ $date_min = new \DateTime();
+ $date_min->setTimestamp($res['date_min']);
+ $date_max = new \DateTime();
+ $date_max->setTimestamp($res['date_max']);
+ $interval = $date_max->diff($date_min, true);
+
+ return round($res['count'] / ($interval->format('%a') / ($period)), 2);
+ }
+
/**
* Initialize an array for statistics depending on a range
*
diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml
index 9d2eb28e4..2331db78c 100644
--- a/app/views/stats/repartition.phtml
+++ b/app/views/stats/repartition.phtml
@@ -56,11 +56,22 @@ function initStats() {
return;
}
// Entry per hour
+ var avg_h = [];
+ for (var i = -1; i <= 24; i++) {
+ avg_h.push([i, averageHour?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerHour'),
- [repartitionHour ?>],
+ [{
+ data: repartitionHour ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_h,
+ lines: {show: true},
+ label: averageHour?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 23,
tickFormatter: function(x) {
var x = parseInt(x);
@@ -70,14 +81,26 @@ function initStats() {
max: 23.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per day of week
+ var avg_dow = [];
+ for (var i = -1; i <= 7; i++) {
+ avg_dow.push([i, averageDayOfWeek?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerDayOfWeek'),
- [repartitionDayOfWeek ?>],
+ [{
+ data: repartitionDayOfWeek ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_dow,
+ lines: {show: true},
+ label: averageDayOfWeek?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 6,
tickFormatter: function(x) {
var x = parseInt(x),
@@ -88,14 +111,26 @@ function initStats() {
max: 6.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per month
+ var avg_m = [];
+ for (var i = 0; i <= 13; i++) {
+ avg_m.push([i, averageMonth?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerMonth'),
- [repartitionMonth ?>],
+ [{
+ data: repartitionMonth ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_m,
+ lines: {show: true},
+ label: averageMonth?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 12,
tickFormatter: function(x) {
var x = parseInt(x),
@@ -106,6 +141,7 @@ function initStats() {
max: 12.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
--
cgit v1.2.3
From 48f91da2e5d7da4d8a4f11987116bfc8cbf049ca Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Mon, 8 Sep 2014 19:52:21 +0200
Subject: Check FRESHRSS_PATH is writable.
FRESHRSS_PATH needs to be writable before performing update.
---
app/Controllers/updateController.php | 41 ++++++++++++------------------------
app/i18n/en.php | 2 ++
app/i18n/fr.php | 2 ++
3 files changed, 18 insertions(+), 27 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 857d975b2..5d5ec3586 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -15,15 +15,19 @@ class FreshRSS_update_Controller extends Minz_ActionController {
}
public function indexAction() {
- if (file_exists(UPDATE_FILENAME)) {
+ if (file_exists(UPDATE_FILENAME) && !is_writable(FRESHRSS_PATH)) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('file_is_nok', FRESHRSS_PATH)
+ );
+ } elseif (file_exists(UPDATE_FILENAME)) {
// There is an update file to apply!
$this->view->message = array(
'status' => 'good',
'title' => _t('ok'),
'body' => _t('update_can_apply', _url('update', 'apply'))
);
-
- return;
}
}
@@ -33,11 +37,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
if (file_exists(UPDATE_FILENAME)) {
// There is already an update file to apply: we don't need to check
// the webserver!
- $this->view->message = array(
- 'status' => 'good',
- 'title' => _t('ok'),
- 'body' => _t('update_can_apply', _url('update', 'apply'))
- );
+ Minz_Request::forward(array('c' => 'update'));
return;
}
@@ -73,11 +73,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
$script = $res_array[1];
if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
- $this->view->message = array(
- 'status' => 'good',
- 'title' => _t('ok'),
- 'body' => _t('update_can_apply', _url('update', 'apply'))
- );
+ Minz_Request::forward(array('c' => 'update'));
} else {
$this->view->message = array(
'status' => 'bad',
@@ -88,7 +84,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
}
public function applyAction() {
- if (!file_exists(UPDATE_FILENAME)) {
+ if (!file_exists(UPDATE_FILENAME) || !is_writable(FRESHRSS_PATH)) {
Minz_Request::forward(array('c' => 'update'), true);
}
@@ -104,21 +100,12 @@ class FreshRSS_update_Controller extends Minz_ActionController {
if ($res === true) {
@unlink(UPDATE_FILENAME);
- // TODO: record last update
+ // TODO: record last update_finished
- Minz_Session::_param('notification', array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('update_finished')
- ));
-
- Minz_Request::forward(array(), true);
+ Minz_Request::good(_t('update_finished'));
} else {
- Minz_Session::_param('notification', array(
- 'type' => 'bad',
- 'content' => Minz_Translate::t('update_problem', $res)
- ));
-
- Minz_Request::forward(array('c' => 'update'), true);
+ Minz_Request::bad(_t('update_problem', $res),
+ array('c' => 'update', 'a' => 'index'));
}
}
}
diff --git a/app/i18n/en.php b/app/i18n/en.php
index 95356af2c..c5911cde7 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -152,6 +152,8 @@ return array (
'public' => 'Public',
'invalid_login' => 'Login is invalid',
+ 'file_is_nok' => 'Check permissions on %s directory. HTTP server must have rights to write into.',
+
// VIEWS
'save' => 'Save',
'delete' => 'Delete',
diff --git a/app/i18n/fr.php b/app/i18n/fr.php
index 8437e872e..789a0bb98 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -152,6 +152,8 @@ return array (
'public' => 'Public',
'invalid_login' => 'L’identifiant est invalide !',
+ 'file_is_nok' => 'Veuillez vérifier les droits sur le répertoire %s . Le serveur HTTP doit être capable d’écrire dedans.',
+
// VIEWS
'save' => 'Enregistrer',
'delete' => 'Supprimer',
--
cgit v1.2.3
From d59eebf5423afb94ff68550aa9218674889ab4ad Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Mon, 8 Sep 2014 20:07:09 +0200
Subject: Add data/last_update.txt
Remember last update timestamp.
---
app/Controllers/updateController.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 5d5ec3586..5424792f4 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -11,7 +11,11 @@ class FreshRSS_update_Controller extends Minz_ActionController {
}
Minz_View::prependTitle(_t('update_system') . ' · ');
- $this->view->last_update_time = 'unknown'; // TODO
+ $this->view->last_update_time = 'unknown';
+ $timestamp = (int)@file_get_contents(DATA_PATH . '/last_update.txt');
+ if (is_numeric($timestamp) && $timestamp > 0) {
+ $this->view->last_update_time = timestamptodate($timestamp);
+ }
}
public function indexAction() {
@@ -99,8 +103,7 @@ class FreshRSS_update_Controller extends Minz_ActionController {
if ($res === true) {
@unlink(UPDATE_FILENAME);
-
- // TODO: record last update_finished
+ @file_put_contents(DATA_PATH . '/last_update.txt', time());
Minz_Request::good(_t('update_finished'));
} else {
--
cgit v1.2.3
From 213bc2b9ddef88fd9e3cb50ac0893742f5fdd101 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Fri, 12 Sep 2014 21:07:53 +0200
Subject: Check if update has been done during last minute
Cancel check action if update has been done during last hour.
---
app/Controllers/updateController.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 5424792f4..ec6778d51 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -38,7 +38,11 @@ class FreshRSS_update_Controller extends Minz_ActionController {
public function checkAction() {
$this->view->change_view('update', 'index');
- if (file_exists(UPDATE_FILENAME)) {
+ // Get the last update. If already check during the last hour, do nothing.
+ $last_update = (int)@file_get_contents(DATA_PATH . '/last_update.txt');
+ $check_last_hour = (time() - 3600) <= $last_update;
+
+ if (file_exists(UPDATE_FILENAME) || $check_last_hour) {
// There is already an update file to apply: we don't need to check
// the webserver!
Minz_Request::forward(array('c' => 'update'));
--
cgit v1.2.3
From 098f5e6d747cf442b72f75a22a9ce43d36605d65 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Fri, 12 Sep 2014 21:10:45 +0200
Subject: Log error if update.freshrss.org is unreachable
---
app/Controllers/updateController.php | 5 +++++
1 file changed, 5 insertions(+)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index ec6778d51..4c1dd002c 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -56,9 +56,14 @@ class FreshRSS_update_Controller extends Minz_ActionController {
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
$result = curl_exec($c);
$c_status = curl_getinfo($c, CURLINFO_HTTP_CODE);
+ $c_error = curl_error($c);
curl_close($c);
if ($c_status !== 200) {
+ Minz_Log::error(
+ 'Error during update (HTTP code ' . $c_status . '): ' . $c_error
+ );
+
$this->view->message = array(
'status' => 'bad',
'title' => _t('damn'),
--
cgit v1.2.3
From 3fa726a81eb1889f29115cf4d8349d15f68b03f9 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Fri, 12 Sep 2014 21:34:42 +0200
Subject: Import all .json files
Before, only feed_*.json and *starred*.json was imported. Now, all
*.json files are imported.
---
app/Controllers/importExportController.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 5adf3878a..07c097c4a 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -119,8 +119,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} elseif (substr_compare($filename, '.json', -5) === 0 &&
strpos($filename, 'starred') !== false) {
return 'json_starred';
- } elseif (substr_compare($filename, '.json', -5) === 0 &&
- strpos($filename, 'feed_') === 0) {
+ } elseif (substr_compare($filename, '.json', -5) === 0) {
return 'json_feed';
} else {
return 'unknown';
@@ -238,6 +237,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
strpos($article_object['id'], 'com.google') !== false
);
+
$error = false;
foreach ($article_object['items'] as $item) {
$feed = $this->addFeedArticles($item['origin'], $google_compliant);
@@ -263,7 +263,10 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
);
$entry->_tags($tags);
- //FIME: Use entryDAO->addEntryPrepare(). Do not call entryDAO->listLastGuidsByFeed() for each entry. Consider using a transaction.
+ // FIXME
+ // Use entryDAO->addEntryPrepare().
+ // Do not call entryDAO->listLastGuidsByFeed() for each entry.
+ // Consider using a transaction.
$id = $this->entryDAO->addEntryObject(
$entry, $this->view->conf, $feed->keepHistory()
);
--
cgit v1.2.3
From 021457657186f019a9227e7a2a0b32148ffe4002 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Fri, 12 Sep 2014 21:46:37 +0200
Subject: FIXME (import/export) Use entryDAO addEntryPrepare
---
app/Controllers/importExportController.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 07c097c4a..e7d364efd 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -239,6 +239,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$error = false;
+ $prepared_statement = $this->entryDAO->addEntryPrepare();
foreach ($article_object['items'] as $item) {
$feed = $this->addFeedArticles($item['origin'], $google_compliant);
if (is_null($feed)) {
@@ -261,15 +262,14 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$item[$key_content]['content'], $item['alternate'][0]['href'],
$item['published'], $is_read, $starred
);
+ $entry->_id(min(time(), $entry->date(true)) . uSecString());
$entry->_tags($tags);
// FIXME
- // Use entryDAO->addEntryPrepare().
// Do not call entryDAO->listLastGuidsByFeed() for each entry.
// Consider using a transaction.
- $id = $this->entryDAO->addEntryObject(
- $entry, $this->view->conf, $feed->keepHistory()
- );
+ $values = $entry->toArray();
+ $id = $this->entryDAO->addEntry($values, $prepared_statement);
if (!$error && ($id === false)) {
$error = true;
--
cgit v1.2.3
From b7b05ca3cefbb35a5174da4d4d734107f19c24a1 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Mon, 15 Sep 2014 15:34:56 +0200
Subject: Import/Export: use transactions
List of articles must be iterated twice since feeds must be in DB before
using transaction for articles. It may be improved?
See https://github.com/marienfressinaud/FreshRSS/issues/591
---
app/Controllers/importExportController.php | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index e7d364efd..a44991335 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -237,16 +237,28 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
strpos($article_object['id'], 'com.google') !== false
);
-
$error = false;
- $prepared_statement = $this->entryDAO->addEntryPrepare();
+ $article_to_feed = array();
+
+ // First, we check feeds of articles are in DB (and add them if needed).
foreach ($article_object['items'] as $item) {
$feed = $this->addFeedArticles($item['origin'], $google_compliant);
if (is_null($feed)) {
$error = true;
+ } else {
+ $article_to_feed[$item['id']] = $feed->id();
+ }
+ }
+
+ // Then, articles are imported.
+ $prepared_statement = $this->entryDAO->addEntryPrepare();
+ $this->entryDAO->beginTransaction();
+ foreach ($article_object['items'] as $item) {
+ if (!isset($article_to_feed[$item['id']])) {
continue;
}
+ $feed_id = $article_to_feed[$item['id']];
$author = isset($item['author']) ? $item['author'] : '';
$key_content = ($google_compliant && !isset($item['content'])) ?
'summary' : 'content';
@@ -258,16 +270,13 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
$entry = new FreshRSS_Entry(
- $feed->id(), $item['id'], $item['title'], $author,
+ $feed_id, $item['id'], $item['title'], $author,
$item[$key_content]['content'], $item['alternate'][0]['href'],
$item['published'], $is_read, $starred
);
$entry->_id(min(time(), $entry->date(true)) . uSecString());
$entry->_tags($tags);
- // FIXME
- // Do not call entryDAO->listLastGuidsByFeed() for each entry.
- // Consider using a transaction.
$values = $entry->toArray();
$id = $this->entryDAO->addEntry($values, $prepared_statement);
@@ -275,6 +284,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$error = true;
}
}
+ $this->entryDAO->commit();
return $error;
}
--
cgit v1.2.3
From 69c7c1aa48d42656f73c724d7e9062ca19914133 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Mon, 15 Sep 2014 15:55:35 +0200
Subject: Change loading of base-theme css
If metadata.json indicates it should use "_template.css" or "_base.css",
base-theme/template|base.css is used. It facilitates theme maintenance.
---
app/Controllers/importExportController.php | 1 -
app/FreshRSS.php | 13 +-
p/themes/Dark/metadata.json | 2 +-
p/themes/Dark/template.css | 698 -----------------------------
p/themes/Flat/metadata.json | 2 +-
p/themes/Flat/template.css | 698 -----------------------------
p/themes/Origine/metadata.json | 2 +-
p/themes/Origine/template.css | 698 -----------------------------
p/themes/Screwdriver/metadata.json | 2 +-
p/themes/Screwdriver/template.css | 698 -----------------------------
10 files changed, 15 insertions(+), 2799 deletions(-)
delete mode 100644 p/themes/Dark/template.css
delete mode 100644 p/themes/Flat/template.css
delete mode 100644 p/themes/Origine/template.css
delete mode 100644 p/themes/Screwdriver/template.css
(limited to 'app/Controllers')
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index a44991335..f329766b8 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -109,7 +109,6 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
// A *very* basic guess file type function. Only based on filename
// That's could be improved but should be enough, at least for a first
// implementation.
- // TODO: improve this function?
if (substr_compare($filename, '.zip', -4) === 0) {
return 'zip';
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index cf6390f68..6cca27f78 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -139,11 +139,20 @@ class FreshRSS extends Minz_FrontController {
}
}
- private function loadStylesAndScripts ($loginOk) {
+ private function loadStylesAndScripts($loginOk) {
$theme = FreshRSS_Themes::load($this->conf->theme);
if ($theme) {
foreach($theme['files'] as $file) {
- Minz_View::appendStyle (Minz_Url::display ('/themes/' . $theme['id'] . '/' . $file . '?' . @filemtime(PUBLIC_PATH . '/themes/' . $theme['id'] . '/' . $file)));
+ $theme_id = $theme['id'];
+ $filename = $file;
+ if ($file[0] == '_') {
+ $theme_id = 'base-theme';
+ $filename = substr($file, 1);
+ }
+ $filetime = @filemtime(PUBLIC_PATH . '/themes/' . $theme_id . '/' . $filename);
+ Minz_View::appendStyle(Minz_Url::display(
+ '/themes/' . $theme_id . '/' . $filename . '?' . $filetime
+ ));
}
}
diff --git a/p/themes/Dark/metadata.json b/p/themes/Dark/metadata.json
index 5eb3a05e8..bdc068c2e 100644
--- a/p/themes/Dark/metadata.json
+++ b/p/themes/Dark/metadata.json
@@ -3,5 +3,5 @@
"author": "AD",
"description": "Le coté obscur du thème “Origine”",
"version": 0.2,
- "files": ["template.css", "dark.css"]
+ "files": ["_template.css", "dark.css"]
}
diff --git a/p/themes/Dark/template.css b/p/themes/Dark/template.css
deleted file mode 100644
index 466ec4603..000000000
--- a/p/themes/Dark/template.css
+++ /dev/null
@@ -1,698 +0,0 @@
-@charset "UTF-8";
-
-/*=== GENERAL */
-/*============*/
-html, body {
- margin: 0;
- padding: 0;
- font-size: 100%;
-}
-
-/*=== Links */
-a {
- text-decoration: none;
-}
-a:hover {
- text-decoration: underline;
-}
-
-/*=== Lists */
-ul, ol, dd {
- margin: 0;
- padding: 0;
-}
-
-/*=== Titles */
-h1 {
- margin: 0.6em 0 0.3em;
- font-size: 1.5em;
- line-height: 1.6em;
-}
-h2 {
- margin: 0.5em 0 0.25em;
- font-size: 1.3em;
- line-height: 2em;
-}
-h3 {
- margin: 0.5em 0 0.25em;
- font-size: 1.1em;
- line-height: 2em;
-}
-
-/*=== Paragraphs */
-p {
- margin: 1em 0 0.5em;
- font-size: 1em;
-}
-
-/*=== Images */
-img {
- height: auto;
- max-width: 100%;
-}
-img.favicon {
- height: 16px;
- width: 16px;
- vertical-align: middle;
-}
-
-/*=== Videos */
-iframe, embed, object, video {
- max-width: 100%;
-}
-
-/*=== Forms */
-legend {
- display: block;
- width: 100%;
- clear: both;
-}
-label {
- display: block;
-}
-input {
- width: 180px;
-}
-textarea {
- width: 300px;
-}
-input, select, textarea {
- display: inline-block;
- max-width: 100%;
-}
-input[type="radio"],
-input[type="checkbox"] {
- width: 15px !important;
- min-height: 15px !important;
-}
-input.extend:focus {
- width: 300px;
-}
-
-/*=== COMPONENTS */
-/*===============*/
-/*=== Forms */
-.form-group:after {
- content: "";
- display: block;
- clear: both;
-}
-.form-group.form-actions {
- min-width: 250px;
-}
-.form-group .group-name {
- display: block;
- float: left;
- width: 200px;
-}
-.form-group .group-controls {
- min-width: 250px;
- margin: 0 0 0 220px;
-}
-.form-group .group-controls .control {
- display: block;
-}
-
-/*=== Buttons */
-.stick {
- display: inline-block;
- white-space: nowrap;
-}
-.btn,
-a.btn {
- display: inline-block;
- cursor: pointer;
- overflow: hidden;
-}
-.btn-important {
- font-weight: bold;
-}
-
-/*=== Navigation */
-.nav-list .nav-header,
-.nav-list .item {
- display: block;
-}
-.nav-list .item,
-.nav-list .item > a {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.nav-head {
- display: block;
-}
-.nav-head .item {
- display: inline-block;
-}
-
-/*=== Horizontal-list */
-.horizontal-list {
- display: table;
- table-layout: fixed;
- width: 100%;
-}
-.horizontal-list .item {
- display: table-cell;
-}
-
-/*=== Dropdown */
-.dropdown {
- position: relative;
- display: inline-block;
-}
-.dropdown-target {
- display: none;
-}
-.dropdown-menu {
- display: none;
- min-width: 200px;
- margin: 0;
- position: absolute;
- right: 0;
- background: #fff;
- border: 1px solid #aaa;
-}
-.dropdown-header {
- display: block;
-}
-.dropdown-menu > .item {
- display: block;
-}
-.dropdown-menu > .item > a,
-.dropdown-menu > .item > span {
- display: block;
-}
-.dropdown-menu > .item[aria-checked="true"] > a:before {
- content: '✓';
-}
-.dropdown-menu .input {
- display: block;
-}
-.dropdown-menu .input select,
-.dropdown-menu .input input {
- display: block;
- max-width: 95%;
-}
-.dropdown-target:target ~ .dropdown-menu {
- display: block;
- z-index: 10;
-}
-.dropdown-close {
- display: inline;
-}
-.dropdown-close a {
- font-size: 0;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
- z-index: -10;
-}
-.separator {
- display: block;
- height: 0;
- border-bottom: 1px solid #aaa;
-}
-
-/*=== Alerts */
-.alert {
- display: block;
- width: 90%;
-}
-.group-controls .alert {
- width: 100%
-}
-.alert-head {
- margin: 0;
- font-weight: bold;
-}
-.alert ul {
- margin: 5px 20px;
-}
-
-/*=== Icons */
-.icon {
- display: inline-block;
- width: 16px;
- height: 16px;
- vertical-align: middle;
- line-height: 16px;
-}
-
-/*=== Pagination */
-.pagination {
- display: table;
- width: 100%;
- margin: 0;
- padding: 0;
- table-layout: fixed;
-}
-.pagination .item {
- display: table-cell;
-}
-.pagination .pager-first,
-.pagination .pager-previous,
-.pagination .pager-next,
-.pagination .pager-last {
- width: 100px;
-}
-
-/*=== STRUCTURE */
-/*===============*/
-/*=== Header */
-.header {
- display: table;
- width: 100%;
- table-layout: fixed;
-}
-.header > .item {
- display: table-cell;
-}
-.header > .item.title {
- width: 250px;
- white-space: nowrap;
-}
-.header > .item.title h1 {
- display: inline-block;
-}
-.header > .item.title .logo {
- display: inline-block;
- height: 32px;
- width: 32px;
- vertical-align: middle;
-}
-.header > .item.configure {
- width: 100px;
-}
-
-/*=== Body */
-#global {
- display: table;
- width: 100%;
- height: 100%;
- table-layout: fixed;
-}
-.aside {
- display: table-cell;
- height: 100%;
- width: 250px;
- vertical-align: top;
-}
-.aside.aside_flux {
- background: #fff;
-}
-
-/*=== Aside main page (categories) */
-.categories {
- list-style: none;
- margin: 0;
-}
-.state_unread li:not(.active)[data-unread="0"] {
- display: none;
-}
-.category {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.category .btn:not([data-unread="0"]):after {
- content: attr(data-unread);
-}
-
-/*=== Aside main page (feeds) */
-.categories .feeds {
- width: 100%;
- list-style: none;
-}
-.categories .feeds:not(.active) {
- display: none;
-}
-.categories .feeds .feed {
- display: inline-block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-.categories .feeds .feed:not([data-unread="0"]):before {
- content: "(" attr(data-unread) ") ";
-}
-.categories .feeds .dropdown-menu {
- left: 0;
-}
-.categories .feeds .item .dropdown-toggle > .icon {
- visibility: hidden;
- cursor: pointer;
- vertical-align: top;
-}
-.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon,
-.categories .feeds .item:hover .dropdown-toggle > .icon,
-.categories .feeds .item.active .dropdown-toggle > .icon {
- visibility: visible;
-}
-
-/*=== New article notification */
-#new-article {
- display: none;
-}
-#new-article > a {
- display: block;
-}
-
-/*=== Day indication */
-.day .name {
- position: absolute;
- right: 0;
- width: 50%;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-/*=== Feed article header and footer */
-.flux_header {
- position: relative;
-}
-.flux .item {
- line-height: 40px;
- white-space: nowrap;
-}
-.flux .item.manage,
-.flux .item.link {
- width: 40px;
- text-align: center;
-}
-.flux .item.website {
- width: 200px;
-}
-.flux.not_read .item.title,
-.flux.current .item.title {
- font-weight: bold;
-}
-.flux:not(.current):hover .item.title {
- position: absolute;
- max-width: calc(100% - 320px);
- background: #fff;
-}
-.flux .item.title a {
- color: #000;
- text-decoration: none;
-}
-.flux .item.date {
- width: 145px;
- text-align: right;
-}
-.flux .item > a {
- display: block;
-}
-.flux .item > a {
- display: block;
- text-decoration: none;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-.flux .item.share > a {
- display: list-item;
- list-style-position: inside;
- list-style-type: decimal;
-}
-
-/*=== Feed article content */
-.hide_posts > .flux:not(.active) > .flux_content {
- display: none;
-}
-.content {
- min-height: 20em;
- margin: auto;
- line-height: 1.7em;
- word-wrap: break-word;
-}
-.content.large {
- max-width: 1000px;
-}
-.content.medium {
- max-width: 800px;
-}
-.content.thin {
- max-width: 550px;
-}
-.content ul,
-.content ol,
-.content dd {
- margin: 0 0 0 15px;
- padding: 0 0 5px 15px;
-}
-.content pre {
- overflow: auto;
-}
-
-/*=== Notification and actualize notification */
-.notification {
- position: absolute;
- top: 1em;
- left: 25%; right: 25%;
- z-index: 10;
- background: #fff;
- border: 1px solid #aaa;
-}
-.notification.closed {
- display: none;
-}
-.notification a.close {
- position: absolute;
- top: 0; bottom: 0;
- right: 0;
- display: inline-block;
-}
-
-#actualizeProgress {
- position: fixed;
-}
-#actualizeProgress progress {
- max-width: 100%;
- vertical-align: middle;
-}
-#actualizeProgress .progress {
- vertical-align: middle;
-}
-
-/*=== Navigation menu (for articles) */
-#nav_entries {
- position: fixed;
- bottom: 0; left: 0;
- display: table;
- width: 250px;
- background: #fff;
- table-layout: fixed;
-}
-#nav_entries .item {
- display: table-cell;
- width: 30%;
-}
-#nav_entries a {
- display: block;
-}
-
-/*=== "Load more" part */
-#load_more {
- min-height: 40px;
-}
-.loading {
- background: url("loader.gif") center center no-repeat;
- font-size: 0;
-}
-#bigMarkAsRead {
- display: block;
- padding: 3em 0;
- text-align: center;
-}
-.bigTick {
- font-size: 7em;
- line-height: 1.6em;
-}
-
-/*=== Statistiques */
-.stat > table {
- width: 100%;
-}
-
-/*=== GLOBAL VIEW */
-/*================*/
-/*=== Category boxes */
-#stream.global .box-category {
- display: inline-block;
- width: 19em;
- max-width: 95%;
- margin: 20px 10px;
- border: 1px solid #ccc;
- vertical-align: top;
-}
-#stream.global .category {
- width: 100%;
-}
-#stream.global .btn {
- display: block;
-}
-#stream.global .box-category .feeds {
- display: block;
- overflow: auto;
-}
-#stream.global .box-category .feed {
- width: 19em;
- max-width: 90%;
-}
-
-/*=== Panel */
-#overlay {
- display: none;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- background: rgba(0, 0, 0, 0.9);
-}
-#panel {
- display: none;
- position: fixed;
- top: 1em; bottom: 1em;
- left: 2em; right: 2em;
- overflow: auto;
- background: #fff;
-}
-#panel .close {
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
-}
-#panel .close img {
- display: none;
-}
-
-/*=== DIVERS */
-/*===========*/
-.nav-login,
-.nav_menu .search,
-.nav_menu .toggle_aside {
- display: none;
-}
-
-.aside .toggle_aside {
- position: absolute;
- right: 0;
- display: none;
- width: 30px;
- height: 30px;
- line-height: 30px;
- text-align: center;
-}
-
-/*=== MOBILE */
-/*===========*/
-@media(max-width: 840px) {
- .header,
- .aside .btn-important,
- .aside .feeds .dropdown,
- .flux_header .item.website span,
- .item.date, .day .date,
- .dropdown-menu > .no-mobile,
- .no-mobile {
- display: none;
- }
- .nav-login {
- display: block;
- }
- .nav_menu .toggle_aside,
- .aside .toggle_aside,
- .nav_menu .search,
- #panel .close img {
- display: inline-block;
- }
-
- .aside {
- position: fixed;
- top: 0; bottom: 0;
- left: 0;
- width: 0;
- overflow: hidden;
- z-index: 100;
- }
- .aside:target {
- width: 90%;
- overflow: auto;
- }
- .aside .categories {
- margin: 10px 0 75px;
- }
-
- .flux_header .item.website {
- width: 40px;
- }
-
- .flux:not(.current):hover .item.title {
- position: relative;
- width: auto;
- white-space: nowrap;
- }
-
- .notification {
- top: 0;
- left: 0;
- right: 0;
- }
-
- #nav_entries {
- width: 100%;
- }
-
- #stream.global .box-category {
- margin: 10px 0;
- }
-
- #panel {
- top: 0; bottom: 0;
- left: 0; right: 0;
- }
- #panel .close {
- top: 0; right: 0;
- left: auto; bottom: auto;
- display: inline-block;
- width: 30px;
- height: 30px;
- }
-}
-
-/*=== PRINTER */
-/*============*/
-@media print {
- .header, .aside,
- .nav_menu, .day,
- .flux_header,
- .flux_content .bottom,
- .pagination,
- #nav_entries {
- display: none;
- }
- html, body {
- background: #fff;
- color: #000;
- font-family: Serif;
- }
- #global,
- .flux_content {
- display: block !important;
- }
- .flux_content .content {
- width: 100% !important;
- }
- .flux_content .content a {
- color: #000;
- }
- .flux_content .content a:after {
- content: " [" attr(href) "] ";
- font-style: italic;
- }
-}
diff --git a/p/themes/Flat/metadata.json b/p/themes/Flat/metadata.json
index 182c82470..3afdc98af 100644
--- a/p/themes/Flat/metadata.json
+++ b/p/themes/Flat/metadata.json
@@ -3,5 +3,5 @@
"author": "Marien Fressinaud",
"description": "Thème plat pour FreshRSS",
"version": 0.2,
- "files": ["template.css", "flat.css"]
+ "files": ["_template.css", "flat.css"]
}
\ No newline at end of file
diff --git a/p/themes/Flat/template.css b/p/themes/Flat/template.css
deleted file mode 100644
index 466ec4603..000000000
--- a/p/themes/Flat/template.css
+++ /dev/null
@@ -1,698 +0,0 @@
-@charset "UTF-8";
-
-/*=== GENERAL */
-/*============*/
-html, body {
- margin: 0;
- padding: 0;
- font-size: 100%;
-}
-
-/*=== Links */
-a {
- text-decoration: none;
-}
-a:hover {
- text-decoration: underline;
-}
-
-/*=== Lists */
-ul, ol, dd {
- margin: 0;
- padding: 0;
-}
-
-/*=== Titles */
-h1 {
- margin: 0.6em 0 0.3em;
- font-size: 1.5em;
- line-height: 1.6em;
-}
-h2 {
- margin: 0.5em 0 0.25em;
- font-size: 1.3em;
- line-height: 2em;
-}
-h3 {
- margin: 0.5em 0 0.25em;
- font-size: 1.1em;
- line-height: 2em;
-}
-
-/*=== Paragraphs */
-p {
- margin: 1em 0 0.5em;
- font-size: 1em;
-}
-
-/*=== Images */
-img {
- height: auto;
- max-width: 100%;
-}
-img.favicon {
- height: 16px;
- width: 16px;
- vertical-align: middle;
-}
-
-/*=== Videos */
-iframe, embed, object, video {
- max-width: 100%;
-}
-
-/*=== Forms */
-legend {
- display: block;
- width: 100%;
- clear: both;
-}
-label {
- display: block;
-}
-input {
- width: 180px;
-}
-textarea {
- width: 300px;
-}
-input, select, textarea {
- display: inline-block;
- max-width: 100%;
-}
-input[type="radio"],
-input[type="checkbox"] {
- width: 15px !important;
- min-height: 15px !important;
-}
-input.extend:focus {
- width: 300px;
-}
-
-/*=== COMPONENTS */
-/*===============*/
-/*=== Forms */
-.form-group:after {
- content: "";
- display: block;
- clear: both;
-}
-.form-group.form-actions {
- min-width: 250px;
-}
-.form-group .group-name {
- display: block;
- float: left;
- width: 200px;
-}
-.form-group .group-controls {
- min-width: 250px;
- margin: 0 0 0 220px;
-}
-.form-group .group-controls .control {
- display: block;
-}
-
-/*=== Buttons */
-.stick {
- display: inline-block;
- white-space: nowrap;
-}
-.btn,
-a.btn {
- display: inline-block;
- cursor: pointer;
- overflow: hidden;
-}
-.btn-important {
- font-weight: bold;
-}
-
-/*=== Navigation */
-.nav-list .nav-header,
-.nav-list .item {
- display: block;
-}
-.nav-list .item,
-.nav-list .item > a {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.nav-head {
- display: block;
-}
-.nav-head .item {
- display: inline-block;
-}
-
-/*=== Horizontal-list */
-.horizontal-list {
- display: table;
- table-layout: fixed;
- width: 100%;
-}
-.horizontal-list .item {
- display: table-cell;
-}
-
-/*=== Dropdown */
-.dropdown {
- position: relative;
- display: inline-block;
-}
-.dropdown-target {
- display: none;
-}
-.dropdown-menu {
- display: none;
- min-width: 200px;
- margin: 0;
- position: absolute;
- right: 0;
- background: #fff;
- border: 1px solid #aaa;
-}
-.dropdown-header {
- display: block;
-}
-.dropdown-menu > .item {
- display: block;
-}
-.dropdown-menu > .item > a,
-.dropdown-menu > .item > span {
- display: block;
-}
-.dropdown-menu > .item[aria-checked="true"] > a:before {
- content: '✓';
-}
-.dropdown-menu .input {
- display: block;
-}
-.dropdown-menu .input select,
-.dropdown-menu .input input {
- display: block;
- max-width: 95%;
-}
-.dropdown-target:target ~ .dropdown-menu {
- display: block;
- z-index: 10;
-}
-.dropdown-close {
- display: inline;
-}
-.dropdown-close a {
- font-size: 0;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
- z-index: -10;
-}
-.separator {
- display: block;
- height: 0;
- border-bottom: 1px solid #aaa;
-}
-
-/*=== Alerts */
-.alert {
- display: block;
- width: 90%;
-}
-.group-controls .alert {
- width: 100%
-}
-.alert-head {
- margin: 0;
- font-weight: bold;
-}
-.alert ul {
- margin: 5px 20px;
-}
-
-/*=== Icons */
-.icon {
- display: inline-block;
- width: 16px;
- height: 16px;
- vertical-align: middle;
- line-height: 16px;
-}
-
-/*=== Pagination */
-.pagination {
- display: table;
- width: 100%;
- margin: 0;
- padding: 0;
- table-layout: fixed;
-}
-.pagination .item {
- display: table-cell;
-}
-.pagination .pager-first,
-.pagination .pager-previous,
-.pagination .pager-next,
-.pagination .pager-last {
- width: 100px;
-}
-
-/*=== STRUCTURE */
-/*===============*/
-/*=== Header */
-.header {
- display: table;
- width: 100%;
- table-layout: fixed;
-}
-.header > .item {
- display: table-cell;
-}
-.header > .item.title {
- width: 250px;
- white-space: nowrap;
-}
-.header > .item.title h1 {
- display: inline-block;
-}
-.header > .item.title .logo {
- display: inline-block;
- height: 32px;
- width: 32px;
- vertical-align: middle;
-}
-.header > .item.configure {
- width: 100px;
-}
-
-/*=== Body */
-#global {
- display: table;
- width: 100%;
- height: 100%;
- table-layout: fixed;
-}
-.aside {
- display: table-cell;
- height: 100%;
- width: 250px;
- vertical-align: top;
-}
-.aside.aside_flux {
- background: #fff;
-}
-
-/*=== Aside main page (categories) */
-.categories {
- list-style: none;
- margin: 0;
-}
-.state_unread li:not(.active)[data-unread="0"] {
- display: none;
-}
-.category {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.category .btn:not([data-unread="0"]):after {
- content: attr(data-unread);
-}
-
-/*=== Aside main page (feeds) */
-.categories .feeds {
- width: 100%;
- list-style: none;
-}
-.categories .feeds:not(.active) {
- display: none;
-}
-.categories .feeds .feed {
- display: inline-block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-.categories .feeds .feed:not([data-unread="0"]):before {
- content: "(" attr(data-unread) ") ";
-}
-.categories .feeds .dropdown-menu {
- left: 0;
-}
-.categories .feeds .item .dropdown-toggle > .icon {
- visibility: hidden;
- cursor: pointer;
- vertical-align: top;
-}
-.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon,
-.categories .feeds .item:hover .dropdown-toggle > .icon,
-.categories .feeds .item.active .dropdown-toggle > .icon {
- visibility: visible;
-}
-
-/*=== New article notification */
-#new-article {
- display: none;
-}
-#new-article > a {
- display: block;
-}
-
-/*=== Day indication */
-.day .name {
- position: absolute;
- right: 0;
- width: 50%;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-/*=== Feed article header and footer */
-.flux_header {
- position: relative;
-}
-.flux .item {
- line-height: 40px;
- white-space: nowrap;
-}
-.flux .item.manage,
-.flux .item.link {
- width: 40px;
- text-align: center;
-}
-.flux .item.website {
- width: 200px;
-}
-.flux.not_read .item.title,
-.flux.current .item.title {
- font-weight: bold;
-}
-.flux:not(.current):hover .item.title {
- position: absolute;
- max-width: calc(100% - 320px);
- background: #fff;
-}
-.flux .item.title a {
- color: #000;
- text-decoration: none;
-}
-.flux .item.date {
- width: 145px;
- text-align: right;
-}
-.flux .item > a {
- display: block;
-}
-.flux .item > a {
- display: block;
- text-decoration: none;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-.flux .item.share > a {
- display: list-item;
- list-style-position: inside;
- list-style-type: decimal;
-}
-
-/*=== Feed article content */
-.hide_posts > .flux:not(.active) > .flux_content {
- display: none;
-}
-.content {
- min-height: 20em;
- margin: auto;
- line-height: 1.7em;
- word-wrap: break-word;
-}
-.content.large {
- max-width: 1000px;
-}
-.content.medium {
- max-width: 800px;
-}
-.content.thin {
- max-width: 550px;
-}
-.content ul,
-.content ol,
-.content dd {
- margin: 0 0 0 15px;
- padding: 0 0 5px 15px;
-}
-.content pre {
- overflow: auto;
-}
-
-/*=== Notification and actualize notification */
-.notification {
- position: absolute;
- top: 1em;
- left: 25%; right: 25%;
- z-index: 10;
- background: #fff;
- border: 1px solid #aaa;
-}
-.notification.closed {
- display: none;
-}
-.notification a.close {
- position: absolute;
- top: 0; bottom: 0;
- right: 0;
- display: inline-block;
-}
-
-#actualizeProgress {
- position: fixed;
-}
-#actualizeProgress progress {
- max-width: 100%;
- vertical-align: middle;
-}
-#actualizeProgress .progress {
- vertical-align: middle;
-}
-
-/*=== Navigation menu (for articles) */
-#nav_entries {
- position: fixed;
- bottom: 0; left: 0;
- display: table;
- width: 250px;
- background: #fff;
- table-layout: fixed;
-}
-#nav_entries .item {
- display: table-cell;
- width: 30%;
-}
-#nav_entries a {
- display: block;
-}
-
-/*=== "Load more" part */
-#load_more {
- min-height: 40px;
-}
-.loading {
- background: url("loader.gif") center center no-repeat;
- font-size: 0;
-}
-#bigMarkAsRead {
- display: block;
- padding: 3em 0;
- text-align: center;
-}
-.bigTick {
- font-size: 7em;
- line-height: 1.6em;
-}
-
-/*=== Statistiques */
-.stat > table {
- width: 100%;
-}
-
-/*=== GLOBAL VIEW */
-/*================*/
-/*=== Category boxes */
-#stream.global .box-category {
- display: inline-block;
- width: 19em;
- max-width: 95%;
- margin: 20px 10px;
- border: 1px solid #ccc;
- vertical-align: top;
-}
-#stream.global .category {
- width: 100%;
-}
-#stream.global .btn {
- display: block;
-}
-#stream.global .box-category .feeds {
- display: block;
- overflow: auto;
-}
-#stream.global .box-category .feed {
- width: 19em;
- max-width: 90%;
-}
-
-/*=== Panel */
-#overlay {
- display: none;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- background: rgba(0, 0, 0, 0.9);
-}
-#panel {
- display: none;
- position: fixed;
- top: 1em; bottom: 1em;
- left: 2em; right: 2em;
- overflow: auto;
- background: #fff;
-}
-#panel .close {
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
-}
-#panel .close img {
- display: none;
-}
-
-/*=== DIVERS */
-/*===========*/
-.nav-login,
-.nav_menu .search,
-.nav_menu .toggle_aside {
- display: none;
-}
-
-.aside .toggle_aside {
- position: absolute;
- right: 0;
- display: none;
- width: 30px;
- height: 30px;
- line-height: 30px;
- text-align: center;
-}
-
-/*=== MOBILE */
-/*===========*/
-@media(max-width: 840px) {
- .header,
- .aside .btn-important,
- .aside .feeds .dropdown,
- .flux_header .item.website span,
- .item.date, .day .date,
- .dropdown-menu > .no-mobile,
- .no-mobile {
- display: none;
- }
- .nav-login {
- display: block;
- }
- .nav_menu .toggle_aside,
- .aside .toggle_aside,
- .nav_menu .search,
- #panel .close img {
- display: inline-block;
- }
-
- .aside {
- position: fixed;
- top: 0; bottom: 0;
- left: 0;
- width: 0;
- overflow: hidden;
- z-index: 100;
- }
- .aside:target {
- width: 90%;
- overflow: auto;
- }
- .aside .categories {
- margin: 10px 0 75px;
- }
-
- .flux_header .item.website {
- width: 40px;
- }
-
- .flux:not(.current):hover .item.title {
- position: relative;
- width: auto;
- white-space: nowrap;
- }
-
- .notification {
- top: 0;
- left: 0;
- right: 0;
- }
-
- #nav_entries {
- width: 100%;
- }
-
- #stream.global .box-category {
- margin: 10px 0;
- }
-
- #panel {
- top: 0; bottom: 0;
- left: 0; right: 0;
- }
- #panel .close {
- top: 0; right: 0;
- left: auto; bottom: auto;
- display: inline-block;
- width: 30px;
- height: 30px;
- }
-}
-
-/*=== PRINTER */
-/*============*/
-@media print {
- .header, .aside,
- .nav_menu, .day,
- .flux_header,
- .flux_content .bottom,
- .pagination,
- #nav_entries {
- display: none;
- }
- html, body {
- background: #fff;
- color: #000;
- font-family: Serif;
- }
- #global,
- .flux_content {
- display: block !important;
- }
- .flux_content .content {
- width: 100% !important;
- }
- .flux_content .content a {
- color: #000;
- }
- .flux_content .content a:after {
- content: " [" attr(href) "] ";
- font-style: italic;
- }
-}
diff --git a/p/themes/Origine/metadata.json b/p/themes/Origine/metadata.json
index 59a45e8f6..774320eb4 100644
--- a/p/themes/Origine/metadata.json
+++ b/p/themes/Origine/metadata.json
@@ -3,5 +3,5 @@
"author": "Marien Fressinaud",
"description": "Le thème par défaut pour FreshRSS",
"version": 0.2,
- "files": ["template.css", "origine.css"]
+ "files": ["_template.css", "origine.css"]
}
diff --git a/p/themes/Origine/template.css b/p/themes/Origine/template.css
deleted file mode 100644
index 466ec4603..000000000
--- a/p/themes/Origine/template.css
+++ /dev/null
@@ -1,698 +0,0 @@
-@charset "UTF-8";
-
-/*=== GENERAL */
-/*============*/
-html, body {
- margin: 0;
- padding: 0;
- font-size: 100%;
-}
-
-/*=== Links */
-a {
- text-decoration: none;
-}
-a:hover {
- text-decoration: underline;
-}
-
-/*=== Lists */
-ul, ol, dd {
- margin: 0;
- padding: 0;
-}
-
-/*=== Titles */
-h1 {
- margin: 0.6em 0 0.3em;
- font-size: 1.5em;
- line-height: 1.6em;
-}
-h2 {
- margin: 0.5em 0 0.25em;
- font-size: 1.3em;
- line-height: 2em;
-}
-h3 {
- margin: 0.5em 0 0.25em;
- font-size: 1.1em;
- line-height: 2em;
-}
-
-/*=== Paragraphs */
-p {
- margin: 1em 0 0.5em;
- font-size: 1em;
-}
-
-/*=== Images */
-img {
- height: auto;
- max-width: 100%;
-}
-img.favicon {
- height: 16px;
- width: 16px;
- vertical-align: middle;
-}
-
-/*=== Videos */
-iframe, embed, object, video {
- max-width: 100%;
-}
-
-/*=== Forms */
-legend {
- display: block;
- width: 100%;
- clear: both;
-}
-label {
- display: block;
-}
-input {
- width: 180px;
-}
-textarea {
- width: 300px;
-}
-input, select, textarea {
- display: inline-block;
- max-width: 100%;
-}
-input[type="radio"],
-input[type="checkbox"] {
- width: 15px !important;
- min-height: 15px !important;
-}
-input.extend:focus {
- width: 300px;
-}
-
-/*=== COMPONENTS */
-/*===============*/
-/*=== Forms */
-.form-group:after {
- content: "";
- display: block;
- clear: both;
-}
-.form-group.form-actions {
- min-width: 250px;
-}
-.form-group .group-name {
- display: block;
- float: left;
- width: 200px;
-}
-.form-group .group-controls {
- min-width: 250px;
- margin: 0 0 0 220px;
-}
-.form-group .group-controls .control {
- display: block;
-}
-
-/*=== Buttons */
-.stick {
- display: inline-block;
- white-space: nowrap;
-}
-.btn,
-a.btn {
- display: inline-block;
- cursor: pointer;
- overflow: hidden;
-}
-.btn-important {
- font-weight: bold;
-}
-
-/*=== Navigation */
-.nav-list .nav-header,
-.nav-list .item {
- display: block;
-}
-.nav-list .item,
-.nav-list .item > a {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.nav-head {
- display: block;
-}
-.nav-head .item {
- display: inline-block;
-}
-
-/*=== Horizontal-list */
-.horizontal-list {
- display: table;
- table-layout: fixed;
- width: 100%;
-}
-.horizontal-list .item {
- display: table-cell;
-}
-
-/*=== Dropdown */
-.dropdown {
- position: relative;
- display: inline-block;
-}
-.dropdown-target {
- display: none;
-}
-.dropdown-menu {
- display: none;
- min-width: 200px;
- margin: 0;
- position: absolute;
- right: 0;
- background: #fff;
- border: 1px solid #aaa;
-}
-.dropdown-header {
- display: block;
-}
-.dropdown-menu > .item {
- display: block;
-}
-.dropdown-menu > .item > a,
-.dropdown-menu > .item > span {
- display: block;
-}
-.dropdown-menu > .item[aria-checked="true"] > a:before {
- content: '✓';
-}
-.dropdown-menu .input {
- display: block;
-}
-.dropdown-menu .input select,
-.dropdown-menu .input input {
- display: block;
- max-width: 95%;
-}
-.dropdown-target:target ~ .dropdown-menu {
- display: block;
- z-index: 10;
-}
-.dropdown-close {
- display: inline;
-}
-.dropdown-close a {
- font-size: 0;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
- z-index: -10;
-}
-.separator {
- display: block;
- height: 0;
- border-bottom: 1px solid #aaa;
-}
-
-/*=== Alerts */
-.alert {
- display: block;
- width: 90%;
-}
-.group-controls .alert {
- width: 100%
-}
-.alert-head {
- margin: 0;
- font-weight: bold;
-}
-.alert ul {
- margin: 5px 20px;
-}
-
-/*=== Icons */
-.icon {
- display: inline-block;
- width: 16px;
- height: 16px;
- vertical-align: middle;
- line-height: 16px;
-}
-
-/*=== Pagination */
-.pagination {
- display: table;
- width: 100%;
- margin: 0;
- padding: 0;
- table-layout: fixed;
-}
-.pagination .item {
- display: table-cell;
-}
-.pagination .pager-first,
-.pagination .pager-previous,
-.pagination .pager-next,
-.pagination .pager-last {
- width: 100px;
-}
-
-/*=== STRUCTURE */
-/*===============*/
-/*=== Header */
-.header {
- display: table;
- width: 100%;
- table-layout: fixed;
-}
-.header > .item {
- display: table-cell;
-}
-.header > .item.title {
- width: 250px;
- white-space: nowrap;
-}
-.header > .item.title h1 {
- display: inline-block;
-}
-.header > .item.title .logo {
- display: inline-block;
- height: 32px;
- width: 32px;
- vertical-align: middle;
-}
-.header > .item.configure {
- width: 100px;
-}
-
-/*=== Body */
-#global {
- display: table;
- width: 100%;
- height: 100%;
- table-layout: fixed;
-}
-.aside {
- display: table-cell;
- height: 100%;
- width: 250px;
- vertical-align: top;
-}
-.aside.aside_flux {
- background: #fff;
-}
-
-/*=== Aside main page (categories) */
-.categories {
- list-style: none;
- margin: 0;
-}
-.state_unread li:not(.active)[data-unread="0"] {
- display: none;
-}
-.category {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.category .btn:not([data-unread="0"]):after {
- content: attr(data-unread);
-}
-
-/*=== Aside main page (feeds) */
-.categories .feeds {
- width: 100%;
- list-style: none;
-}
-.categories .feeds:not(.active) {
- display: none;
-}
-.categories .feeds .feed {
- display: inline-block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-.categories .feeds .feed:not([data-unread="0"]):before {
- content: "(" attr(data-unread) ") ";
-}
-.categories .feeds .dropdown-menu {
- left: 0;
-}
-.categories .feeds .item .dropdown-toggle > .icon {
- visibility: hidden;
- cursor: pointer;
- vertical-align: top;
-}
-.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon,
-.categories .feeds .item:hover .dropdown-toggle > .icon,
-.categories .feeds .item.active .dropdown-toggle > .icon {
- visibility: visible;
-}
-
-/*=== New article notification */
-#new-article {
- display: none;
-}
-#new-article > a {
- display: block;
-}
-
-/*=== Day indication */
-.day .name {
- position: absolute;
- right: 0;
- width: 50%;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-/*=== Feed article header and footer */
-.flux_header {
- position: relative;
-}
-.flux .item {
- line-height: 40px;
- white-space: nowrap;
-}
-.flux .item.manage,
-.flux .item.link {
- width: 40px;
- text-align: center;
-}
-.flux .item.website {
- width: 200px;
-}
-.flux.not_read .item.title,
-.flux.current .item.title {
- font-weight: bold;
-}
-.flux:not(.current):hover .item.title {
- position: absolute;
- max-width: calc(100% - 320px);
- background: #fff;
-}
-.flux .item.title a {
- color: #000;
- text-decoration: none;
-}
-.flux .item.date {
- width: 145px;
- text-align: right;
-}
-.flux .item > a {
- display: block;
-}
-.flux .item > a {
- display: block;
- text-decoration: none;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-.flux .item.share > a {
- display: list-item;
- list-style-position: inside;
- list-style-type: decimal;
-}
-
-/*=== Feed article content */
-.hide_posts > .flux:not(.active) > .flux_content {
- display: none;
-}
-.content {
- min-height: 20em;
- margin: auto;
- line-height: 1.7em;
- word-wrap: break-word;
-}
-.content.large {
- max-width: 1000px;
-}
-.content.medium {
- max-width: 800px;
-}
-.content.thin {
- max-width: 550px;
-}
-.content ul,
-.content ol,
-.content dd {
- margin: 0 0 0 15px;
- padding: 0 0 5px 15px;
-}
-.content pre {
- overflow: auto;
-}
-
-/*=== Notification and actualize notification */
-.notification {
- position: absolute;
- top: 1em;
- left: 25%; right: 25%;
- z-index: 10;
- background: #fff;
- border: 1px solid #aaa;
-}
-.notification.closed {
- display: none;
-}
-.notification a.close {
- position: absolute;
- top: 0; bottom: 0;
- right: 0;
- display: inline-block;
-}
-
-#actualizeProgress {
- position: fixed;
-}
-#actualizeProgress progress {
- max-width: 100%;
- vertical-align: middle;
-}
-#actualizeProgress .progress {
- vertical-align: middle;
-}
-
-/*=== Navigation menu (for articles) */
-#nav_entries {
- position: fixed;
- bottom: 0; left: 0;
- display: table;
- width: 250px;
- background: #fff;
- table-layout: fixed;
-}
-#nav_entries .item {
- display: table-cell;
- width: 30%;
-}
-#nav_entries a {
- display: block;
-}
-
-/*=== "Load more" part */
-#load_more {
- min-height: 40px;
-}
-.loading {
- background: url("loader.gif") center center no-repeat;
- font-size: 0;
-}
-#bigMarkAsRead {
- display: block;
- padding: 3em 0;
- text-align: center;
-}
-.bigTick {
- font-size: 7em;
- line-height: 1.6em;
-}
-
-/*=== Statistiques */
-.stat > table {
- width: 100%;
-}
-
-/*=== GLOBAL VIEW */
-/*================*/
-/*=== Category boxes */
-#stream.global .box-category {
- display: inline-block;
- width: 19em;
- max-width: 95%;
- margin: 20px 10px;
- border: 1px solid #ccc;
- vertical-align: top;
-}
-#stream.global .category {
- width: 100%;
-}
-#stream.global .btn {
- display: block;
-}
-#stream.global .box-category .feeds {
- display: block;
- overflow: auto;
-}
-#stream.global .box-category .feed {
- width: 19em;
- max-width: 90%;
-}
-
-/*=== Panel */
-#overlay {
- display: none;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- background: rgba(0, 0, 0, 0.9);
-}
-#panel {
- display: none;
- position: fixed;
- top: 1em; bottom: 1em;
- left: 2em; right: 2em;
- overflow: auto;
- background: #fff;
-}
-#panel .close {
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
-}
-#panel .close img {
- display: none;
-}
-
-/*=== DIVERS */
-/*===========*/
-.nav-login,
-.nav_menu .search,
-.nav_menu .toggle_aside {
- display: none;
-}
-
-.aside .toggle_aside {
- position: absolute;
- right: 0;
- display: none;
- width: 30px;
- height: 30px;
- line-height: 30px;
- text-align: center;
-}
-
-/*=== MOBILE */
-/*===========*/
-@media(max-width: 840px) {
- .header,
- .aside .btn-important,
- .aside .feeds .dropdown,
- .flux_header .item.website span,
- .item.date, .day .date,
- .dropdown-menu > .no-mobile,
- .no-mobile {
- display: none;
- }
- .nav-login {
- display: block;
- }
- .nav_menu .toggle_aside,
- .aside .toggle_aside,
- .nav_menu .search,
- #panel .close img {
- display: inline-block;
- }
-
- .aside {
- position: fixed;
- top: 0; bottom: 0;
- left: 0;
- width: 0;
- overflow: hidden;
- z-index: 100;
- }
- .aside:target {
- width: 90%;
- overflow: auto;
- }
- .aside .categories {
- margin: 10px 0 75px;
- }
-
- .flux_header .item.website {
- width: 40px;
- }
-
- .flux:not(.current):hover .item.title {
- position: relative;
- width: auto;
- white-space: nowrap;
- }
-
- .notification {
- top: 0;
- left: 0;
- right: 0;
- }
-
- #nav_entries {
- width: 100%;
- }
-
- #stream.global .box-category {
- margin: 10px 0;
- }
-
- #panel {
- top: 0; bottom: 0;
- left: 0; right: 0;
- }
- #panel .close {
- top: 0; right: 0;
- left: auto; bottom: auto;
- display: inline-block;
- width: 30px;
- height: 30px;
- }
-}
-
-/*=== PRINTER */
-/*============*/
-@media print {
- .header, .aside,
- .nav_menu, .day,
- .flux_header,
- .flux_content .bottom,
- .pagination,
- #nav_entries {
- display: none;
- }
- html, body {
- background: #fff;
- color: #000;
- font-family: Serif;
- }
- #global,
- .flux_content {
- display: block !important;
- }
- .flux_content .content {
- width: 100% !important;
- }
- .flux_content .content a {
- color: #000;
- }
- .flux_content .content a:after {
- content: " [" attr(href) "] ";
- font-style: italic;
- }
-}
diff --git a/p/themes/Screwdriver/metadata.json b/p/themes/Screwdriver/metadata.json
index f45f1a98a..46095e507 100644
--- a/p/themes/Screwdriver/metadata.json
+++ b/p/themes/Screwdriver/metadata.json
@@ -3,5 +3,5 @@
"author": "Mister aiR",
"description": "C'est un cocktail ! C'est chaud mais « fresh » à la fois. Ce thème tue du chaton.",
"version": 1.1,
- "files": ["template.css","screwdriver.css"]
+ "files": ["_template.css","screwdriver.css"]
}
diff --git a/p/themes/Screwdriver/template.css b/p/themes/Screwdriver/template.css
deleted file mode 100644
index ddb3f376f..000000000
--- a/p/themes/Screwdriver/template.css
+++ /dev/null
@@ -1,698 +0,0 @@
-@charset "UTF-8";
-
-/*=== GENERAL */
-/*============*/
-html, body {
- margin: 0;
- padding: 0;
- font-size: 92%;
-}
-
-/*=== Links */
-a {
- text-decoration: none;
-}
-a:hover {
- text-decoration: underline;
-}
-
-/*=== Lists */
-ul, ol, dd {
- margin: 0;
- padding: 0;
-}
-
-/*=== Titles */
-h1 {
- margin: 0.6em 0 0.3em;
- font-size: 1.5em;
- line-height: 1.6em;
-}
-h2 {
- margin: 0.5em 0 0.25em;
- font-size: 1.3em;
- line-height: 2em;
-}
-h3 {
- margin: 0.5em 0 0.25em;
- font-size: 1.1em;
- line-height: 2em;
-}
-
-/*=== Paragraphs */
-p {
- margin: 1em 0 0.5em;
- font-size: 1em;
-}
-
-/*=== Images */
-img {
- height: auto;
- max-width: 100%;
-}
-img.favicon {
- height: 16px;
- width: 16px;
- vertical-align: middle;
-}
-
-/*=== Videos */
-iframe, embed, object, video {
- max-width: 100%;
-}
-
-/*=== Forms */
-legend {
- display: block;
- width: 100%;
- clear: both;
-}
-label {
- display: block;
-}
-input {
- width: 180px;
-}
-textarea {
- width: 300px;
-}
-input, select, textarea {
- display: inline-block;
- max-width: 100%;
-}
-input[type="radio"],
-input[type="checkbox"] {
- width: 15px !important;
- min-height: 15px !important;
-}
-input.extend:focus {
- width: 300px;
-}
-
-/*=== COMPONENTS */
-/*===============*/
-/*=== Forms */
-.form-group:after {
- content: "";
- display: block;
- clear: both;
-}
-.form-group.form-actions {
- min-width: 250px;
-}
-.form-group .group-name {
- display: block;
- float: left;
- width: 200px;
-}
-.form-group .group-controls {
- min-width: 250px;
- margin: 0 0 0 220px;
-}
-.form-group .group-controls .control {
- display: block;
-}
-
-/*=== Buttons */
-.stick {
- display: inline-block;
- white-space: nowrap;
-}
-.btn,
-a.btn {
- display: inline-block;
- cursor: pointer;
- overflow: hidden;
-}
-.btn-important {
- font-weight: bold;
-}
-
-/*=== Navigation */
-.nav-list .nav-header,
-.nav-list .item {
- display: block;
-}
-.nav-list .item,
-.nav-list .item > a {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.nav-head {
- display: block;
-}
-.nav-head .item {
- display: inline-block;
-}
-
-/*=== Horizontal-list */
-.horizontal-list {
- display: table;
- table-layout: fixed;
- width: 100%;
-}
-.horizontal-list .item {
- display: table-cell;
-}
-
-/*=== Dropdown */
-.dropdown {
- position: relative;
- display: inline-block;
-}
-.dropdown-target {
- display: none;
-}
-.dropdown-menu {
- display: none;
- min-width: 200px;
- margin: 0;
- position: absolute;
- right: 0;
- background: #fff;
- border: 1px solid #aaa;
-}
-.dropdown-header {
- display: block;
-}
-.dropdown-menu > .item {
- display: block;
-}
-.dropdown-menu > .item > a,
-.dropdown-menu > .item > span {
- display: block;
-}
-.dropdown-menu > .item[aria-checked="true"] > a:before {
- content: '✓';
-}
-.dropdown-menu .input {
- display: block;
-}
-.dropdown-menu .input select,
-.dropdown-menu .input input {
- display: block;
- max-width: 95%;
-}
-.dropdown-target:target ~ .dropdown-menu {
- display: block;
- z-index: 10;
-}
-.dropdown-close {
- display: inline;
-}
-.dropdown-close a {
- font-size: 0;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
- z-index: -10;
-}
-.separator {
- display: block;
- height: 0;
- border-bottom: 1px solid #aaa;
-}
-
-/*=== Alerts */
-.alert {
- display: block;
- width: 90%;
-}
-.group-controls .alert {
- width: 100%
-}
-.alert-head {
- margin: 0;
- font-weight: bold;
-}
-.alert ul {
- margin: 5px 20px;
-}
-
-/*=== Icons */
-.icon {
- display: inline-block;
- width: 16px;
- height: 16px;
- vertical-align: middle;
- line-height: 16px;
-}
-
-/*=== Pagination */
-.pagination {
- display: table;
- width: 100%;
- margin: 0;
- padding: 0;
- table-layout: fixed;
-}
-.pagination .item {
- display: table-cell;
-}
-.pagination .pager-first,
-.pagination .pager-previous,
-.pagination .pager-next,
-.pagination .pager-last {
- width: 100px;
-}
-
-/*=== STRUCTURE */
-/*===============*/
-/*=== Header */
-.header {
- display: table;
- width: 100%;
- table-layout: fixed;
-}
-.header > .item {
- display: table-cell;
-}
-.header > .item.title {
- width: 250px;
- white-space: nowrap;
-}
-.header > .item.title h1 {
- display: inline-block;
-}
-.header > .item.title .logo {
- display: inline-block;
- height: 32px;
- width: 32px;
- vertical-align: middle;
-}
-.header > .item.configure {
- width: 100px;
-}
-
-/*=== Body */
-#global {
- display: table;
- width: 100%;
- height: 100%;
- table-layout: fixed;
-}
-.aside {
- display: table-cell;
- height: 100%;
- width: 250px;
- vertical-align: top;
-}
-.aside.aside_flux {
- background: #fff;
-}
-
-/*=== Aside main page (categories) */
-.categories {
- list-style: none;
- margin: 0;
-}
-.state_unread li:not(.active)[data-unread="0"] {
- display: none;
-}
-.category {
- display: block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.category .btn:not([data-unread="0"]):after {
- content: attr(data-unread);
-}
-
-/*=== Aside main page (feeds) */
-.categories .feeds {
- width: 100%;
- list-style: none;
-}
-.categories .feeds:not(.active) {
- display: none;
-}
-.categories .feeds .feed {
- display: inline-block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-.categories .feeds .feed:not([data-unread="0"]):before {
- content: "(" attr(data-unread) ") ";
-}
-.categories .feeds .dropdown-menu {
- left: 0;
-}
-.categories .feeds .item .dropdown-toggle > .icon {
- visibility: hidden;
- cursor: pointer;
- vertical-align: top;
-}
-.categories .feeds .item .dropdown-target:target ~ .dropdown-toggle > .icon,
-.categories .feeds .item:hover .dropdown-toggle > .icon,
-.categories .feeds .item.active .dropdown-toggle > .icon {
- visibility: visible;
-}
-
-/*=== New article notification */
-#new-article {
- display: none;
-}
-#new-article > a {
- display: block;
-}
-
-/*=== Day indication */
-.day .name {
- position: absolute;
- right: 0;
- width: 50%;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-/*=== Feed article header and footer */
-.flux_header {
- position: relative;
-}
-.flux .item {
- line-height: 40px;
- white-space: nowrap;
-}
-.flux .item.manage,
-.flux .item.link {
- width: 40px;
- text-align: center;
-}
-.flux .item.website {
- width: 200px;
-}
-.flux.not_read .item.title,
-.flux.current .item.title {
- font-weight: bold;
-}
-.flux:not(.current):hover .item.title {
- position: absolute;
- max-width: calc(100% - 320px);
- background: #fff;
-}
-.flux .item.title a {
- color: #000;
- text-decoration: none;
-}
-.flux .item.date {
- width: 145px;
- text-align: right;
-}
-.flux .item > a {
- display: block;
-}
-.flux .item > a {
- display: block;
- text-decoration: none;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-.flux .item.share > a {
- display: list-item;
- list-style-position: inside;
- list-style-type: decimal;
-}
-
-/*=== Feed article content */
-.hide_posts > .flux:not(.active) > .flux_content {
- display: none;
-}
-.content {
- min-height: 20em;
- margin: auto;
- line-height: 1.7em;
- word-wrap: break-word;
-}
-.content.large {
- max-width: 1000px;
-}
-.content.medium {
- max-width: 800px;
-}
-.content.thin {
- max-width: 550px;
-}
-.content ul,
-.content ol,
-.content dd {
- margin: 0 0 0 15px;
- padding: 0 0 5px 15px;
-}
-.content pre {
- overflow: auto;
-}
-
-/*=== Notification and actualize notification */
-.notification {
- position: absolute;
- top: 1em;
- left: 25%; right: 25%;
- z-index: 10;
- background: #fff;
- border: 1px solid #aaa;
-}
-.notification.closed {
- display: none;
-}
-.notification a.close {
- position: absolute;
- top: 0; bottom: 0;
- right: 0;
- display: inline-block;
-}
-
-#actualizeProgress {
- position: fixed;
-}
-#actualizeProgress progress {
- max-width: 100%;
- vertical-align: middle;
-}
-#actualizeProgress .progress {
- vertical-align: middle;
-}
-
-/*=== Navigation menu (for articles) */
-#nav_entries {
- position: fixed;
- bottom: 0; left: 0;
- display: table;
- width: 250px;
- background: #fff;
- table-layout: fixed;
-}
-#nav_entries .item {
- display: table-cell;
- width: 30%;
-}
-#nav_entries a {
- display: block;
-}
-
-/*=== "Load more" part */
-#load_more {
- min-height: 40px;
-}
-.loading {
- background: url("loader.gif") center center no-repeat;
- font-size: 0;
-}
-#bigMarkAsRead {
- display: block;
- padding: 3em 0;
- text-align: center;
-}
-.bigTick {
- font-size: 7em;
- line-height: 1.6em;
-}
-
-/*=== Statistiques */
-.stat > table {
- width: 100%;
-}
-
-/*=== GLOBAL VIEW */
-/*================*/
-/*=== Category boxes */
-#stream.global .box-category {
- display: inline-block;
- width: 19em;
- max-width: 95%;
- margin: 20px 10px;
- border: 1px solid #ccc;
- vertical-align: top;
-}
-#stream.global .category {
- width: 100%;
-}
-#stream.global .btn {
- display: block;
-}
-#stream.global .box-category .feeds {
- display: block;
- overflow: auto;
-}
-#stream.global .box-category .feed {
- width: 19em;
- max-width: 90%;
-}
-
-/*=== Panel */
-#overlay {
- display: none;
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- background: rgba(0, 0, 0, 0.9);
-}
-#panel {
- display: none;
- position: fixed;
- top: 1em; bottom: 1em;
- left: 2em; right: 2em;
- overflow: auto;
- background: #fff;
-}
-#panel .close {
- position: fixed;
- top: 0; bottom: 0;
- left: 0; right: 0;
- display: block;
-}
-#panel .close img {
- display: none;
-}
-
-/*=== DIVERS */
-/*===========*/
-.nav-login,
-.nav_menu .search,
-.nav_menu .toggle_aside {
- display: none;
-}
-
-.aside .toggle_aside {
- position: absolute;
- right: 0;
- display: none;
- width: 30px;
- height: 30px;
- line-height: 30px;
- text-align: center;
-}
-
-/*=== MOBILE */
-/*===========*/
-@media(max-width: 840px) {
- .header,
- .aside .btn-important,
- .aside .feeds .dropdown,
- .flux_header .item.website span,
- .item.date, .day .date,
- .dropdown-menu > .no-mobile,
- .no-mobile {
- display: none;
- }
- .nav-login {
- display: block;
- }
- .nav_menu .toggle_aside,
- .aside .toggle_aside,
- .nav_menu .search,
- #panel .close img {
- display: inline-block;
- }
-
- .aside {
- position: fixed;
- top: 0; bottom: 0;
- left: 0;
- width: 0;
- overflow: hidden;
- z-index: 100;
- }
- .aside:target {
- width: 90%;
- overflow: auto;
- }
- .aside .categories {
- margin: 10px 0 75px;
- }
-
- .flux_header .item.website {
- width: 40px;
- }
-
- .flux:not(.current):hover .item.title {
- position: relative;
- width: auto;
- white-space: nowrap;
- }
-
- .notification {
- top: 0;
- left: 0;
- right: 0;
- }
-
- #nav_entries {
- width: 100%;
- }
-
- #stream.global .box-category {
- margin: 10px 0;
- }
-
- #panel {
- top: 0; bottom: 0;
- left: 0; right: 0;
- }
- #panel .close {
- top: 0; right: 0;
- left: auto; bottom: auto;
- display: inline-block;
- width: 30px;
- height: 30px;
- }
-}
-
-/*=== PRINTER */
-/*============*/
-@media print {
- .header, .aside,
- .nav_menu, .day,
- .flux_header,
- .flux_content .bottom,
- .pagination,
- #nav_entries {
- display: none;
- }
- html, body {
- background: #fff;
- color: #000;
- font-family: Serif;
- }
- #global,
- .flux_content {
- display: block !important;
- }
- .flux_content .content {
- width: 100% !important;
- }
- .flux_content .content a {
- color: #000;
- }
- .flux_content .content a:after {
- content: " [" attr(href) "] ";
- font-style: italic;
- }
-}
--
cgit v1.2.3
From 1e5efc92993feddb7916ef675010d0de0e470ac5 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Tue, 16 Sep 2014 14:23:04 +0200
Subject: Mark many as read must be a POST action
See https://github.com/marienfressinaud/FreshRSS/issues/599
---
app/Controllers/entryController.php | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'app/Controllers')
diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php
index ac43587ea..ab66d9198 100755
--- a/app/Controllers/entryController.php
+++ b/app/Controllers/entryController.php
@@ -45,6 +45,10 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
$entryDAO = FreshRSS_Factory::createEntryDao();
if ($id == false) {
+ if (!Minz_Request::isPost()) {
+ return;
+ }
+
if (!$get) {
$entryDAO->markReadEntries ($idMax);
} else {
--
cgit v1.2.3
From a4e43e9c53ac404d16af5d913a56eeb444b1ce10 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Tue, 16 Sep 2014 18:30:24 +0200
Subject: Message if last update checking is close
last_update.txt is updated even if there is no update
If last_update.txt has been modified during last hour, show a message
See https://github.com/marienfressinaud/FreshRSS/issues/480#issuecomment-55765373
---
app/Controllers/updateController.php | 11 ++++++-----
app/i18n/en.php | 2 +-
app/i18n/fr.php | 2 +-
app/views/update/index.phtml | 17 +++++++++++++----
4 files changed, 21 insertions(+), 11 deletions(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 4c1dd002c..72244e9c7 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -12,9 +12,11 @@ class FreshRSS_update_Controller extends Minz_ActionController {
Minz_View::prependTitle(_t('update_system') . ' · ');
$this->view->last_update_time = 'unknown';
+ $this->view->check_last_hour = false;
$timestamp = (int)@file_get_contents(DATA_PATH . '/last_update.txt');
if (is_numeric($timestamp) && $timestamp > 0) {
$this->view->last_update_time = timestamptodate($timestamp);
+ $this->view->check_last_hour = (time() - 3600) <= $timestamp;
}
}
@@ -38,13 +40,10 @@ class FreshRSS_update_Controller extends Minz_ActionController {
public function checkAction() {
$this->view->change_view('update', 'index');
- // Get the last update. If already check during the last hour, do nothing.
- $last_update = (int)@file_get_contents(DATA_PATH . '/last_update.txt');
- $check_last_hour = (time() - 3600) <= $last_update;
-
- if (file_exists(UPDATE_FILENAME) || $check_last_hour) {
+ if (file_exists(UPDATE_FILENAME) || $this->view->check_last_hour) {
// There is already an update file to apply: we don't need to check
// the webserver!
+ // Or if already check during the last hour, do nothing.
Minz_Request::forward(array('c' => 'update'));
return;
@@ -81,6 +80,8 @@ class FreshRSS_update_Controller extends Minz_ActionController {
'body' => _t('no_update')
);
+ @file_put_contents(DATA_PATH . '/last_update.txt', time());
+
return;
}
diff --git a/app/i18n/en.php b/app/i18n/en.php
index c5911cde7..8f39115ad 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -424,7 +424,7 @@ return array (
'update' => 'Update',
'update_system' => 'Update system',
'update_check' => 'Check for new updates',
- 'update_last' => 'Last update: %s',
+ 'update_last' => 'Last verification: %s',
'update_can_apply' => 'There is an available update. Apply ',
'update_server_not_found' => 'Update server cannot be found. [%s]',
'no_update' => 'No update to apply',
diff --git a/app/i18n/fr.php b/app/i18n/fr.php
index 789a0bb98..48b4c1732 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -424,7 +424,7 @@ return array (
'update' => 'Mise à jour',
'update_system' => 'Système de mise à jour',
'update_check' => 'Vérifier les mises à jour',
- 'update_last' => 'Dernière mise à jour : %s',
+ 'update_last' => 'Dernière vérification : %s',
'update_can_apply' => 'Il y’a une mise à jour à appliquer. Appliquer la mise à jour ',
'update_server_not_found' => 'Le serveur de mise à jour n’a pas été trouvé. [%s]',
'no_update' => 'Aucune mise à jour à appliquer',
diff --git a/app/views/update/index.phtml b/app/views/update/index.phtml
index 1824c02b8..5be8b1e8b 100644
--- a/app/views/update/index.phtml
+++ b/app/views/update/index.phtml
@@ -5,17 +5,26 @@
+
+ last_update_time); ?>
+
+
message)) { ?>
message['title']; ?>
message['body']; ?>
+ check_last_hour) { ?>
+
+
+
+
- message) || $this->message['status'] !== 'good') { ?>
-
- last_update_time); ?>
-
+ check_last_hour &&
+ (empty($this->message) || $this->message['status'] !== 'good')) {
+ ?>
--
cgit v1.2.3
From 7d5e57b35b4eca07417c296c156edb3b88eef90b Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Wed, 17 Sep 2014 09:15:19 +0200
Subject: Load $nb/2 articles when articles are unfolded
See https://github.com/marienfressinaud/FreshRSS/issues/559
---
app/Controllers/indexController.php | 5 +++++
app/layout/layout.phtml | 1 +
app/views/helpers/pagination.phtml | 5 ++++-
3 files changed, 10 insertions(+), 1 deletion(-)
(limited to 'app/Controllers')
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index b0b051119..1d74a570b 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -83,6 +83,11 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$nb = Minz_Request::param ('nb', $this->view->conf->posts_per_page);
$first = Minz_Request::param ('next', '');
+ $ajax_request = Minz_Request::param('ajax', false);
+ if ($ajax_request == 1 && $this->view->conf->display_posts) {
+ $nb = max(1, round($nb / 2));
+ }
+
if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ) { //Any unread article in this category at all?
switch ($getType) {
case 'a':
diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml
index 96a88d245..f95f45b5e 100644
--- a/app/layout/layout.phtml
+++ b/app/layout/layout.phtml
@@ -13,6 +13,7 @@
if (!empty($this->nextId)) {
$params = Minz_Request::params();
$params['next'] = $this->nextId;
+ $params['ajax'] = 1;
?>
diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml
index f6fcbc701..1b15cc632 100755
--- a/app/views/helpers/pagination.phtml
+++ b/app/views/helpers/pagination.phtml
@@ -9,7 +9,10 @@
+
+ update_to_apply) { ?>
+
+
--
cgit v1.2.3
From 3b8c381689334a15e7c034425f8615860dc3fa13 Mon Sep 17 00:00:00 2001
From: Marien Fressinaud
Date: Wed, 17 Sep 2014 13:37:39 +0200
Subject: No cache for update system
See https://github.com/marienfressinaud/FreshRSS/issues/616
---
app/Controllers/updateController.php | 2 ++
1 file changed, 2 insertions(+)
(limited to 'app/Controllers')
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index 78d636163..da5bddc65 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -10,6 +10,8 @@ class FreshRSS_update_Controller extends Minz_ActionController {
);
}
+ invalidateHttpCache();
+
Minz_View::prependTitle(_t('update_system') . ' · ');
$this->view->update_to_apply = false;
$this->view->last_update_time = 'unknown';
--
cgit v1.2.3
From 4211539c24e36531f2c5440ad454c4e208131047 Mon Sep 17 00:00:00 2001
From: plopoyop
Date: Thu, 18 Sep 2014 10:46:34 +0200
Subject: Add timeout option for HTML5 notification
---
app/Controllers/configureController.php | 1 +
app/Models/Configuration.php | 7 +++++++
app/i18n/de.php | 2 ++
app/i18n/en.php | 2 ++
app/i18n/fr.php | 2 ++
app/views/configure/display.phtml | 7 +++++++
app/views/helpers/javascript_vars.phtml | 2 ++
p/scripts/main.js | 6 ++++++
8 files changed, 29 insertions(+)
(limited to 'app/Controllers')
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index bb96bfae3..b1cd45014 100755
--- a/app/Controllers/configureController.php
+++ b/app/Controllers/configureController.php
@@ -157,6 +157,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->conf->_bottomline_tags(Minz_Request::param('bottomline_tags', false));
$this->view->conf->_bottomline_date(Minz_Request::param('bottomline_date', false));
$this->view->conf->_bottomline_link(Minz_Request::param('bottomline_link', false));
+ $this->view->conf->_html5_notif_timeout(Minz_Request::param('html5_notif_timeout', 0));
$this->view->conf->save();
Minz_Session::_param('language', $this->view->conf->language);
diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php
index e4408df73..830d39f0d 100644
--- a/app/Models/Configuration.php
+++ b/app/Models/Configuration.php
@@ -60,6 +60,7 @@ class FreshRSS_Configuration {
'bottomline_link' => true,
'sharing' => array(),
'queries' => array(),
+ 'html5_notif_timeout' => 0,
);
private $available_languages = array(
@@ -269,6 +270,12 @@ class FreshRSS_Configuration {
$this->data['content_width'] = 'thin';
}
}
+
+ public function _html5_notif_timeout ($value) {
+ $value = intval($value);
+ $this->data['html5_notif_timeout'] = $value >= 0 ? $value : 0;
+ }
+
public function _token($value) {
$this->data['token'] = $value;
}
diff --git a/app/i18n/de.php b/app/i18n/de.php
index 4301a8b6d..3f7d8ca27 100644
--- a/app/i18n/de.php
+++ b/app/i18n/de.php
@@ -212,6 +212,8 @@ return array (
'reading_icons' => 'Lese Symbol',
'top_line' => 'Kopfzeile',
'bottom_line' => 'Fusszeile',
+ 'html5_notif_timeout' => 'HTML5 notification timeout',
+ 'seconds_(0_means_no_timeout)' => 'seconds (0 means no timeout)',
'img_with_lazyload' => 'Verwende die "träge laden" Methode zum laden von Bildern',
'auto_read_when' => 'Artikel als gelesen markieren…',
'article_selected' => 'wenn der Artikel ausgewählt ist',
diff --git a/app/i18n/en.php b/app/i18n/en.php
index 8f39115ad..1e842a1e1 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -280,6 +280,8 @@ return array (
'article_icons' => 'Article icons',
'top_line' => 'Top line',
'bottom_line' => 'Bottom line',
+ 'html5_notif_timeout' => 'HTML5 notification timeout',
+ 'seconds_(0_means_no_timeout)' => 'seconds (0 means no timeout)',
'img_with_lazyload' => 'Use "lazy load" mode to load pictures',
'sticky_post' => 'Stick the article to the top when opened',
'reading_confirm' => 'Display a confirmation dialog on “mark all as read” actions',
diff --git a/app/i18n/fr.php b/app/i18n/fr.php
index 48b4c1732..bbfa71f66 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -280,6 +280,8 @@ return array (
'article_icons' => 'Icônes d’article',
'top_line' => 'Ligne du haut',
'bottom_line' => 'Ligne du bas',
+ 'html5_notif_timeout' => 'Temps d\'affichage de la notification HTML5',
+ 'seconds_(0_means_no_timeout)' => 'secondes (0 signifie aucun timeout ) ',
'img_with_lazyload' => 'Utiliser le mode “chargement différé” pour les images',
'sticky_post' => 'Aligner l’article en haut quand il est ouvert',
'reading_confirm' => 'Afficher une confirmation lors des actions “marquer tout comme lu”',
diff --git a/app/views/configure/display.phtml b/app/views/configure/display.phtml
index 955fc6747..8eb3a156b 100644
--- a/app/views/configure/display.phtml
+++ b/app/views/configure/display.phtml
@@ -91,6 +91,13 @@
+
+