show podcast episode comment on timeline

This commit is contained in:
Your Name 2023-02-01 22:40:34 -05:00 committed by Henri Dickson
parent 41479999b7
commit adce46e3ab
20 changed files with 440 additions and 174 deletions

View file

@ -1,3 +1,21 @@
function create_player(audio) {
window.player = new Shikwasa.Player({
container: () => document.querySelector('.player'),
preload: 'metadata',
autoplay: true,
themeColor: '#1190C0',
fixed: {
type: 'fixed',
position: 'bottom'
},
audio: audio
});
// $('.shk-title').on('click', e=>{
// window.location = "#";
// });
$('.footer').attr('style', 'margin-bottom: 120px !important');
}
function catalog_init(context) {
// readonly star rating of detail display section
let ratingLabels = $(".grid__main .rating-star", context);
@ -47,6 +65,38 @@ function catalog_init(context) {
e.preventDefault();
})
$('.source-label__rss', context).parent().attr('title', 'Copy link here and subscribe in your podcast app');
$('.episode', context).on('click', e=>{
e.preventDefault();
var ele = e.target;
var album = $(ele).data('album');
var artist = $(ele).data('hosts');
var title = $(ele).data('title');
var cover_url = $(ele).data('cover');
var media_url = $(ele).data('media');
var position = $(ele).data('position');
if (!media_url) return;
window.current_item_uuid = $(ele).data('uuid');
if (!window.player) {
create_player({
title: title,
cover: cover_url,
src: media_url,
album: album,
artist: artist
})
} else {
window.player.update({
title: title,
cover: cover_url,
src: media_url,
album: album,
artist: artist
})
}
if (position) window.player._initSeek = position;
window.player.play()
});
}
$(function() {

View file

@ -66,7 +66,7 @@
{% endif %}
</div>
<div>{% if item.duration %}
{% trans '时长:' %}{{ item.duration|duration_format }}
{% trans '时长:' %}{{ item.duration|duration_format:1000 }}
{% endif %}
</div>
<div>{% if item.genre %}

View file

@ -120,6 +120,28 @@
</div>
{% endif %}
{% block content %}
{% if item.contents %}
<div class="entity-desc" id="contents">
<h5 class="entity-desc__title">{% trans '目录' %}</h5>
<p class="entity-desc__content">{{ item.contents | linebreaksbr }}</p>
<div class="entity-desc__unfold-button entity-desc__unfold-button--hidden">
<a href="javascript:void(0);">展开全部</a>
</div>
</div>
{% endif %}
{% if item.track_list %}
<div class="entity-desc" id="description">
<h5 class="entity-desc__title">{% trans '曲目' %}</h5>
<p class="entity-desc__content">{{ item.track_list | linebreaksbr }}</p>
<div class="entity-desc__unfold-button entity-desc__unfold-button--hidden">
<a href="javascript:void(0);">展开全部</a>
</div>
</div>
{% endif %}
{% endblock %}
<div class="entity-marks">
<h5 class="entity-marks__title">{% trans '标记' %}</h5>
{% if mark_list %}
@ -309,7 +331,5 @@
</div>
{% include "partial/_footer.html" %}
</div>
<div class="player">
</div>
</body>
</html>

View file

@ -70,7 +70,6 @@
{% endif %}
</div>
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
{% endif %}
@ -84,104 +83,46 @@
{% endblock %}
{% block content %}
<div class="entity-desc" id="episodes">
<h5 class="entity-desc__title">{% trans '近期节目' %}</h5>
<br>
<div hx-get="{% url 'catalog:episode_data' item.uuid %}" hx-trigger="load" hx-swap="outerHTML"></div>
</div>
{% endblock %}
<!-- class specific sidebar -->
{% block sidebar %}
<div class="aside-section-wrapper">
<div class="action-panel" id="episodes">
<div class="action-panel__label">{% trans '近期单集' %}</div>
<div >
{% for ep in item.recent_episodes %}
<p>
<a data-media="{{ ep.media_url }}" data-cover="{{ ep.cover_url|default:item.cover }}" class="episode" href="{{ep.url}}" data-uuid="{{ep.uuid}}">{{ ep.title }}</a>
<a href="#" hx-get="{% url 'journal:comment' item.uuid ep.uuid %}" hx-target="body" hx-swap="beforeend"><span class="comment icon"></span></a>
</p>
{% endfor %}
</div>
<div class="action-panel__button-group action-panel__button-group--center">
<button href="#" class="podlove-subscribe-button-primary action-panel__button">{% trans '订阅' %}</button>
<button href="#" class="podlove-subscribe-button-primary action-panel__button">{% trans '用播客应用订阅' %}</button>
</div>
</div>
</div>
<script>
window.podcastData = {
"title": "{{ item.title | escapejs }}",
"subtitle": "",
"description": "{{ item.brief | escapejs }}",
"cover": "{{ item.cover.url | escapejs }}",
"feeds": [
{
"type": "audio",
"format": "mp3",
"url": "{{ item.feed_url | escapejs }}",
"variant": "high"
}
]
}
</script>
<script class="podlove-subscribe-button" src="https://cdn.podlove.org/subscribe-button/javascripts/app.js" data-json-data="podcastData" data-buttonid="primary" data-language="en" data-hide="true" data-color="#1190C0">
</script>
<script type="text/javascript">
album = "{{ item.title|escapejs }}"
artists = "{{ item.hosts|join:' / '|escapejs }}"
function create_player(audio) {
window.player = new Shikwasa.Player({
container: () => document.querySelector('.player'),
preload: 'metadata',
autoplay: true,
themeColor: '#1190C0',
fixed: {
type: 'fixed',
position: 'bottom'
},
audio: audio
});
$('.shk-title').on('click', e=>{
window.location = "#episodes";
});
$('.footer').attr('style', 'margin-bottom: 120px !important');
}
$(()=>{
$('.episode').on('click', e=>{
e.preventDefault();
ele = e.target;
title = $(ele).text();
cover_url = $(ele).data('cover');
media_url = $(ele).data('media');
if (!media_url) return;
window.current_item_uuid = $(ele).data('uuid');
if (!window.player) {
create_player({
title: title,
cover: cover_url,
src: media_url,
album: album,
artist: artists
})
} else {
window.player.update({
title: title,
cover: cover_url,
src: media_url,
album: album,
artist: artists
})
}
window.player.play()
});
{% if focus_item %}
loc = 1 * "{{request.GET.position|escapejs}}";
window.current_item_uuid = "{{focus_item.uuid}}";
create_player({
title: "{{ focus_item.title | escapejs }}",
cover: "{{ focus_item.cover_url | default:'' | escapejs }}",
src: "{{ focus_item.media_url | escapejs }}",
album: album,
artist: artists
})
if (loc) window.player._initSeek = loc;
{% endif %}
});
window.podcastData = {
"title": "{{ item.title | escapejs }}",
"subtitle": "",
"description": "{{ item.brief | escapejs }}",
"cover": "{{ item.cover.url | escapejs }}",
"feeds": [{"type": "audio", "format": "mp3", "url": "{{ item.feed_url | escapejs }}", "variant": "high"}]
}
$(()=>{
{% if focus_item %}
var position = 1 * "{{request.GET.position|escapejs}}";
window.current_item_uuid = "{{focus_item.uuid}}";
create_player({
title: "{{ focus_item.title | escapejs }}",
cover: "{{ focus_item.cover_url | default:item.cover.url | escapejs }}",
src: "{{ focus_item.media_url | escapejs }}",
album: "{{ item.title|escapejs }}",
artist: "{{ item.hosts|join:' / '|escapejs }}"
})
if (position) window.player._initSeek = position;
{% endif %}
});
</script>
<script class="podlove-subscribe-button" src="https://cdn.podlove.org/subscribe-button/javascripts/app.js" data-json-data="podcastData" data-buttonid="primary" data-language="en" data-hide="true" data-color="#1190C0"></script>
{% endblock %}

View file

@ -0,0 +1,39 @@
{% load static %}
{% load i18n %}
{% load l10n %}
{% load humanize %}
{% for ep in episodes %}
<details>
<summary>
<h6 class="entity-desc__title">
<a
data-media="{{ ep.media_url }}"
data-cover="{{ ep.cover_url|default:item.cover.url }}"
class="episode gg-play-button-o"
href="{{ep.url}}"
data-uuid="{{ep.uuid}}"
data-title="{{ ep.title }}"
data-album = "{{ item.title }}"
data-hosts = "{{ item.hosts|join:' / ' }}"
style="top:4px;margin-right: 8px;">
</a>
{{ ep.title }}
<small style="color:lightgrey;">{{ ep.pub_date|date }}</small>
</h6>
</summary>
<p> {{ ep.brief | linebreaksbr }} </p>
</details>
<div style="margin-bottom: 8px;margin-left: 32px;">
{% if request.user.is_authenticated %}
<a class="icon gg-comment" style="--ggs:0.5;margin-right: 10px;" title="评论单集" href="#" hx-get="{% url 'journal:comment' item.uuid ep.uuid %}" hx-target="body" hx-swap="beforeend"></a>
{% endif %}
<a class="icon gg-external" style="--ggs:0.6;" title="打开源网站" target="_blank" href="{{ep.link}}"></a>
</div>
{% if forloop.last %}
<button hx-get="{% url 'catalog:episode_data' item.uuid %}?last={{ ep.pub_date|date:'Y-m-d H:i:s.uO'|urlencode }}" hx-trigger="click" hx-swap="outerHTML">显示更多</button>
{% endif %}
{% empty %}
<div>{% trans '目前没有更多内容了' %}</div>
{% endfor %}

View file

@ -29,6 +29,7 @@ urlpatterns = [
retrieve,
name="retrieve",
),
path("podcast/<str:item_uuid>/episodes", episode_data, name="episode_data"),
path("catalog/create/<str:item_model>", create, name="create"),
re_path(
r"^(?P<item_path>"

View file

@ -126,7 +126,6 @@ def create(request, item_model):
form.instance.save()
return redirect(form.instance.url)
else:
pprint(form.errors)
return HttpResponseBadRequest(form.errors)
else:
return HttpResponseBadRequest()
@ -155,7 +154,6 @@ def edit(request, item_path, item_uuid):
form.instance.save()
return redirect(form.instance.url)
else:
pprint(form.errors)
return HttpResponseBadRequest(form.errors)
else:
return HttpResponseBadRequest()
@ -221,6 +219,16 @@ def merge(request, item_path, item_uuid):
return redirect(new_item.url)
def episode_data(request, item_uuid):
item = get_object_or_404(Item, uid=base62.decode(item_uuid))
qs = item.episodes.all().order_by("-pub_date")
if request.GET.get("last"):
qs = qs.filter(pub_date__lt=request.GET.get("last"))
return render(
request, "podcast_episode_data.html", {"item": item, "episodes": qs[:10]}
)
@login_required
def mark_list(request, item_path, item_uuid, following_only=False):
item = get_object_or_404(Item, uid=base62.decode(item_uuid))

View file

@ -197,31 +197,145 @@ progress {
}
.icon {
color: lightgray;
color: grey;
}
.icon:hover {
color: #00a1cc;
}
.comment.icon {
box-sizing: unset;
position: absolute;
margin-left: 2px;
margin-top: 4px;
width: 15px;
height: 10px;
border: solid 1px currentColor;
border-radius: 2px;
input:invalid#position {
border: red dashed 1px;
}
.comment.icon:before {
content: '';
position: absolute;
left: 3px;
top: 8px;
width: 4px;
height: 4px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background-color: white;
border-bottom: solid 1px currentColor;
border-right: solid 1px currentColor;
summary:focus {
outline-style: none;
}
summary::-webkit-details-marker {
display: none;
}
.gg-play-button-o {
box-sizing: border-box;
position: relative;
display: inline-block;
transform: scale(var(--ggs,1));
width: 22px;
height: 22px;
border: 2px solid;
border-radius: 20px
}
.gg-play-button-o::before {
content: "";
display: inline-block;
box-sizing: border-box;
position: absolute;
width: 0;
height: 10px;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid;
top: 4px;
left: 7px
}
.gg-link {
box-sizing: border-box;
position: relative;
display: inline-block;
transform: rotate(-45deg) scale(var(--ggs,1));
width: 8px;
height: 2px;
background: currentColor;
border-radius: 4px
}
.gg-link::after,
.gg-link::before {
content: "";
display: inline-block;
box-sizing: border-box;
position: absolute;
border-radius: 3px;
width: 8px;
height: 10px;
border: 2px solid;
top: -4px
}
.gg-link::before {
border-right: 0;
border-top-left-radius: 40px;
border-bottom-left-radius: 40px;
left: -6px
}
.gg-link::after {
border-left: 0;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
right: -6px
}
.gg-external {
box-sizing: border-box;
position: relative;
display: inline-block;
transform: scale(var(--ggs,1));
width: 12px;
height: 12px;
box-shadow:
-2px 2px 0 0,
-4px -4px 0 -2px,
4px 4px 0 -2px;
margin-left: -2px;
margin-top: 1px
}
.gg-external::after,
.gg-external::before {
content: "";
display: inline-block;
box-sizing: border-box;
position: absolute;
right: -4px
}
.gg-external::before {
background: currentColor;
transform: rotate(-45deg);
width: 12px;
height: 2px;
top: 1px
}
.gg-external::after {
width: 8px;
height: 8px;
border-right: 2px solid;
border-top: 2px solid;
top: -4px
}
.gg-comment {
box-sizing: border-box;
position: relative;
display: inline-block;
transform: scale(var(--ggs,1));
width: 20px;
height: 16px;
border: 2px solid;
border-bottom: 0;
box-shadow:
-6px 8px 0 -6px,
6px 8px 0 -6px
}
.gg-comment::after,
.gg-comment::before {
content: "";
display: inline-block;
box-sizing: border-box;
position: absolute;
width: 8px
}
.gg-comment::before {
border: 2px solid;
border-top-color: transparent;
border-bottom-left-radius: 20px;
right: 4px;
bottom: -6px;
height: 6px
}

View file

@ -258,7 +258,7 @@
var $stars = $starSet.$stars;
if(newSize <= 1 || newSize > 200) {
console.log('star size out of bounds');
console.error('star size out of bounds');
return;
}

View file

@ -15,3 +15,5 @@
</div>
</div>
</footer>
<div class="player">
</div>

View file

@ -7,8 +7,10 @@ register = template.Library()
@register.filter(is_safe=True)
@stringfilter
def duration_format(value):
duration = int(value)
h = duration // 3600000
m = duration % 3600000 // 60000
return (f"{h}小时 " if h else "") + (f"{m}分钟" if m else "")
def duration_format(value, unit):
duration = int(value or 0) // int(unit or 1)
h = duration // 3600
m = duration % 3600 // 60
s = duration % 60
return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"
# return (f"{h}小时 " if h else "") + (f"{m}分钟" if m else "")

View file

@ -195,6 +195,15 @@ class Comment(Content):
def html(self):
return render_text(self.text)
@property
def item_url(self):
if self.focus_item:
return self.focus_item.get_absolute_url_with_position(
self.metadata["position"]
)
else:
return self.item.url
@staticmethod
def comment_item_by_user(item, user, text, visibility=0):
comment = Comment.objects.filter(owner=user, item=item).first()

View file

@ -13,57 +13,52 @@
<div class="modal-underlay" _="on click trigger closeModal"></div>
<div class="modal-content">
<div class="add-to-list-modal__head">
<span class="add-to-list-modal__title">{% trans '分享' %} {{ item.title }}: {{ focus_item.title }}</span>
<span class="add-to-list-modal__title">{% trans '评论单集' %} {{ item.title }}: {{ focus_item.title }}</span>
<span class="add-to-list-modal__close-button modal-close" _="on click trigger closeModal">
<span class="icon-cross">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<polygon
points="20 2.61 17.39 0 10 7.39 2.61 0 0 2.61 7.39 10 0 17.39 2.61 20 10 12.61 17.39 20 20 17.39 12.61 10 20 2.61">
</polygon>
</svg>
points="20 2.61 17.39 0 10 7.39 2.61 0 0 2.61 7.39 10 0 17.39 2.61 20 10 12.61 17.39 20 20 17.39 12.61 10 20 2.61"></polygon>
</svg>
</span>
</span>
</span>
</div>
<div class="add-to-list-modal__body">
<form action="{% url 'journal:comment' item.uuid focus_item.uuid %}" method="post">
{% csrf_token %}
</div>
<div class="add-to-list-modal__body">
<form action="{% url 'journal:comment' item.uuid focus_item.uuid %}" method="post">
{% csrf_token %}
<textarea name="text" cols="40" rows="10" placeholder="超过360字部分实例可能无法显示" maxlength="360" id="id_text">{% if comment.text %}{{ comment.text }}{% endif %}</textarea>
<textarea name="text" cols="40" rows="10" placeholder="超过360字部分实例可能无法显示" maxlength="360" id="id_text">{% if comment.text %}{{ comment.text }}{% endif %}</textarea>
<div class="mark-modal__share-checkbox float-right">
<label for="id_share_to_mastodon"><input type="checkbox" name="share_to_mastodon" id="id_share_to_mastodon" value="1" checked>分享到联邦网络</label>
</div>
<div class="mark-modal__option">
<div class="mark-modal__visibility-radio">
<span>可见性:
<ul id="id_visibility">
<li><label for="id_visibility_0"><input type="radio" name="visibility" value="0" required="" id="id_visibility_0" {% if comment.visibility == 0 or not comment %}checked{% endif %}> 公开</label> </li>
<li><label for="id_visibility_1"><input type="radio" name="visibility" value="1" required="" id="id_visibility_1" {% if comment.visibility == 1 %}checked{% endif %}> 仅关注者</label> </li>
<li><label for="id_visibility_2"><input type="radio" name="visibility" value="2" required="" id="id_visibility_2" {% if comment.visibility == 2 %}checked{% endif %}> 仅自己</label> </li>
</ul>
</span>
<div class="mark-modal__share-checkbox float-right">
<label for="id_share_to_mastodon"><input type="checkbox" name="share_to_mastodon" id="id_share_to_mastodon" value="1" checked>分享到联邦网络</label>
</div>
</div>
<div class="mark-modal__confirm-button">
<input type="submit" class="button float-right" value="保存">
</div>
<style type="text/css">
input:invalid#position {
border: red dashed 1px;
}
</style>
<div class="mark-modal__option">
<div class="mark-modal__visibility-radio">
<span>
<label for="share_position"><input type="checkbox" name="share_position" value="1" id="share_position"> 分享播放位置: </label>
<input type="input" name="position" id="position" value="00:00:00" class="html-duration-picker" pattern="[0-9]{2}:[0-9]{2}:[0-9]{2}" title="hh:mm:ss" style="display: none;">
</span>
<div class="mark-modal__option">
<div class="mark-modal__visibility-radio">
<span>可见性:
<ul id="id_visibility">
<li><label for="id_visibility_0"><input type="radio" name="visibility" value="0" required="" id="id_visibility_0" {% if comment.visibility == 0 or not comment %}checked{% endif %}> 公开</label> </li>
<li><label for="id_visibility_1"><input type="radio" name="visibility" value="1" required="" id="id_visibility_1" {% if comment.visibility == 1 %}checked{% endif %}> 仅关注者</label> </li>
<li><label for="id_visibility_2"><input type="radio" name="visibility" value="2" required="" id="id_visibility_2" {% if comment.visibility == 2 %}checked{% endif %}> 仅自己</label> </li>
</ul>
</span>
</div>
</div>
</div>
</form>
<div class="mark-modal__confirm-button">
<input type="submit" class="button float-right" value="保存">
</div>
<div class="mark-modal__option">
<div class="mark-modal__visibility-radio">
<span>
<label for="share_position"><input type="checkbox" name="share_position" value="1" id="share_position"> 分享播放位置: </label>
<input type="input" name="position" id="position" value="00:00:00" class="html-duration-picker" pattern="[0-9]{2}:[0-9]{2}:[0-9]{2}" title="hh:mm:ss" style="display: none;">
</span>
</div>
</div>
</form>
</div>
</div>
</div>
<script type="text/javascript">

View file

@ -11,7 +11,7 @@
<img src="{{ item.cover|thumb:'normal' }}" alt="" class="entity-list__entity-img">
</a>
{% if not action.taken %}
<a title="加入想读" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
<a title="标记" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
{% endif %}
</div>

View file

@ -215,8 +215,9 @@ def comment(request, item_uuid, focus_item_uuid):
pos = datetime.strptime(position, "%H:%M:%S")
position = pos.hour * 3600 + pos.minute * 60 + pos.second
except:
raise
position = 0
if settings.DEBUG:
raise
position = None
share_to_mastodon = bool(request.POST.get("share_to_mastodon", default=False))
shared_link = None
post_error = False
@ -224,7 +225,7 @@ def comment(request, item_uuid, focus_item_uuid):
shared_link = comment.metadata.get("shared_link") if comment else None
status_id = get_status_id_by_url(shared_link)
link = focus_item.get_absolute_url_with_position(position or None)
status = f"分享{ItemCategory(item.category).label}{item.title}》的《{focus_item.title}\n{link}\n{text}"
status = f"分享{ItemCategory(item.category).label}{item.title}》的《{focus_item.title}\n{link}\n\n{text}"
spoiler, status = get_spoiler_text(status, item)
try:
response = post_toot(
@ -241,11 +242,13 @@ def comment(request, item_uuid, focus_item_uuid):
if "url" in j:
shared_link = j["url"]
except Exception as e:
raise
if settings.DEBUG:
raise
post_error = True
if comment:
comment.visibility = visibility
comment.text = text
comment.metadata["position"] = position
if shared_link:
comment.metadata["shared_link"] = shared_link
comment.save()
@ -256,7 +259,7 @@ def comment(request, item_uuid, focus_item_uuid):
focus_item=focus_item,
text=text,
visibility=visibility,
metadata={"shared_link": shared_link},
metadata={"shared_link": shared_link, "position": position},
)
if post_error:
return render_relogin(request)
@ -514,7 +517,6 @@ def review_edit(request, item_uuid, review_uuid=None):
if review
else ReviewForm(request.POST)
)
print(form.instance.body)
if form.is_valid():
if not review:
form.instance.owner = request.user

View file

@ -28,6 +28,7 @@ class ActivityTemplate(models.TextChoices):
CreateCollection = "create_collection"
LikeCollection = "like_collection"
FeatureCollection = "feature_collection"
CommentFocusItem = "comment_focus_item"
class LocalActivity(models.Model, UserOwnedObjectMixin):
@ -174,10 +175,24 @@ class LikeCollectionProcessor(DefaultActivityProcessor):
def updated(self):
if isinstance(self.action_object.target, Collection):
super().update()
super().updated()
@DataSignalManager.register
class FeaturedCollectionProcessor(DefaultActivityProcessor):
model = FeaturedCollection
template = ActivityTemplate.FeatureCollection
@DataSignalManager.register
class CommentFocusItemProcessor(DefaultActivityProcessor):
model = Comment
template = ActivityTemplate.CommentFocusItem
def created(self):
if self.action_object.focus_item:
super().created()
def updated(self):
if self.action_object.focus_item:
super().updated()

View file

@ -0,0 +1,66 @@
{% load static %}
{% load i18n %}
{% load l10n %}
{% load admin_url %}
{% load mastodon %}
{% load oauth_token %}
{% load truncate %}
{% load thumb %}
{% load prettydate %}
{% load user_actions %}
{% load duration %}
{% wish_item_action activity.action_object.item as action %}
<div class="entity-list__entity-img-wrapper">
<a href="{{ activity.action_object.item.url }}">
<img src="{{ activity.action_object.item.cover|thumb:'normal' }}" alt="" class="entity-list__entity-img" style="min-width:80px;max-width:80px">
</a>
{% if not action.taken %}
<a title="标记" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' activity.action_object.item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
{% endif %}
</div>
<div class="entity-list__entity-text">
<div class="collection-item-position-edit">
<span class="entity-marks__mark-time">
{% if activity.action_object.metadata.shared_link %}
<a href="{{ activity.action_object.metadata.shared_link }}" action_object="_blank">
<img src="{% static 'img/fediverse.svg' %}" style="filter: invert(93%) sepia(1%) saturate(53%) hue-rotate(314deg) brightness(95%) contrast(80%); vertical-align:text-top; max-width:14px; margin-right:6px;" />
<span class="entity-marks__mark-time">{{ activity.action_object.created_time|prettydate }}</span>
</a>
{% else %}
<a><span class="entity-marks__mark-time">{{ activity.action_object.created_time|prettydate }}</span></a>
{% endif %}
</span>
</div>
<span class="entity-list__entity-info" style="top:0px;">
<a href="{% url 'journal:user_profile' activity.owner.mastodon_username %}">{{ activity.owner.display_name }}</a> 在听
</span>
<div class="entity-list__entity-title">
<a href="{{ activity.action_object.item.url }}" class="entity-list__entity-link" style="font-weight:bold;">{{ activity.action_object.item.title }}
{% if activity.action_object.item.year %}<small style="font-weight: lighter">({{ activity.action_object.item.year }})</small>{% endif %}
</a>
{% for res in activity.action_object.item.external_resources.all %}
<a href="{{ res.url }}">
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
</a>
{% endfor %}
</div>
<p class="entity-list__entity-brief">
<a class="episode gg-play-button-o" href="#"
data-uuid="{{ activity.action_object.focus_item.uuid }}"
data-media = "{{ activity.action_object.focus_item.media_url }}"
data-cover = "{{ activity.action_object.focus_item.cover_url|default:activity.action_object.item.cover.url }}"
data-title = "{{ activity.action_object.focus_item.title }}"
data-album = "{{ activity.action_object.item.title }}"
data-hosts = "{{ activity.action_object.item.hosts|join:' / ' }}"
data-position = "{{ activity.action_object.metadata.position | default:0 }}"
style="top:4px;margin-right: 8px;"></a>
<a href="{{ activity.action_object.item_url }}">{{ activity.action_object.focus_item.title }}</a>
{% if activity.action_object.metadata.position %}
<span style="color:lightgrey;">{{ activity.action_object.metadata.position|duration_format:1 }}</span>
{% endif %}
<br>
{{ activity.action_object.html | safe }}
</p>
</div>

View file

@ -16,7 +16,7 @@
<img src="{{ activity.action_object.item.cover|thumb:'normal' }}" alt="" class="entity-list__entity-img" style="min-width:80px;max-width:80px">
</a>
{% if not action.taken %}
<a title="加入想读" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' activity.action_object.item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
<a title="标记" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' activity.action_object.item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
{% endif %}
</div>
<div class="entity-list__entity-text">

View file

@ -15,7 +15,7 @@
<img src="{{ activity.action_object.item.cover|thumb:'normal' }}" alt="" class="entity-list__entity-img" style="min-width:80px;max-width:80px">
</a>
{% if not action.taken %}
<a title="加入想读" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' activity.action_object.item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
<a title="标记" class="entity-list__entity-action-icon" hx-get="{% url 'journal:mark' activity.action_object.item.uuid %}?shelf_type=wishlist" class="edit" hx-target="body" hx-swap="beforeend"></a>
{% endif %}
</div>
<div class="entity-list__entity-text">

View file

@ -16,6 +16,8 @@
{% include "common_libs.html" with jquery=0 %}
<script src="{% static 'js/mastodon.js' %}"></script>
<script src="{% static 'js/home.js' %}"></script>
<script src=" https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/shikwasa.min.js "></script>
<link href=" https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/style.min.css " rel="stylesheet"></link>
</head>
<body>