mirror of
https://codeberg.org/Reuh/feather.git
synced 2025-10-27 10:09:32 +00:00
feat: allow marking items as unread by restoring their files and add option to not write read articles even when synced
This commit is contained in:
parent
48c2c0f850
commit
b5474cb376
4 changed files with 33 additions and 17 deletions
|
|
@ -82,13 +82,16 @@ class FeatherApp:
|
||||||
to_mark_as_read = []
|
to_mark_as_read = []
|
||||||
to_mark_as_unread = []
|
to_mark_as_unread = []
|
||||||
for article in self.iter_articles():
|
for article in self.iter_articles():
|
||||||
if not article.has_html():
|
has_html = article.has_html()
|
||||||
if article.unread:
|
if article.unread and not has_html:
|
||||||
to_mark_as_read.append(article)
|
to_mark_as_read.append(article)
|
||||||
marked_as_read += 1
|
marked_as_read += 1
|
||||||
else:
|
elif not article.unread and (
|
||||||
to_mark_as_unread.append(article)
|
(config.write_read_articles and not has_html)
|
||||||
marked_as_unread += 1
|
or (not config.write_read_articles and has_html)
|
||||||
|
):
|
||||||
|
to_mark_as_unread.append(article)
|
||||||
|
marked_as_unread += 1
|
||||||
|
|
||||||
if len(to_mark_as_read) == len(to_mark_as_unread) == 0:
|
if len(to_mark_as_read) == len(to_mark_as_unread) == 0:
|
||||||
return # nothing to do
|
return # nothing to do
|
||||||
|
|
@ -260,6 +263,7 @@ class FeatherApp:
|
||||||
"""Regenerate all local files using local data only"""
|
"""Regenerate all local files using local data only"""
|
||||||
for article in self.iter_articles():
|
for article in self.iter_articles():
|
||||||
article.regenerate()
|
article.regenerate()
|
||||||
|
self.remove_empty_categories()
|
||||||
|
|
||||||
def clear_data(self):
|
def clear_data(self):
|
||||||
"""Delete all local data"""
|
"""Delete all local data"""
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ password = "password"
|
||||||
# Set to 0 to let Feather choose (200 for ttrss, 1000 for googlereader).
|
# Set to 0 to let Feather choose (200 for ttrss, 1000 for googlereader).
|
||||||
# Can be set through the environment variable SERVER_ARTICLES_PER_REQUEST.
|
# Can be set through the environment variable SERVER_ARTICLES_PER_REQUEST.
|
||||||
articles_per_request = 0
|
articles_per_request = 0
|
||||||
# Set to true to only sync unread articles; Feather will not retrieve or store any read article.
|
# Set to true to only sync unread articles; Feather will not retrieve any read article from the server.
|
||||||
# Can be set through the environment variable SERVER_ONLY_SYNC_UNREAD_ARTICLES.
|
# Can be set through the environment variable SERVER_ONLY_SYNC_UNREAD_ARTICLES.
|
||||||
only_sync_unread_articles = true
|
only_sync_unread_articles = true
|
||||||
|
|
||||||
|
|
@ -36,6 +36,13 @@ data = "data"
|
||||||
reader = "reader"
|
reader = "reader"
|
||||||
|
|
||||||
[html]
|
[html]
|
||||||
|
# If set to true, Feather will also generate articles files for read articles.
|
||||||
|
# Also remember to set server.only_sync_unread_articles = false; otherwise this will do nothing.
|
||||||
|
# The the mark-as-unread behavior will also change depending on this value:
|
||||||
|
# - if false, marking an article as unread requires its file to be recreated/restored from the trash;
|
||||||
|
# - if true, marking an article as unread requires deleting its article file (same as mark-as-read).
|
||||||
|
# Can be set through the environment variable HTML_WRITE_READ_ARTICLES.
|
||||||
|
write_read_articles = false
|
||||||
# Template used for generating article HTML files. All templates are Jinja2 templates.
|
# Template used for generating article HTML files. All templates are Jinja2 templates.
|
||||||
# Available fields:
|
# Available fields:
|
||||||
# - id: article id (int | str)
|
# - id: article id (int | str)
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ class Config:
|
||||||
self.timezone: ZoneInfo = ZoneInfo(str(get_config("datetime", "timezone")))
|
self.timezone: ZoneInfo = ZoneInfo(str(get_config("datetime", "timezone")))
|
||||||
self.time_format: str = str(get_config("datetime", "format"))
|
self.time_format: str = str(get_config("datetime", "format"))
|
||||||
|
|
||||||
|
self.write_read_articles: bool = bool(get_config("html", "write_read_articles"))
|
||||||
self.article_template: Template = Template(
|
self.article_template: Template = Template(
|
||||||
str(get_config("html", "article_template")), autoescape=True
|
str(get_config("html", "article_template")), autoescape=True
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -234,8 +234,11 @@ class Article(ABC):
|
||||||
def _delete_html(self, missing_ok=False):
|
def _delete_html(self, missing_ok=False):
|
||||||
"""Delete the HTML file associated with this article."""
|
"""Delete the HTML file associated with this article."""
|
||||||
# Delete a HTML file for a JSON object
|
# Delete a HTML file for a JSON object
|
||||||
html_path = self.config.html_root / self.html_path
|
if self.html_path is None:
|
||||||
html_path.unlink(missing_ok=missing_ok)
|
return
|
||||||
|
else:
|
||||||
|
html_path = self.config.html_root / self.html_path
|
||||||
|
html_path.unlink(missing_ok=missing_ok)
|
||||||
|
|
||||||
def has_html(self) -> bool:
|
def has_html(self) -> bool:
|
||||||
"""Check if the HTML file associated with the article exists on disk."""
|
"""Check if the HTML file associated with the article exists on disk."""
|
||||||
|
|
@ -251,13 +254,14 @@ class Article(ABC):
|
||||||
|
|
||||||
def write(self, recompute_paths=False):
|
def write(self, recompute_paths=False):
|
||||||
"""Write all the files associated with this article to disk."""
|
"""Write all the files associated with this article to disk."""
|
||||||
try:
|
if self.unread or self.config.write_read_articles:
|
||||||
self._write_html(recompute_path=recompute_paths)
|
try:
|
||||||
except FileExistsError:
|
self._write_html(recompute_path=recompute_paths)
|
||||||
raise
|
except FileExistsError:
|
||||||
except:
|
raise
|
||||||
self._delete_html(missing_ok=True)
|
except:
|
||||||
raise
|
self._delete_html(missing_ok=True)
|
||||||
|
raise
|
||||||
try:
|
try:
|
||||||
self._write_json(recompute_path=recompute_paths)
|
self._write_json(recompute_path=recompute_paths)
|
||||||
except FileExistsError:
|
except FileExistsError:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue