aboutsummaryrefslogtreecommitdiff
path: root/app/views
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2022-07-04 09:53:26 +0200
committerGravatar GitHub <noreply@github.com> 2022-07-04 09:53:26 +0200
commit509c8cae6381ec46af7c8303eb92fda6ce496a4a (patch)
tree653f7f44df842f9d7135decd89467879a0098c50 /app/views
parent57d571230eeb2d3ede57e640b640f17c7a2298a2 (diff)
Dynamic OPML (#4407)
* Dynamic OPML draft #fix https://github.com/FreshRSS/FreshRSS/issues/4191 * Export dynamic OPML http://opml.org/spec2.opml#1629043127000 * Restart with simpler approach * Minor revert * Export dynamic OPML also for single feeds * Special category type for importing dynamic OPML * Parameter for excludeMutedFeeds * Details * More draft * i18n * Fix update * Draft manual import working * Working manual refresh * Draft automatic update * Working Web refresh + fixes * Import/export dynamic OPML settings * Annoying numerous lines in SQL logs * Fix minor JavaScript error * Fix auto adding new columns * Add require * Add missing 🗲 * Missing space * Disable adding new feeds to dynamic categories * Link from import * i18n typo * Improve theme icon function * Fix pink-dark
Diffstat (limited to 'app/views')
-rw-r--r--app/views/category/actualize.phtml1
-rw-r--r--app/views/category/refreshOpml.phtml1
-rw-r--r--app/views/helpers/category/update.phtml32
-rw-r--r--app/views/helpers/export/opml.phtml55
-rw-r--r--app/views/importExport/index.phtml9
-rw-r--r--app/views/index/opml.phtml3
-rw-r--r--app/views/javascript/actualize.phtml12
-rw-r--r--app/views/subscription/add.phtml40
-rw-r--r--app/views/subscription/index.phtml5
9 files changed, 136 insertions, 22 deletions
diff --git a/app/views/category/actualize.phtml b/app/views/category/actualize.phtml
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/app/views/category/actualize.phtml
@@ -0,0 +1 @@
+OK
diff --git a/app/views/category/refreshOpml.phtml b/app/views/category/refreshOpml.phtml
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/app/views/category/refreshOpml.phtml
@@ -0,0 +1 @@
+OK
diff --git a/app/views/helpers/category/update.phtml b/app/views/helpers/category/update.phtml
index 927010136..c08e6995a 100644
--- a/app/views/helpers/category/update.phtml
+++ b/app/views/helpers/category/update.phtml
@@ -1,6 +1,9 @@
<?php /** @var FreshRSS_View $this */ ?>
<div class="post">
- <h2><?= $this->category->name() ?></h2>
+ <h2>
+ <?= $this->category->name() ?>
+ <?php if ($this->category->kind() == FreshRSS_Category::KIND_DYNAMIC_OPML) { echo _i('opml-dyn'); } ?>
+ </h2>
<div>
<a href="<?= _url('index', 'index', 'get', 'c_' . $this->category->id()) ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
@@ -31,9 +34,36 @@
<div class="group-controls">
<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
+ </div>
+ </div>
+ <?php if (!$this->category->isDefault()): ?>
+ <legend><?= _t('sub.category.dynamic_opml') ?> <?= _i('opml-dyn') ?></legend>
+ <div class="form-group">
+ <label class="group-name" for="opml_url"><?= _t('sub.category.opml_url') ?></label>
+ <div class="group-controls">
+ <div class="stick">
+ <input id="opml_url" name="opml_url" type="url" autocomplete="off" class="long" data-disable-update="refreshOpml" value="<?= $this->category->attributes('opml_url') ?>" />
+ <button type="submit" class="btn" id="refreshOpml" formmethod="post" formaction="<?= _url('category', 'refreshOpml', 'id', $this->category->id()) ?>">
+ <?= _i('refresh') ?> <?= _t('gen.action.refresh_opml') ?>
+ </button>
+ <a class="btn open-url" target="_blank" rel="noreferrer" href="" data-input="opml_url" title="<?= _t('gen.action.open_url') ?>"><?= _i('link') ?></a>
+ </div>
+ <p class="help"><?= _i('help') ?> <?= _t('gen.short.blank_to_disable') ?></p>
+ <p class="help"><?= _i('help') ?> <?= _t('sub.category.dynamic_opml.help') ?></p>
+ </div>
+ </div>
+ <div class="form-group form-actions">
+ <div class="group-controls">
+ <button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
+ <button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
+ <button type="submit" class="btn btn-attention confirm"
+ data-str-confirm="<?= _t('gen.js.confirm_action_feed_cat') ?>"
+ formaction="<?= _url('category', 'empty', 'id', $this->category->id(), 'muted', 1) ?>"
+ formmethod="post"><?= _t('gen.action.delete_muted_feeds') ?></button>
</div>
</div>
+ <?php endif; ?>
<legend><?= _t('sub.category.archiving') ?></legend>
<?php
diff --git a/app/views/helpers/export/opml.phtml b/app/views/helpers/export/opml.phtml
index 64c02c302..f99754138 100644
--- a/app/views/helpers/export/opml.phtml
+++ b/app/views/helpers/export/opml.phtml
@@ -1,21 +1,14 @@
<?php
-/** @var FreshRSS_View $this */
-$opml_array = array(
- 'head' => array(
- 'title' => FreshRSS_Context::$system_conf->title,
- 'dateCreated' => date('D, d M Y H:i:s')
- ),
- 'body' => array()
-);
-
-foreach ($this->categories as $key => $cat) {
- $opml_array['body'][$key] = array(
- 'text' => htmlspecialchars_decode($cat->name(), ENT_QUOTES),
- '@outlines' => array()
- );
-
- foreach ($cat->feeds() as $feed) {
+/**
+ * @param array<FreshRSS_Feed> $feeds
+ */
+function feedsToOutlines($feeds, $excludeMutedFeeds = false): array {
+ $outlines = [];
+ foreach ($feeds as $feed) {
+ if ($feed->mute() && $excludeMutedFeeds) {
+ continue;
+ }
$outline = [
'text' => htmlspecialchars_decode($feed->name(), ENT_QUOTES),
'type' => FreshRSS_Export_Service::TYPE_RSS_ATOM,
@@ -47,8 +40,36 @@ foreach ($this->categories as $key => $cat) {
if ($feed->pathEntries() != '') {
$outline['frss:cssFullContent'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $feed->pathEntries()];
}
- $opml_array['body'][$key]['@outlines'][] = $outline;
+ $outlines[] = $outline;
}
+ return $outlines;
+}
+
+/** @var FreshRSS_View $this */
+
+$opml_array = array(
+ 'head' => array(
+ 'title' => FreshRSS_Context::$system_conf->title,
+ 'dateCreated' => date('D, d M Y H:i:s')
+ ),
+ 'body' => array()
+);
+
+if (!empty($this->categories)) {
+ foreach ($this->categories as $key => $cat) {
+ $outline = [
+ 'text' => htmlspecialchars_decode($cat->name(), ENT_QUOTES),
+ '@outlines' => feedsToOutlines($cat->feeds(), $this->excludeMutedFeeds),
+ ];
+ if ($cat->kind() === FreshRSS_Category::KIND_DYNAMIC_OPML) {
+ $outline['frss:opmlUrl'] = ['namespace' => FreshRSS_Export_Service::FRSS_NAMESPACE, 'value' => $cat->attributes('opml_url')];;
+ }
+ $opml_array['body'][$key] = $outline;
+ }
+}
+
+if (!empty($this->feeds)) {
+ $opml_array['body'][] = feedsToOutlines($this->feeds, $this->excludeMutedFeeds);
}
echo libopml_render($opml_array);
diff --git a/app/views/importExport/index.phtml b/app/views/importExport/index.phtml
index c5bc97446..adc236dc4 100644
--- a/app/views/importExport/index.phtml
+++ b/app/views/importExport/index.phtml
@@ -10,6 +10,15 @@
<h1><?= _t('sub.menu.import_export') ?></h1>
+ <h2><?= _t('sub.category.dynamic_opml') ?></h2>
+ <div class="form-group form-actions">
+ <div class="group-controls">
+ <ul>
+ <li><a href="<?= _url('subscription', 'add') ?>"><?= _t('sub.title.add_dynamic_opml') ?> <?= _i('opml-dyn') ?></a></li>
+ </ul>
+ </div>
+ </div>
+
<h2><?= _t('sub.import_export.import') ?></h2>
<form method="post" action="<?= _url('importExport', 'import') ?>" enctype="multipart/form-data">
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
diff --git a/app/views/index/opml.phtml b/app/views/index/opml.phtml
new file mode 100644
index 000000000..69dace924
--- /dev/null
+++ b/app/views/index/opml.phtml
@@ -0,0 +1,3 @@
+<?php
+/** @var FreshRSS_View $this */
+$this->renderHelper('export/opml');
diff --git a/app/views/javascript/actualize.phtml b/app/views/javascript/actualize.phtml
index c154137f6..73890dd40 100644
--- a/app/views/javascript/actualize.phtml
+++ b/app/views/javascript/actualize.phtml
@@ -1,5 +1,14 @@
-<?php /** @var FreshRSS_View $this */ ?>
<?php
+/** @var FreshRSS_View $this */
+
+$categories = [];
+foreach ($this->categories as $category) {
+ $categories[] = [
+ 'url' => Minz_Url::display(array('c' => 'category', 'a' => 'refreshOpml', 'params' => array('id' => $category->id(), 'ajax' => '1')), 'php'),
+ 'title' => $category->name(),
+ ];
+}
+
$feeds = array();
foreach ($this->feeds as $feed) {
$feeds[] = array(
@@ -8,6 +17,7 @@ foreach ($this->feeds as $feed) {
);
}
echo json_encode(array(
+ 'categories' => $categories,
'feeds' => $feeds,
'feedback_no_refresh' => _t('feedback.sub.feed.no_refresh'),
'feedback_actualize' => _t('feedback.sub.actualize'),
diff --git a/app/views/subscription/add.phtml b/app/views/subscription/add.phtml
index 9e5b2a399..5aadc350b 100644
--- a/app/views/subscription/add.phtml
+++ b/app/views/subscription/add.phtml
@@ -15,7 +15,7 @@
<div class="form-group">
<label class="group-name" for="new-category"><?= _t('sub.category') ?></label>
<div class="group-controls">
- <input id="new-category" name="new-category" type="text" autocomplete="off"/>
+ <input id="new-category" name="new-category" type="text" required="required" autocomplete="off" />
</div>
</div>
@@ -45,7 +45,12 @@
<label class="group-name" for="category"><?= _t('sub.category') ?></label>
<div class="group-controls">
<select name="category" id="category">
- <?php foreach ($this->categories as $cat) { ?>
+ <?php
+ foreach ($this->categories as $cat) {
+ if ($cat->kind() == FreshRSS_Category::KIND_DYNAMIC_OPML) {
+ continue;
+ }
+ ?>
<option value="<?= $cat->id() ?>"<?= $cat->id() == ( Minz_Request::param('cat_id') ?: 1 ) ? ' selected="selected"' : '' ?>>
<?= $cat->name() ?>
</option>
@@ -218,4 +223,35 @@
</div>
</div>
</form>
+
+ <h2>
+ <?= _t('sub.title.add_dynamic_opml') ?>
+ <?= _i('opml-dyn') ?>
+ </h2>
+ <form action="<?= _url('category', 'create') ?>" method="post">
+ <input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
+ <div class="form-group">
+ <label class="group-name" for="new-category"><?= _t('sub.category') ?></label>
+ <div class="group-controls">
+ <input id="new-category" name="new-category" type="text" required="required" autocomplete="off" />
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="group-name" for="opml_url"><?= _t('sub.category.opml_url') ?></label>
+ <div class="group-controls">
+ <div class="stick">
+ <input id="opml_url" name="opml_url" type="url" required="required" autocomplete="off" class="long" />
+ <a class="btn open-url" target="_blank" rel="noreferrer" href="" data-input="opml_url" title="<?= _t('gen.action.open_url') ?>"><?= _i('link') ?></a>
+ </div>
+ <p class="help"><?= _i('help') ?> <?= _t('sub.category.dynamic_opml.help') ?></p>
+ </div>
+ </div>
+
+ <div class="form-group form-actions">
+ <div class="group-controls">
+ <button type="submit" class="btn btn-important"><?= _t('gen.action.add') ?></button>
+ </div>
+ </div>
+ </form>
</main>
diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml
index 139bb2de0..8b2411edf 100644
--- a/app/views/subscription/index.phtml
+++ b/app/views/subscription/index.phtml
@@ -36,6 +36,7 @@
<div class="box-title">
<a class="configure open-slider" href="<?= _url('subscription', 'category', 'id', $cat->id()) ?>"><?= _i('configure') ?></a>
<?= $cat->name() ?>
+ <?php if ($cat->kind() == FreshRSS_Category::KIND_DYNAMIC_OPML) { echo _i('opml-dyn'); } ?>
</div>
<ul class="box-content drop-zone" dropzone="move" data-cat-id="<?= $cat->id() ?>">
<?php
@@ -60,7 +61,9 @@
?>
<li class="item feed disabled"><div class="alert-warn"><?= _t('sub.category.empty') ?></div></li>
<?php } ?>
- <li class="item feed">✚ <a href="<?= _url('subscription', 'add', 'cat_id', $cat->id()) ?>"><?= _t('sub.feed.add') ?></a></li>
+ <?php if ($cat->kind() != FreshRSS_Category::KIND_DYNAMIC_OPML): ?>
+ <li class="item feed">✚ <a href="<?= _url('subscription', 'add', 'cat_id', $cat->id()) ?>"><?= _t('sub.feed.add') ?></a></li>
+ <?php endif; ?>
</ul>
</div>
<?php } ?>