diff options
| author | 2022-07-04 09:53:26 +0200 | |
|---|---|---|
| committer | 2022-07-04 09:53:26 +0200 | |
| commit | 509c8cae6381ec46af7c8303eb92fda6ce496a4a (patch) | |
| tree | 653f7f44df842f9d7135decd89467879a0098c50 /app/views | |
| parent | 57d571230eeb2d3ede57e640b640f17c7a2298a2 (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.phtml | 1 | ||||
| -rw-r--r-- | app/views/category/refreshOpml.phtml | 1 | ||||
| -rw-r--r-- | app/views/helpers/category/update.phtml | 32 | ||||
| -rw-r--r-- | app/views/helpers/export/opml.phtml | 55 | ||||
| -rw-r--r-- | app/views/importExport/index.phtml | 9 | ||||
| -rw-r--r-- | app/views/index/opml.phtml | 3 | ||||
| -rw-r--r-- | app/views/javascript/actualize.phtml | 12 | ||||
| -rw-r--r-- | app/views/subscription/add.phtml | 40 | ||||
| -rw-r--r-- | app/views/subscription/index.phtml | 5 |
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 } ?> |
