@rmdes/indiekit-endpoint-activitypub 2.0.34 → 2.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/assets/reader.css CHANGED
@@ -752,6 +752,12 @@
752
752
  color: var(--color-green50);
753
753
  }
754
754
 
755
+ .ap-card__action--save.ap-card__action--active {
756
+ background: #4a9eff22;
757
+ border-color: #4a9eff;
758
+ color: #4a9eff;
759
+ }
760
+
755
761
  .ap-card__action:disabled {
756
762
  cursor: wait;
757
763
  opacity: 0.6;
@@ -132,7 +132,7 @@ export function tagTimelineController(mountPath) {
132
132
  response.render("activitypub-tag-timeline", {
133
133
  title: `#${tag}`,
134
134
  readerParent: { href: `${mountPath}/admin/reader`, text: response.locals.__("activitypub.reader.title") },
135
- tag,
135
+ hashtag: tag,
136
136
  items,
137
137
  before: result.before,
138
138
  after: result.after,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-activitypub",
3
- "version": "2.0.34",
3
+ "version": "2.0.36",
4
4
  "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
5
5
  "keywords": [
6
6
  "indiekit",
@@ -4,7 +4,7 @@
4
4
  {# Tag header #}
5
5
  <header class="ap-tag-header">
6
6
  <div class="ap-tag-header__info">
7
- <h2 class="ap-tag-header__title">#{{ tag }}</h2>
7
+ <h2 class="ap-tag-header__title">#{{ hashtag }}</h2>
8
8
  <p class="ap-tag-header__count">
9
9
  {{ __("activitypub.reader.tagTimeline.postsTagged", items.length) }}
10
10
  </p>
@@ -13,7 +13,7 @@
13
13
  {% if isFollowed %}
14
14
  <form action="{{ mountPath }}/admin/reader/unfollow-tag" method="post" class="ap-tag-header__follow-form">
15
15
  <input type="hidden" name="_csrf" value="{{ csrfToken }}">
16
- <input type="hidden" name="tag" value="{{ tag }}">
16
+ <input type="hidden" name="tag" value="{{ hashtag }}">
17
17
  <button type="submit" class="ap-tag-header__unfollow-btn">
18
18
  {{ __("activitypub.reader.tagTimeline.unfollowTag") }}
19
19
  </button>
@@ -21,7 +21,7 @@
21
21
  {% else %}
22
22
  <form action="{{ mountPath }}/admin/reader/follow-tag" method="post" class="ap-tag-header__follow-form">
23
23
  <input type="hidden" name="_csrf" value="{{ csrfToken }}">
24
- <input type="hidden" name="tag" value="{{ tag }}">
24
+ <input type="hidden" name="tag" value="{{ hashtag }}">
25
25
  <button type="submit" class="ap-tag-header__follow-btn">
26
26
  {{ __("activitypub.reader.tagTimeline.followTag") }}
27
27
  </button>
@@ -37,7 +37,7 @@
37
37
  {% if items.length > 0 %}
38
38
  <div class="ap-timeline"
39
39
  data-mount-path="{{ mountPath }}"
40
- data-tag="{{ tag }}"
40
+ data-tag="{{ hashtag }}"
41
41
  data-before="{{ before if before else '' }}">
42
42
  {% for item in items %}
43
43
  {% include "partials/ap-item-card.njk" %}
@@ -48,12 +48,12 @@
48
48
  {% if before or after %}
49
49
  <nav class="ap-pagination ap-pagination--js-hidden" id="ap-tag-pagination">
50
50
  {% if after %}
51
- <a href="?tag={{ tag }}&after={{ after }}" class="ap-pagination__prev">
51
+ <a href="?tag={{ hashtag }}&after={{ after }}" class="ap-pagination__prev">
52
52
  {{ __("activitypub.reader.pagination.newer") }}
53
53
  </a>
54
54
  {% endif %}
55
55
  {% if before %}
56
- <a href="?tag={{ tag }}&before={{ before }}" class="ap-pagination__next">
56
+ <a href="?tag={{ hashtag }}&before={{ before }}" class="ap-pagination__next">
57
57
  {{ __("activitypub.reader.pagination.older") }}
58
58
  </a>
59
59
  {% endif %}
@@ -66,7 +66,7 @@
66
66
  id="ap-load-more"
67
67
  data-before="{{ before }}"
68
68
  data-tab=""
69
- data-tag="{{ tag }}"
69
+ data-tag="{{ hashtag }}"
70
70
  x-data="apInfiniteScroll()"
71
71
  x-init="init()"
72
72
  @ap-append-items.window="appendItems($event.detail)">
@@ -79,6 +79,6 @@
79
79
  </div>
80
80
  {% endif %}
81
81
  {% else %}
82
- {{ prose({ text: __("activitypub.reader.tagTimeline.noPosts") | replace("%s", tag) }) }}
82
+ {{ prose({ text: __("activitypub.reader.tagTimeline.noPosts", hashtag) }) }}
83
83
  {% endif %}
84
84
  {% endblock %}
@@ -151,8 +151,31 @@
151
151
  x-data="{
152
152
  liked: {{ 'true' if isLiked else 'false' }},
153
153
  boosted: {{ 'true' if isBoosted else 'false' }},
154
+ saved: false,
154
155
  loading: false,
155
156
  error: '',
157
+ async saveLater() {
158
+ if (this.saved) return;
159
+ const el = this.$root;
160
+ const itemUrl = el.dataset.itemUrl;
161
+ try {
162
+ const res = await fetch('/readlater/save', {
163
+ method: 'POST',
164
+ headers: { 'Content-Type': 'application/json' },
165
+ body: JSON.stringify({
166
+ url: itemUrl,
167
+ title: el.closest('article')?.querySelector('p')?.textContent?.substring(0, 80) || itemUrl,
168
+ source: 'activitypub'
169
+ }),
170
+ credentials: 'same-origin'
171
+ });
172
+ if (res.ok) this.saved = true;
173
+ else this.error = 'Failed to save';
174
+ } catch (e) {
175
+ this.error = e.message;
176
+ }
177
+ if (this.error) setTimeout(() => this.error = '', 3000);
178
+ },
156
179
  async interact(action) {
157
180
  if (this.loading) return;
158
181
  this.loading = true;
@@ -213,6 +236,16 @@
213
236
  <a href="{{ itemUrl }}" class="ap-card__action ap-card__action--link" target="_blank" rel="noopener">
214
237
  🔗 {{ __("activitypub.reader.actions.viewOriginal") }}
215
238
  </a>
239
+ {% if application.readlaterEndpoint %}
240
+ <button class="ap-card__action ap-card__action--save"
241
+ :class="{ 'ap-card__action--active': saved }"
242
+ :disabled="saved"
243
+ @click="saveLater()"
244
+ :title="saved ? 'Saved' : 'Save for later'">
245
+ <span x-text="saved ? '🔖' : '📑'"></span>
246
+ <span x-text="saved ? 'Saved' : 'Save'"></span>
247
+ </button>
248
+ {% endif %}
216
249
  <div x-show="error" x-text="error" class="ap-card__action-error" x-transition></div>
217
250
  </footer>
218
251
  {# Close moderation content warning wrapper #}