add progress to note
This commit is contained in:
parent
3eafcd3ec8
commit
7157f3b0b0
22 changed files with 779 additions and 192 deletions
|
@ -90,18 +90,25 @@
|
|||
{% include "action_open_post.html" with post=note.latest_post %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<h6>{{ note.title|default:'' }}</h6>
|
||||
<p>{{ note.content|linebreaks }}</p>
|
||||
<div>
|
||||
{% if note.title %}<h6>{{ note.title|default:'' }}</h6>{% endif %}
|
||||
<p>
|
||||
{% if note.progress_value %}<span class="tag-list"><span><a>{{ note.progress_display }}</a></span></span>{% endif %}
|
||||
{{ note.content|linebreaksbr }}
|
||||
<div class="attachments">
|
||||
{% for attachment in note.attachments %}
|
||||
{% if attachment.type == 'image' %}
|
||||
<img src="{{ attachment.url }}"
|
||||
<a href="#img_{{ note.uuid }}_{{ loop.index }}">
|
||||
<img src="{{ attachment.preview_url }}"
|
||||
alt="image attachment"
|
||||
style="max-height:6em;
|
||||
max-width:50%">
|
||||
class="preview">
|
||||
</a>
|
||||
<a href="#" class="lightbox" id="img_{{ note.uuid }}_{{ loop.index }}">
|
||||
<span style="background-image: url('{{ attachment.url }}')"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</p>
|
||||
{% endfor %}
|
||||
</section>
|
||||
<section>
|
||||
|
|
|
@ -3,11 +3,23 @@ import json
|
|||
import django.contrib.postgres.forms as postgres
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import ModelForm
|
||||
from django.utils import formats
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
|
||||
|
||||
class NeoModelForm(ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# if "uuid" in self.fields:
|
||||
# if self.instance and self.instance.pk:
|
||||
# self.fields["uuid"].initial = self.instance.uuid
|
||||
for visible in self.visible_fields():
|
||||
w = visible.field.widget
|
||||
w.attrs["class"] = "widget " + w.__class__.__name__.lower()
|
||||
|
||||
|
||||
class PreviewImageInput(forms.FileInput):
|
||||
template_name = "widgets/image.html"
|
||||
|
||||
|
|
|
@ -86,6 +86,16 @@ dialog {
|
|||
|
||||
article {
|
||||
padding-bottom: 1em;
|
||||
form {
|
||||
overflow: hidden;
|
||||
input[type="submit"] {
|
||||
margin-top: 1em;
|
||||
}
|
||||
div.widget.radioselect {
|
||||
display: flex;
|
||||
grid-column-gap: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type="date"] {
|
||||
|
|
26
common/static/scss/_lightbox.scss
Normal file
26
common/static/scss/_lightbox.scss
Normal file
|
@ -0,0 +1,26 @@
|
|||
.lightbox {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 1em;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
-webkit-backdrop-filter: var(--pico-modal-overlay-backdrop-filter);
|
||||
}
|
||||
|
||||
.lightbox:target {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lightbox span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
|
@ -27,3 +27,10 @@ section.replies {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attachements {
|
||||
img.preview {
|
||||
max-height: 6em;
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
@import '_form.scss';
|
||||
@import '_post.scss';
|
||||
@import '_l10n.scss';
|
||||
@import '_lightbox.scss';
|
||||
|
|
|
@ -159,7 +159,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -205,7 +215,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -233,7 +253,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -265,7 +295,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -316,7 +356,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -343,7 +393,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -382,7 +442,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -415,7 +485,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -451,7 +531,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -596,7 +686,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
@ -656,7 +756,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
|
|
@ -27,7 +27,17 @@ class Migration(migrations.Migration):
|
|||
to="journal.piece",
|
||||
),
|
||||
),
|
||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
||||
(
|
||||
"visibility",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Public"),
|
||||
(1, "Followers Only"),
|
||||
(2, "Mentioned Only"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_time",
|
||||
models.DateTimeField(default=django.utils.timezone.now),
|
||||
|
|
44
journal/migrations/0003_note_progress.py
Normal file
44
journal/migrations/0003_note_progress.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Generated by Django 4.2.13 on 2024-06-14 22:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("journal", "0002_note"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="progress_type",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("page", "Page"),
|
||||
("chapter", "Chapter"),
|
||||
("part", "Part"),
|
||||
("episode", "Episode"),
|
||||
("track", "Track"),
|
||||
("cycle", "Cycle"),
|
||||
("timestamp", "Timestamp"),
|
||||
("percentage", "Percentage"),
|
||||
],
|
||||
default=None,
|
||||
max_length=50,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="progress_value",
|
||||
field=models.CharField(blank=True, default=None, max_length=500, null=True),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name="note",
|
||||
index=models.Index(
|
||||
fields=["owner", "item", "created_time"],
|
||||
name="journal_not_owner_i_7f9460_idx",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -434,8 +434,8 @@ class PieceInteraction(models.Model):
|
|||
class Content(Piece):
|
||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||
visibility = models.PositiveSmallIntegerField(
|
||||
default=0
|
||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore
|
||||
choices=VisibilityType.choices, default=0, null=False
|
||||
) # type:ignore
|
||||
created_time = models.DateTimeField(default=timezone.now)
|
||||
edited_time = models.DateTimeField(auto_now=True)
|
||||
metadata = models.JSONField(default=dict)
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.utils import timezone
|
|||
from catalog.models import Item, ItemCategory
|
||||
from users.models import APIdentity
|
||||
|
||||
from .common import Piece
|
||||
from .common import Piece, VisibilityType
|
||||
|
||||
list_add = django.dispatch.Signal()
|
||||
list_remove = django.dispatch.Signal()
|
||||
|
@ -25,8 +25,8 @@ class List(Piece):
|
|||
items: "models.ManyToManyField[Item, List]"
|
||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||
visibility = models.PositiveSmallIntegerField(
|
||||
default=0
|
||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore
|
||||
choices=VisibilityType.choices, default=0, null=False
|
||||
) # type:ignore
|
||||
created_time = models.DateTimeField(default=timezone.now)
|
||||
edited_time = models.DateTimeField(auto_now=True)
|
||||
metadata = models.JSONField(default=dict)
|
||||
|
@ -151,8 +151,8 @@ class ListMember(Piece):
|
|||
parent: models.ForeignKey["ListMember", "List"]
|
||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||
visibility = models.PositiveSmallIntegerField(
|
||||
default=0
|
||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore[reportAssignmentType]
|
||||
choices=VisibilityType.choices, default=0, null=False
|
||||
) # type:ignore
|
||||
created_time = models.DateTimeField(default=timezone.now)
|
||||
edited_time = models.DateTimeField(auto_now=True)
|
||||
metadata = models.JSONField(default=dict)
|
||||
|
|
|
@ -5,14 +5,14 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from users.models import APIdentity
|
||||
|
||||
from .common import Piece
|
||||
from .common import Piece, VisibilityType
|
||||
|
||||
|
||||
class Like(Piece): # TODO remove
|
||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||
visibility = models.PositiveSmallIntegerField(
|
||||
default=0
|
||||
) # 0: Public / 1: Follower only / 2: Self only # type: ignore
|
||||
choices=VisibilityType.choices, default=0, null=False
|
||||
) # type:ignore
|
||||
created_time = models.DateTimeField(default=timezone.now)
|
||||
edited_time = models.DateTimeField(auto_now=True)
|
||||
target = models.ForeignKey(Piece, on_delete=models.CASCADE, related_name="likes")
|
||||
|
|
|
@ -108,7 +108,9 @@ class Mark:
|
|||
|
||||
@cached_property
|
||||
def notes(self):
|
||||
return Note.objects.filter(owner=self.owner, item=self.item)
|
||||
return Note.objects.filter(owner=self.owner, item=self.item).order_by(
|
||||
"-created_time"
|
||||
)
|
||||
# post_ids = PiecePost.objects.filter(
|
||||
# piece__note__owner_id=self.owner.pk, piece__note__item_id=self.item.pk
|
||||
# ).values_list("post_id", flat=True)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import re
|
||||
from functools import cached_property
|
||||
from typing import override
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
|
||||
from catalog.models import Item
|
||||
from mastodon.api import delete_toot_later
|
||||
from takahe.utils import Takahe
|
||||
|
||||
|
@ -11,17 +14,74 @@ from .common import Content
|
|||
from .renderers import render_text
|
||||
from .shelf import ShelfMember
|
||||
|
||||
_progress = re.compile(
|
||||
r"^\s*(?P<prefix>(p|pg|page|ch|chapter|pt|part|e|ep|episode|trk|track|cycle))?(\s|\.|#)*(?P<value>(\d[\d\:\.\-]*\d|\d))\s*(?P<postfix>(%))?\s*(\s|\n|\.|:)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
_number = re.compile(r"^[\s\d\:\.]+$")
|
||||
|
||||
|
||||
class Note(Content):
|
||||
class ProgressType(models.TextChoices):
|
||||
PAGE = "page", _("Page")
|
||||
CHAPTER = "chapter", _("Chapter")
|
||||
# SECTION = "section", _("Section")
|
||||
# VOLUME = "volume", _("Volume")
|
||||
PART = "part", _("Part")
|
||||
EPISODE = "episode", _("Episode")
|
||||
TRACK = "track", _("Track")
|
||||
CYCLE = "cycle", _("Cycle")
|
||||
TIMESTAMP = "timestamp", _("Timestamp")
|
||||
PERCENTAGE = "percentage", _("Percentage")
|
||||
|
||||
title = models.TextField(blank=True, null=True, default=None)
|
||||
content = models.TextField(blank=False, null=False)
|
||||
sensitive = models.BooleanField(default=False, null=False)
|
||||
attachments = models.JSONField(default=list)
|
||||
progress_type = models.CharField(
|
||||
max_length=50,
|
||||
choices=ProgressType.choices,
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None,
|
||||
)
|
||||
progress_value = models.CharField(
|
||||
max_length=500, blank=True, null=True, default=None
|
||||
)
|
||||
_progress_display_template = {
|
||||
ProgressType.PAGE: _("Page {value}"),
|
||||
ProgressType.CHAPTER: _("Chapter {value}"),
|
||||
# ProgressType.SECTION: _("Section {value}"),
|
||||
# ProgressType.VOLUME: _("Volume {value}"),
|
||||
ProgressType.PART: _("Part {value}"),
|
||||
ProgressType.EPISODE: _("Episode {value}"),
|
||||
ProgressType.TRACK: _("Track {value}"),
|
||||
ProgressType.CYCLE: _("Cycle {value}"),
|
||||
ProgressType.PERCENTAGE: "{value}%",
|
||||
ProgressType.TIMESTAMP: "{value}",
|
||||
}
|
||||
|
||||
class Meta:
|
||||
indexes = [models.Index(fields=["owner", "item", "created_time"])]
|
||||
|
||||
@property
|
||||
def html(self):
|
||||
return render_text(self.content)
|
||||
|
||||
@property
|
||||
def progress_display(self) -> str:
|
||||
if not self.progress_value:
|
||||
return ""
|
||||
if not self.progress_type:
|
||||
return str(self.progress_value)
|
||||
tpl = Note._progress_display_template.get(self.progress_type, None)
|
||||
if not tpl:
|
||||
return str(self.progress_value)
|
||||
if _number.match(self.progress_value):
|
||||
return tpl.format(value=self.progress_value)
|
||||
return self.progress_type.display + ": " + self.progress_value
|
||||
|
||||
@property
|
||||
def ap_object(self):
|
||||
d = {
|
||||
|
@ -36,6 +96,11 @@ class Note(Content):
|
|||
"withRegardTo": self.item.absolute_url,
|
||||
"href": self.absolute_url,
|
||||
}
|
||||
if self.progress_value:
|
||||
d["progress"] = {
|
||||
"type": self.progress_type,
|
||||
"value": self.progress_value,
|
||||
}
|
||||
return d
|
||||
|
||||
@override
|
||||
|
@ -47,6 +112,17 @@ class Note(Content):
|
|||
"sensitive": obj.get("sensitive", post.sensitive),
|
||||
"attachments": [],
|
||||
}
|
||||
progress = obj.get("progress", {})
|
||||
if progress.get("type"):
|
||||
params["progress_type"] = progress.get("type")
|
||||
if progress.get("value"):
|
||||
params["progress_value"] = progress.get("value")
|
||||
if post.local:
|
||||
progress_type, progress_value = cls.extract_progress(params["content"])
|
||||
print(progress_type, progress_value)
|
||||
if progress_value:
|
||||
params["progress_type"] = progress_type
|
||||
params["progress_value"] = progress_value
|
||||
if post:
|
||||
for atta in post.attachments.all():
|
||||
params["attachments"].append(
|
||||
|
@ -103,3 +179,79 @@ class Note(Content):
|
|||
),
|
||||
# not passing "attachments" so it won't change
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def extract_progress(cls, content):
|
||||
m = _progress.match(content)
|
||||
if m and m["value"]:
|
||||
typ_ = "percentage" if m["postfix"] == "%" else m["prefix"]
|
||||
match typ_:
|
||||
case "p" | "pg" | "page":
|
||||
typ = Note.ProgressType.PAGE
|
||||
case "ch" | "chapter":
|
||||
typ = Note.ProgressType.CHAPTER
|
||||
# case "vol" | "volume":
|
||||
# typ = ProgressType.VOLUME
|
||||
# case "section":
|
||||
# typ = ProgressType.SECTION
|
||||
case "pt" | "part":
|
||||
typ = Note.ProgressType.PART
|
||||
case "e" | "ep" | "episode":
|
||||
typ = Note.ProgressType.EPISODE
|
||||
case "trk" | "track":
|
||||
typ = Note.ProgressType.TRACK
|
||||
case "cycle":
|
||||
typ = Note.ProgressType.CYCLE
|
||||
case "percentage":
|
||||
typ = Note.ProgressType.PERCENTAGE
|
||||
case _:
|
||||
typ = "timestamp" if ":" in m["value"] else None
|
||||
return typ, m["value"]
|
||||
return None, None
|
||||
|
||||
@classmethod
|
||||
def get_progress_types_by_item(cls, item: Item):
|
||||
match item.__class__.__name__:
|
||||
case "Edition":
|
||||
v = [
|
||||
Note.ProgressType.PAGE,
|
||||
Note.ProgressType.CHAPTER,
|
||||
Note.ProgressType.PERCENTAGE,
|
||||
]
|
||||
case "TVShow" | "TVSeason":
|
||||
v = [
|
||||
Note.ProgressType.PART,
|
||||
Note.ProgressType.EPISODE,
|
||||
Note.ProgressType.PERCENTAGE,
|
||||
]
|
||||
case "Movie":
|
||||
v = [
|
||||
Note.ProgressType.PART,
|
||||
Note.ProgressType.TIMESTAMP,
|
||||
Note.ProgressType.PERCENTAGE,
|
||||
]
|
||||
case "Podcast":
|
||||
v = [
|
||||
Note.ProgressType.EPISODE,
|
||||
]
|
||||
case "TVEpisode" | "PodcastEpisode":
|
||||
v = []
|
||||
case "Album":
|
||||
v = [
|
||||
Note.ProgressType.TRACK,
|
||||
Note.ProgressType.TIMESTAMP,
|
||||
Note.ProgressType.PERCENTAGE,
|
||||
]
|
||||
case "Game":
|
||||
v = [
|
||||
Note.ProgressType.CYCLE,
|
||||
]
|
||||
case "Performance" | "PerformanceProduction":
|
||||
v = [
|
||||
Note.ProgressType.PART,
|
||||
Note.ProgressType.TIMESTAMP,
|
||||
Note.ProgressType.PERCENTAGE,
|
||||
]
|
||||
case _:
|
||||
v = []
|
||||
return v
|
||||
|
|
|
@ -16,50 +16,23 @@
|
|||
<strong>{% trans 'Note' %} - {{ item.display_title }}</strong>
|
||||
</header>
|
||||
<div>
|
||||
<form action="{% url 'journal:note' item.uuid %}" method="post">
|
||||
<form action="{% url 'journal:note' item.uuid %}"
|
||||
method="post"
|
||||
onsubmit="return !!$('#{{ form.content.id_for_label }}').val() || confirm('{% trans "Note with empty content will be deleted, sure to continue?" %}');;">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="uuid" value="{{ note.uuid|default:'' }}">
|
||||
<textarea name="content" cols="40" rows="10" placeholder="" id="id_content">{{ note.content|default:'' }}</textarea>
|
||||
{{ form.uuid }}
|
||||
<div class="grid">
|
||||
<div>
|
||||
<fieldset>
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="0"
|
||||
required=""
|
||||
id="id_visibility_0"
|
||||
{% if note.visibility == 0 or not note %}checked{% endif %}>
|
||||
<label for="id_visibility_0">{% trans "Public" %}</label>
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="1"
|
||||
required=""
|
||||
id="id_visibility_1"
|
||||
{% if note.visibility == 1 %}checked{% endif %}>
|
||||
<label for="id_visibility_1">{% trans "Followers Only" %}</label>
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="2"
|
||||
required=""
|
||||
id="id_visibility_2"
|
||||
{% if note.visibility == 2 %}checked{% endif %}>
|
||||
<label for="id_visibility_2">{% trans "Mentioned Only" %}</label>
|
||||
</fieldset>
|
||||
<div>{{ form.progress_type }}</div>
|
||||
<div>{{ form.progress_value }}</div>
|
||||
</div>
|
||||
{{ form.content }}
|
||||
{{ form.title }}
|
||||
<div class="grid">
|
||||
<div>{{ form.visibility }}</div>
|
||||
<div>
|
||||
<fieldset>
|
||||
{% if request.user.mastodon_acct %}
|
||||
<label for="id_share_to_mastodon">
|
||||
<input role="switch"
|
||||
type="checkbox"
|
||||
name="share_to_mastodon"
|
||||
id="id_share_to_mastodon"
|
||||
value="1"
|
||||
{% if request.user.preference.mastodon_default_repost %}checked{% endif %}>
|
||||
{% trans "Repost to timeline" %}
|
||||
<label for="{{ form.share_to_mastodon.id_for_label }}">
|
||||
{{ form.share_to_mastodon }} {{ form.share_to_mastodon.label }}
|
||||
</label>
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -25,13 +25,17 @@
|
|||
</span>
|
||||
<div>{{ post.summary|default:'' }}</div>
|
||||
<div {% if post.summary or post.sensitive %}class="spoiler" _="on click toggle .revealed on me"{% endif %}>
|
||||
<div>
|
||||
<div class="attachments">
|
||||
{% for attachment in post.attachments.all %}
|
||||
{% if attachment.is_image %}
|
||||
<img src="{{ attachment.full_url.relative }}"
|
||||
alt="attachment.file_display_name"
|
||||
style="max-height:6em;
|
||||
max-width:50%">
|
||||
<a href="#img_{{ post.pk }}_{{ loop.index }}">
|
||||
<img src="{{ attachment.thumbnail_url.relative }}"
|
||||
alt="image attachment"
|
||||
class="preview">
|
||||
</a>
|
||||
<a href="#" class="lightbox" id="img_{{ post.pk }}_{{ loop.index }}">
|
||||
<span style="background-image: url('{{ attachment.full_url.relative }}')"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -21,8 +21,8 @@ urlpatterns = [
|
|||
path("wish/<str:item_uuid>", wish, name="wish"),
|
||||
path("mark/<str:item_uuid>", mark, name="mark"),
|
||||
path("comment/<str:item_uuid>", comment, name="comment"),
|
||||
path("note/<str:item_uuid>", note, name="note"),
|
||||
path("note/<str:item_uuid>/<str:note_uuid>", note, name="note"),
|
||||
path("item/<str:item_uuid>/note", note_edit, name="note"),
|
||||
path("item/<str:item_uuid>/note/<str:note_uuid>", note_edit, name="note"),
|
||||
path("piece/<str:piece_uuid>/replies", piece_replies, name="piece_replies"),
|
||||
path("post/<int:post_id>/replies", post_replies, name="post_replies"),
|
||||
path("post/<int:post_id>/reply", post_reply, name="post_reply"),
|
||||
|
|
|
@ -16,7 +16,8 @@ from .collection import (
|
|||
user_liked_collection_list,
|
||||
)
|
||||
from .common import piece_delete
|
||||
from .mark import comment, mark, mark_log, note, user_mark_list, wish
|
||||
from .mark import comment, mark, mark_log, user_mark_list, wish
|
||||
from .note import note_edit
|
||||
from .post import (
|
||||
piece_replies,
|
||||
post_boost,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from datetime import datetime
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
|
@ -13,10 +14,8 @@ from loguru import logger
|
|||
|
||||
from catalog.models import *
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||
from mastodon.api import boost_toot_later
|
||||
from takahe.utils import Takahe
|
||||
|
||||
from ..models import Comment, Mark, Note, ShelfManager, ShelfType, TagManager
|
||||
from ..models import Comment, Mark, ShelfManager, ShelfType, TagManager
|
||||
from .common import render_list, render_relogin, target_identity_required
|
||||
|
||||
PAGE_SIZE = 10
|
||||
|
@ -190,53 +189,6 @@ def comment(request: AuthedHttpRequest, item_uuid):
|
|||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def note(request: AuthedHttpRequest, item_uuid: str, note_uuid: str = ""):
|
||||
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
||||
note_uuid = request.POST.get("uuid", note_uuid)
|
||||
note = None
|
||||
content = request.POST.get("content")
|
||||
if note_uuid:
|
||||
note = get_object_or_404(
|
||||
Note, owner=request.user.identity, item=item, uid=get_uuid_or_404(note_uuid)
|
||||
)
|
||||
if request.method == "GET":
|
||||
return render(
|
||||
request,
|
||||
"note.html",
|
||||
{
|
||||
"item": item,
|
||||
"note": note,
|
||||
},
|
||||
)
|
||||
else:
|
||||
if request.POST.get("delete", default=False) or not content:
|
||||
if not note:
|
||||
raise Http404(_("Content not found"))
|
||||
note.delete()
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
share_to_mastodon = bool(request.POST.get("share_to_mastodon", default=False))
|
||||
visibility = int(request.POST.get("visibility", default=0))
|
||||
delete_existing_post = False
|
||||
if note:
|
||||
delete_existing_post = visibility != note.visibility
|
||||
note.content = content
|
||||
note.visibility = visibility
|
||||
note.save()
|
||||
else:
|
||||
note = Note.objects.create(
|
||||
owner=request.user.identity,
|
||||
item=item,
|
||||
content=content,
|
||||
visibility=visibility,
|
||||
)
|
||||
note.sync_to_timeline(delete_existing=delete_existing_post)
|
||||
if share_to_mastodon:
|
||||
note.sync_to_mastodon(delete_existing=delete_existing_post)
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
|
||||
|
||||
def user_mark_list(request: AuthedHttpRequest, user_name, shelf_type, item_category):
|
||||
return render_list(
|
||||
request, user_name, "mark", shelf_type=shelf_type, item_category=item_category
|
||||
|
|
110
journal/views/note.py
Normal file
110
journal/views/note.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from catalog.models import Item
|
||||
from common.forms import NeoModelForm
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||
|
||||
from ..models import Note
|
||||
from ..models.common import VisibilityType
|
||||
|
||||
|
||||
class NoteForm(NeoModelForm):
|
||||
# _progress_choices = [
|
||||
# ("", _("Progress Type (optional)"))
|
||||
# ] + Note.ProgressType.choices
|
||||
# progress_type = forms.ChoiceField(choices=_progress_choices, required=False)
|
||||
visibility = forms.ChoiceField(
|
||||
widget=forms.RadioSelect(), choices=VisibilityType.choices, initial=0
|
||||
)
|
||||
share_to_mastodon = forms.BooleanField(
|
||||
label=_("Post to Fediverse"), initial=True, required=False
|
||||
)
|
||||
uuid = forms.CharField(widget=forms.HiddenInput(), required=False)
|
||||
# content = forms.CharField(required=False, widget=forms.Textarea)
|
||||
|
||||
class Meta:
|
||||
model = Note
|
||||
fields = [
|
||||
"id",
|
||||
"title",
|
||||
"content",
|
||||
"visibility",
|
||||
"progress_type",
|
||||
"progress_value",
|
||||
"sensitive",
|
||||
]
|
||||
widgets = {
|
||||
"progress_value": forms.TextInput(
|
||||
attrs={"placeholder": _("Progress (optional)")}
|
||||
),
|
||||
"content": forms.Textarea(attrs={"placeholder": _("Note Content")}),
|
||||
"title": forms.TextInput(
|
||||
attrs={"placeholder": _("Content Warning (optional)")}
|
||||
),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
item = kwargs.pop("item")
|
||||
super().__init__(*args, **kwargs)
|
||||
# allow submit empty content for existing note, and we'll delete it
|
||||
if self.instance.id:
|
||||
self.fields["content"].required = False
|
||||
# get the corresponding progress types for the item
|
||||
types = Note.get_progress_types_by_item(item)
|
||||
if self.instance.progress_type and self.instance.progress_type not in types:
|
||||
types.append(self.instance.progress_type)
|
||||
choices = [("", _("Progress Type (optional)"))] + [(x, x.label) for x in types]
|
||||
self.fields["progress_type"].choices = choices # type: ignore
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def note_edit(request: AuthedHttpRequest, item_uuid: str, note_uuid: str = ""):
|
||||
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
||||
owner = request.user.identity
|
||||
note_uuid = request.POST.get("uuid", note_uuid)
|
||||
note = None
|
||||
if note_uuid:
|
||||
note = get_object_or_404(
|
||||
Note, owner=owner, item=item, uid=get_uuid_or_404(note_uuid)
|
||||
)
|
||||
form = NoteForm(
|
||||
request.POST or None, item=item, instance=note, initial={"uuid": note_uuid}
|
||||
)
|
||||
form.instance.owner = owner
|
||||
form.instance.item = item
|
||||
if request.method == "GET":
|
||||
return render(
|
||||
request,
|
||||
"note.html",
|
||||
{
|
||||
"item": item,
|
||||
"note": note,
|
||||
"form": form,
|
||||
},
|
||||
)
|
||||
if not form.data["content"]:
|
||||
if not note:
|
||||
raise Http404(_("Content not found"))
|
||||
note.delete()
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
if note:
|
||||
orig_visibility = note.visibility
|
||||
else:
|
||||
orig_visibility = None
|
||||
if not form.is_valid():
|
||||
raise BadRequest(_("Invalid form data"))
|
||||
note = form.save()
|
||||
delete_existing_post = (
|
||||
orig_visibility is not None and orig_visibility != note.visibility
|
||||
)
|
||||
note.sync_to_timeline(delete_existing=delete_existing_post)
|
||||
if form.cleaned_data["share_to_mastodon"]:
|
||||
note.sync_to_mastodon(delete_existing=delete_existing_post)
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-13 20:50-0400\n"
|
||||
"POT-Creation-Date: 2024-06-15 18:22-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -715,15 +715,15 @@ msgstr "我的短评和标签"
|
|||
msgid "my notes"
|
||||
msgstr "我的笔记"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:101
|
||||
#: catalog/templates/_item_user_pieces.html:118
|
||||
msgid "my review"
|
||||
msgstr "我的评论"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:143
|
||||
#: catalog/templates/_item_user_pieces.html:160
|
||||
msgid "my collection"
|
||||
msgstr "我的收藏单"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:173
|
||||
#: catalog/templates/_item_user_pieces.html:190
|
||||
msgid "mark history"
|
||||
msgstr "标记历史"
|
||||
|
||||
|
@ -1029,7 +1029,7 @@ msgstr "创建"
|
|||
#: catalog/templates/catalog_edit.html:50
|
||||
#: journal/templates/add_to_collection.html:35
|
||||
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
||||
#: journal/templates/mark.html:147 journal/templates/note.html:66
|
||||
#: journal/templates/mark.html:147 journal/templates/note.html:39
|
||||
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
||||
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
||||
#: users/templates/users/preferences.html:168
|
||||
|
@ -1114,7 +1114,7 @@ msgstr "热门标签"
|
|||
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
||||
#: common/templates/_sidebar_anonymous.html:43
|
||||
#: common/templates/_sidebar_anonymous.html:58
|
||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:45
|
||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:49
|
||||
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
||||
#: journal/templates/profile.html:187
|
||||
#: journal/templates/user_collection_list.html:51
|
||||
|
@ -1393,7 +1393,7 @@ msgstr "权限不足"
|
|||
|
||||
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
||||
#: journal/views/collection.py:296 journal/views/common.py:81
|
||||
#: journal/views/mark.py:142 journal/views/post.py:41 journal/views/post.py:55
|
||||
#: journal/views/mark.py:141 journal/views/post.py:41 journal/views/post.py:55
|
||||
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
||||
msgid "Invalid parameter"
|
||||
msgstr "无效参数"
|
||||
|
@ -1678,7 +1678,7 @@ msgstr "标题"
|
|||
msgid "Content (Markdown)"
|
||||
msgstr "内容 (Markdown格式)"
|
||||
|
||||
#: journal/forms.py:21
|
||||
#: journal/forms.py:21 journal/views/note.py:26
|
||||
msgid "Post to Fediverse"
|
||||
msgstr "发布到联邦宇宙"
|
||||
|
||||
|
@ -1722,31 +1722,96 @@ msgstr "备注"
|
|||
#: journal/templates/action_open_post.html:14
|
||||
#: journal/templates/action_open_post.html:16
|
||||
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
||||
#: journal/templates/mark.html:93 journal/templates/note.html:32
|
||||
#: journal/templates/tag_edit.html:42 journal/templates/wrapped_share.html:43
|
||||
#: users/templates/users/data.html:47 users/templates/users/data.html:139
|
||||
#: journal/templates/mark.html:93 journal/templates/tag_edit.html:42
|
||||
#: journal/templates/wrapped_share.html:43 users/templates/users/data.html:47
|
||||
#: users/templates/users/data.html:139
|
||||
#: users/templates/users/preferences.html:54
|
||||
msgid "Public"
|
||||
msgstr "公开"
|
||||
|
||||
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
||||
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
||||
#: journal/templates/mark.html:100 journal/templates/note.html:39
|
||||
#: journal/templates/wrapped_share.html:49 users/templates/users/data.html:55
|
||||
#: users/templates/users/data.html:147
|
||||
#: journal/templates/mark.html:100 journal/templates/wrapped_share.html:49
|
||||
#: users/templates/users/data.html:55 users/templates/users/data.html:147
|
||||
#: users/templates/users/preferences.html:61
|
||||
msgid "Followers Only"
|
||||
msgstr "仅关注者"
|
||||
|
||||
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
||||
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
||||
#: journal/templates/mark.html:107 journal/templates/note.html:46
|
||||
#: journal/templates/wrapped_share.html:55 users/templates/users/data.html:63
|
||||
#: users/templates/users/data.html:155
|
||||
#: journal/templates/mark.html:107 journal/templates/wrapped_share.html:55
|
||||
#: users/templates/users/data.html:63 users/templates/users/data.html:155
|
||||
#: users/templates/users/preferences.html:68
|
||||
msgid "Mentioned Only"
|
||||
msgstr "自己和提到的人"
|
||||
|
||||
#: journal/models/note.py:27
|
||||
msgid "Page"
|
||||
msgstr "页码"
|
||||
|
||||
#: journal/models/note.py:28
|
||||
msgid "Chapter"
|
||||
msgstr "章节"
|
||||
|
||||
#: journal/models/note.py:31
|
||||
msgid "Part"
|
||||
msgstr "分部"
|
||||
|
||||
#: journal/models/note.py:32
|
||||
msgid "Episode"
|
||||
msgstr "单集"
|
||||
|
||||
#: journal/models/note.py:33
|
||||
msgid "Track"
|
||||
msgstr "曲目"
|
||||
|
||||
#: journal/models/note.py:34
|
||||
msgid "Cycle"
|
||||
msgstr "周目"
|
||||
|
||||
#: journal/models/note.py:35
|
||||
msgid "Timestamp"
|
||||
msgstr "时间戳"
|
||||
|
||||
#: journal/models/note.py:36
|
||||
msgid "Percentage"
|
||||
msgstr "百分比"
|
||||
|
||||
#: journal/models/note.py:53
|
||||
#, python-brace-format
|
||||
msgid "Page {value}"
|
||||
msgstr "第{value}页"
|
||||
|
||||
#: journal/models/note.py:54
|
||||
#, python-brace-format
|
||||
msgid "Chapter {value}"
|
||||
msgstr "第{value}章"
|
||||
|
||||
#: journal/models/note.py:57
|
||||
#, python-brace-format
|
||||
msgid "Part {value}"
|
||||
msgstr "第{value}部"
|
||||
|
||||
#: journal/models/note.py:58
|
||||
#, python-brace-format
|
||||
msgid "Episode {value}"
|
||||
msgstr "第{value}集"
|
||||
|
||||
#: journal/models/note.py:59
|
||||
#, python-brace-format
|
||||
msgid "Track {value}"
|
||||
msgstr "第{value}首"
|
||||
|
||||
#: journal/models/note.py:60
|
||||
#, python-brace-format
|
||||
msgid "Cycle {value}"
|
||||
msgstr "{value}周目"
|
||||
|
||||
#: journal/models/renderers.py:94 mastodon/api.py:619 takahe/utils.py:540
|
||||
#, python-brace-format
|
||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||
msgstr "关于 {item_title},可能包含剧透或敏感内容"
|
||||
|
||||
#: journal/models/shelf.py:24
|
||||
msgid "WISHLIST"
|
||||
msgstr ""
|
||||
|
@ -2323,7 +2388,6 @@ msgid "Tips: use >!text!< for spoilers; some instances may not be able to
|
|||
msgstr "提示: 善用 >!文字!< 标记可隐藏剧透; 超过360字可能无法分享到联邦宇宙实例时间轴。"
|
||||
|
||||
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
||||
#: journal/templates/note.html:59
|
||||
msgid "Repost to timeline"
|
||||
msgstr "转发到时间轴"
|
||||
|
||||
|
@ -2450,6 +2514,10 @@ msgstr ""
|
|||
msgid "Note"
|
||||
msgstr "笔记"
|
||||
|
||||
#: journal/templates/note.html:21
|
||||
msgid "Note with empty content will be deleted, sure to continue?"
|
||||
msgstr ""
|
||||
|
||||
#: journal/templates/profile.html:55
|
||||
msgid "calendar"
|
||||
msgstr "日历"
|
||||
|
@ -2458,7 +2526,7 @@ msgstr "日历"
|
|||
msgid "annual summary"
|
||||
msgstr "年度小结"
|
||||
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:747
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:678
|
||||
msgid "collection"
|
||||
msgstr "收藏单"
|
||||
|
||||
|
@ -2590,7 +2658,7 @@ msgstr "找不到条目,请使用本站条目网址。"
|
|||
msgid "Login required"
|
||||
msgstr "登录后访问"
|
||||
|
||||
#: journal/views/common.py:33 journal/views/mark.py:119
|
||||
#: journal/views/common.py:33 journal/views/mark.py:118
|
||||
msgid "Data saved but unable to repost to Fediverse instance."
|
||||
msgstr "数据已保存但未能转发到联邦实例。"
|
||||
|
||||
|
@ -2602,15 +2670,35 @@ msgstr "正在重定向到你的联邦实例以重新认证。"
|
|||
msgid "List not found."
|
||||
msgstr "列表未找到"
|
||||
|
||||
#: journal/views/mark.py:110
|
||||
#: journal/views/mark.py:109
|
||||
msgid "Content too long for your Fediverse instance."
|
||||
msgstr "内容过长,超出了你的联邦实例的限制。"
|
||||
|
||||
#: journal/views/mark.py:164 journal/views/mark.py:218
|
||||
#: journal/views/mark.py:163 journal/views/note.py:94
|
||||
#: journal/views/review.py:30
|
||||
msgid "Content not found"
|
||||
msgstr "内容未找到"
|
||||
|
||||
#: journal/views/note.py:44
|
||||
msgid "Progress (optional)"
|
||||
msgstr "进度(选填)"
|
||||
|
||||
#: journal/views/note.py:46
|
||||
msgid "Note Content"
|
||||
msgstr "笔记内容"
|
||||
|
||||
#: journal/views/note.py:48
|
||||
msgid "Content Warning (optional)"
|
||||
msgstr "剧透或敏感内容提示(选填)"
|
||||
|
||||
#: journal/views/note.py:62
|
||||
msgid "Progress Type (optional)"
|
||||
msgstr "进度类型(选填)"
|
||||
|
||||
#: journal/views/note.py:102
|
||||
msgid "Invalid form data"
|
||||
msgstr "无效表单信息。"
|
||||
|
||||
#: journal/views/review.py:112 journal/views/review.py:126
|
||||
#, python-brace-format
|
||||
msgid "Reviews by {0}"
|
||||
|
@ -2649,16 +2737,11 @@ msgstr "标签已更新"
|
|||
msgid "Summary posted to timeline."
|
||||
msgstr "总结已发布到时间轴"
|
||||
|
||||
#: mastodon/api.py:600 takahe/utils.py:540
|
||||
#, python-brace-format
|
||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||
msgstr "关于 {item_title},可能包含剧透或敏感内容"
|
||||
|
||||
#: mastodon/api.py:752
|
||||
#: mastodon/api.py:683
|
||||
msgid "shared my collection"
|
||||
msgstr "分享我的收藏单"
|
||||
|
||||
#: mastodon/api.py:755
|
||||
#: mastodon/api.py:686
|
||||
#, python-brace-format
|
||||
msgid "shared {username}'s collection"
|
||||
msgstr "分享 {username} 的收藏单"
|
||||
|
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-13 20:50-0400\n"
|
||||
"POT-Creation-Date: 2024-06-15 18:22-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -715,15 +715,15 @@ msgstr "我的短評和標籤"
|
|||
msgid "my notes"
|
||||
msgstr "我的筆記"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:101
|
||||
#: catalog/templates/_item_user_pieces.html:118
|
||||
msgid "my review"
|
||||
msgstr "我的評論"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:143
|
||||
#: catalog/templates/_item_user_pieces.html:160
|
||||
msgid "my collection"
|
||||
msgstr "我的收藏單"
|
||||
|
||||
#: catalog/templates/_item_user_pieces.html:173
|
||||
#: catalog/templates/_item_user_pieces.html:190
|
||||
msgid "mark history"
|
||||
msgstr "標記歷史"
|
||||
|
||||
|
@ -1029,7 +1029,7 @@ msgstr "創建"
|
|||
#: catalog/templates/catalog_edit.html:50
|
||||
#: journal/templates/add_to_collection.html:35
|
||||
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
||||
#: journal/templates/mark.html:147 journal/templates/note.html:66
|
||||
#: journal/templates/mark.html:147 journal/templates/note.html:39
|
||||
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
||||
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
||||
#: users/templates/users/preferences.html:168
|
||||
|
@ -1114,7 +1114,7 @@ msgstr "熱門標籤"
|
|||
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
||||
#: common/templates/_sidebar_anonymous.html:43
|
||||
#: common/templates/_sidebar_anonymous.html:58
|
||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:45
|
||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:49
|
||||
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
||||
#: journal/templates/profile.html:187
|
||||
#: journal/templates/user_collection_list.html:51
|
||||
|
@ -1393,7 +1393,7 @@ msgstr "權限不足"
|
|||
|
||||
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
||||
#: journal/views/collection.py:296 journal/views/common.py:81
|
||||
#: journal/views/mark.py:142 journal/views/post.py:41 journal/views/post.py:55
|
||||
#: journal/views/mark.py:141 journal/views/post.py:41 journal/views/post.py:55
|
||||
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
||||
msgid "Invalid parameter"
|
||||
msgstr "無效參數"
|
||||
|
@ -1678,7 +1678,7 @@ msgstr "標題"
|
|||
msgid "Content (Markdown)"
|
||||
msgstr "內容 (Markdown格式)"
|
||||
|
||||
#: journal/forms.py:21
|
||||
#: journal/forms.py:21 journal/views/note.py:26
|
||||
msgid "Post to Fediverse"
|
||||
msgstr "發佈到聯邦宇宙"
|
||||
|
||||
|
@ -1722,31 +1722,96 @@ msgstr "備註"
|
|||
#: journal/templates/action_open_post.html:14
|
||||
#: journal/templates/action_open_post.html:16
|
||||
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
||||
#: journal/templates/mark.html:93 journal/templates/note.html:32
|
||||
#: journal/templates/tag_edit.html:42 journal/templates/wrapped_share.html:43
|
||||
#: users/templates/users/data.html:47 users/templates/users/data.html:139
|
||||
#: journal/templates/mark.html:93 journal/templates/tag_edit.html:42
|
||||
#: journal/templates/wrapped_share.html:43 users/templates/users/data.html:47
|
||||
#: users/templates/users/data.html:139
|
||||
#: users/templates/users/preferences.html:54
|
||||
msgid "Public"
|
||||
msgstr "公開"
|
||||
|
||||
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
||||
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
||||
#: journal/templates/mark.html:100 journal/templates/note.html:39
|
||||
#: journal/templates/wrapped_share.html:49 users/templates/users/data.html:55
|
||||
#: users/templates/users/data.html:147
|
||||
#: journal/templates/mark.html:100 journal/templates/wrapped_share.html:49
|
||||
#: users/templates/users/data.html:55 users/templates/users/data.html:147
|
||||
#: users/templates/users/preferences.html:61
|
||||
msgid "Followers Only"
|
||||
msgstr "僅關注者"
|
||||
|
||||
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
||||
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
||||
#: journal/templates/mark.html:107 journal/templates/note.html:46
|
||||
#: journal/templates/wrapped_share.html:55 users/templates/users/data.html:63
|
||||
#: users/templates/users/data.html:155
|
||||
#: journal/templates/mark.html:107 journal/templates/wrapped_share.html:55
|
||||
#: users/templates/users/data.html:63 users/templates/users/data.html:155
|
||||
#: users/templates/users/preferences.html:68
|
||||
msgid "Mentioned Only"
|
||||
msgstr "自己和提到的人"
|
||||
|
||||
#: journal/models/note.py:27
|
||||
msgid "Page"
|
||||
msgstr "頁碼"
|
||||
|
||||
#: journal/models/note.py:28
|
||||
msgid "Chapter"
|
||||
msgstr "章節"
|
||||
|
||||
#: journal/models/note.py:31
|
||||
msgid "Part"
|
||||
msgstr "分部"
|
||||
|
||||
#: journal/models/note.py:32
|
||||
msgid "Episode"
|
||||
msgstr "單集"
|
||||
|
||||
#: journal/models/note.py:33
|
||||
msgid "Track"
|
||||
msgstr "曲目"
|
||||
|
||||
#: journal/models/note.py:34
|
||||
msgid "Cycle"
|
||||
msgstr "周目"
|
||||
|
||||
#: journal/models/note.py:35
|
||||
msgid "Timestamp"
|
||||
msgstr "時間戳"
|
||||
|
||||
#: journal/models/note.py:36
|
||||
msgid "Percentage"
|
||||
msgstr "百分比"
|
||||
|
||||
#: journal/models/note.py:53
|
||||
#, python-brace-format
|
||||
msgid "Page {value}"
|
||||
msgstr "第{value}頁"
|
||||
|
||||
#: journal/models/note.py:54
|
||||
#, python-brace-format
|
||||
msgid "Chapter {value}"
|
||||
msgstr "第{value}章"
|
||||
|
||||
#: journal/models/note.py:57
|
||||
#, python-brace-format
|
||||
msgid "Part {value}"
|
||||
msgstr "第{value}部"
|
||||
|
||||
#: journal/models/note.py:58
|
||||
#, python-brace-format
|
||||
msgid "Episode {value}"
|
||||
msgstr "第{value}集"
|
||||
|
||||
#: journal/models/note.py:59
|
||||
#, python-brace-format
|
||||
msgid "Track {value}"
|
||||
msgstr "第{value}首"
|
||||
|
||||
#: journal/models/note.py:60
|
||||
#, python-brace-format
|
||||
msgid "Cycle {value}"
|
||||
msgstr "{value}周目"
|
||||
|
||||
#: journal/models/renderers.py:94 mastodon/api.py:619 takahe/utils.py:540
|
||||
#, python-brace-format
|
||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||
msgstr "關於 {item_title},可能包含劇透或敏感內容"
|
||||
|
||||
#: journal/models/shelf.py:24
|
||||
msgid "WISHLIST"
|
||||
msgstr ""
|
||||
|
@ -2323,7 +2388,6 @@ msgid "Tips: use >!text!< for spoilers; some instances may not be able to
|
|||
msgstr "提示: 善用 >!文字!< 標記可隱藏劇透; 超過360字可能無法分享到聯邦宇宙實例時間軸。"
|
||||
|
||||
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
||||
#: journal/templates/note.html:59
|
||||
msgid "Repost to timeline"
|
||||
msgstr "轉發到時間軸"
|
||||
|
||||
|
@ -2450,6 +2514,10 @@ msgstr ""
|
|||
msgid "Note"
|
||||
msgstr "筆記"
|
||||
|
||||
#: journal/templates/note.html:21
|
||||
msgid "Note with empty content will be deleted, sure to continue?"
|
||||
msgstr ""
|
||||
|
||||
#: journal/templates/profile.html:55
|
||||
msgid "calendar"
|
||||
msgstr "日曆"
|
||||
|
@ -2458,7 +2526,7 @@ msgstr "日曆"
|
|||
msgid "annual summary"
|
||||
msgstr "年度小結"
|
||||
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:747
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:678
|
||||
msgid "collection"
|
||||
msgstr "收藏單"
|
||||
|
||||
|
@ -2590,7 +2658,7 @@ msgstr "找不到條目,請使用本站條目網址。"
|
|||
msgid "Login required"
|
||||
msgstr "登錄後訪問"
|
||||
|
||||
#: journal/views/common.py:33 journal/views/mark.py:119
|
||||
#: journal/views/common.py:33 journal/views/mark.py:118
|
||||
msgid "Data saved but unable to repost to Fediverse instance."
|
||||
msgstr "數據已保存但未能轉發到聯邦實例。"
|
||||
|
||||
|
@ -2602,15 +2670,35 @@ msgstr "正在重定向到你的聯邦實例以重新認證。"
|
|||
msgid "List not found."
|
||||
msgstr "列表未找到"
|
||||
|
||||
#: journal/views/mark.py:110
|
||||
#: journal/views/mark.py:109
|
||||
msgid "Content too long for your Fediverse instance."
|
||||
msgstr "內容過長,超出了你的聯邦實例的限制。"
|
||||
|
||||
#: journal/views/mark.py:164 journal/views/mark.py:218
|
||||
#: journal/views/mark.py:163 journal/views/note.py:94
|
||||
#: journal/views/review.py:30
|
||||
msgid "Content not found"
|
||||
msgstr "內容未找到"
|
||||
|
||||
#: journal/views/note.py:44
|
||||
msgid "Progress (optional)"
|
||||
msgstr "進度(選填)"
|
||||
|
||||
#: journal/views/note.py:46
|
||||
msgid "Note Content"
|
||||
msgstr "筆記內容"
|
||||
|
||||
#: journal/views/note.py:48
|
||||
msgid "Content Warning (optional)"
|
||||
msgstr "劇透或敏感內容提示(選填)"
|
||||
|
||||
#: journal/views/note.py:62
|
||||
msgid "Progress Type (optional)"
|
||||
msgstr "進度類型(選填)"
|
||||
|
||||
#: journal/views/note.py:102
|
||||
msgid "Invalid form data"
|
||||
msgstr "無效表單信息。"
|
||||
|
||||
#: journal/views/review.py:112 journal/views/review.py:126
|
||||
#, python-brace-format
|
||||
msgid "Reviews by {0}"
|
||||
|
@ -2649,16 +2737,11 @@ msgstr "標籤已更新"
|
|||
msgid "Summary posted to timeline."
|
||||
msgstr "總結已發佈到時間軸"
|
||||
|
||||
#: mastodon/api.py:600 takahe/utils.py:540
|
||||
#, python-brace-format
|
||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||
msgstr "關於 {item_title},可能包含劇透或敏感內容"
|
||||
|
||||
#: mastodon/api.py:752
|
||||
#: mastodon/api.py:683
|
||||
msgid "shared my collection"
|
||||
msgstr "分享我的收藏單"
|
||||
|
||||
#: mastodon/api.py:755
|
||||
#: mastodon/api.py:686
|
||||
#, python-brace-format
|
||||
msgid "shared {username}'s collection"
|
||||
msgstr "分享 {username} 的收藏單"
|
||||
|
|
Loading…
Add table
Reference in a new issue