Skip to content

Commit 3877e97

Browse files
committed
Improvements to Panel Area.
2 parents 35a24cf + 699973a commit 3877e97

File tree

11 files changed

+205
-41
lines changed

11 files changed

+205
-41
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[*.{css,js,json,html,php,html,md}]
1+
[*.{css,js,json,html,php,html,md,vue}]
22
charset = utf-8
33
indent_style = tab
44
indent_size = 2

classes/Feed.php

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,31 @@ public static function clearCache(array $options = []): bool
218218
return (bool) $cache->flush();
219219
}
220220

221+
/*
222+
* @var Bool
223+
*/
224+
public static function refreshFeedCache(array $options = []): bool
225+
{
226+
$cache = kirby()->cache('scottboms.mastodon');
227+
$options = array_merge([
228+
'username' => option('scottboms.mastodon.username'),
229+
'server' => option('scottboms.mastodon.server'),
230+
], $options);
231+
232+
if (empty($options['username']) || empty($options['server'])) {
233+
return false;
234+
}
235+
236+
$userId = (new self($options))->getUserId();
237+
238+
if (!$userId) {
239+
return false;
240+
}
241+
242+
$cacheKey = CacheKey::forFeed($options['server'], $userId);
243+
return $cache->remove($cacheKey);
244+
}
245+
221246
/*
222247
* @var Object
223248
*/
@@ -241,26 +266,39 @@ public function formatFeed(array $feed): array
241266

242267
// return an obj for the item
243268
return new Obj([
244-
'id' => $item['id'] ?? null,
245-
'url' => $item['url'] ?? null,
246-
'author' => $item['account']['display_name'] ?? $item['account']['username'] ?? '',
247-
'username' => $item['account']['username'] ?? '',
248-
'avatar' => $item['account']['avatar_static'] ?? null,
249-
'originalContent' => $item['content'] ?? '',
250-
'rebloggedContent' => $item['reblog']['content'] ?? '',
251-
'content' => $item['content'] ?? ($item['reblog']['content'] ?? ''),
252-
'isBoost' => $isBoost,
253-
'reblogAuthor' => $isBoost ? new Obj([
269+
'id' => $item['id'] ?? null,
270+
'uri' => $item['uri'] ?? null,
271+
'url' => $item['url'] ?? null,
272+
'author' => $item['account']['display_name'] ?? $item['account']['username'] ?? '',
273+
'username' => $item['account']['username'] ?? '',
274+
'avatar' => $item['account']['avatar_static'] ?? null,
275+
'originalContent' => $item['content'] ?? '',
276+
'rebloggedContent' => $item['reblog']['content'] ?? '',
277+
'content' => $item['content'] ?? ($item['reblog']['content'] ?? ''),
278+
'repliesCount' => $item['replies_count'] ?? 0,
279+
'reblogsCount' => $item['reblogs_count'] ?? 0,
280+
'favouritesCount' => $item['favourites_count'] ?? 0,
281+
'favourited' => $item['favourited'] ?? false,
282+
'reblogged' => $item['reblogged'] ?? false,
283+
'bookmarked' => $item['bookmarked'] ?? false,
284+
'sensitive' => $item['sensitive'] ?? false,
285+
'visibility' => $item['visibility'] ?? 'public',
286+
'muted' => $item['muted'] ?? false,
287+
'language' => $item['language'] ?? 'en',
288+
'inReplyToId' => $item['in_reply_to_id'] ?? null,
289+
'inReplyToAccountId' => $item['in_reply_to_account_id'] ?? null,
290+
'isBoost' => $isBoost,
291+
'reblogAuthor' => $isBoost ? new Obj([
254292
'name' => $item['reblog']['account']['display_name'] ?? $item['reblog']['account']['username'] ?? '',
255293
'url' => $item['reblog']['account']['url'] ?? null,
256294
]) : null,
257-
'attribution' => $isBoost ? 'Boosted from @' . ($source['account']['acct'] ?? 'unknown') : '',
258-
'date' => isset($item['created_at'])
295+
'attribution' => $isBoost ? 'Boosted from @' . ($source['account']['acct'] ?? 'unknown') : '',
296+
'date' => isset($item['created_at'])
259297
? date($this->options['dateformat'] ?? 'Y-m-d', strtotime($item['created_at']))
260298
: '',
261-
'media' => $media, // array of obj
262-
'applicationName' => $item['application']['name'] ?? null,
263-
'applicationWebsite' => $item['application']['website'] ?? null,
299+
'media' => $media, // array of obj
300+
'applicationName' => $item['application']['name'] ?? null,
301+
'applicationWebsite' => $item['application']['website'] ?? null,
264302
]);
265303
}, $feed);
266304
}

index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
'homepage' => 'https://github.com/scottboms/kirby-mastodon-feed',
3434
'license' => 'MIT'
3535
],
36-
version: '1.1.1',
36+
version: '1.1.2',
3737
extends: [
3838
'options' => [
3939
'username' => null,

lib/routes.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,47 @@
1111
// restrict to admins
1212
$user = kirby()->user();
1313
if (!$user || !$user->isAdmin()) {
14-
throw new PermissionException('Not allowed.');
14+
throw new PermissionException('Not allowed');
1515
}
1616

1717
try {
1818
$ok = Feed::clearCache();
1919
return [
2020
'status' => $ok ? 'ok' : 'noop',
21-
'message' => $ok ? 'Mastodon cache cleared.' : 'Nothing to clear.'
21+
'message' => $ok ? 'Mastodon cache cleared' : 'Nothing to clear'
2222
];
2323
} catch (Throwable $e) {
24-
// return a clean error to the panel
24+
// return error to the panel
2525
return [
2626
'status' => 'error',
2727
'message' => 'Cache clear failed: ' . $e->getMessage()
2828
];
2929
}
3030
}
31-
]
31+
],
32+
[
33+
'pattern' => 'mastodon-feed/refresh',
34+
'method' => 'POST',
35+
'auth' => true,
36+
'action' => function () {
37+
$user = kirby()->user();
38+
if (!$user || !$user->isAdmin()) {
39+
throw new PermissionException('Not allowed');
40+
}
41+
42+
try {
43+
$ok = Feed::refreshFeedCache();
44+
return [
45+
'status' => $ok ? 'ok' : 'noop',
46+
'message' => $ok ? 'Feed cache refreshed' : 'Nothing to clear'
47+
];
48+
} catch (Throwable $e) {
49+
// return error to the panel
50+
return [
51+
'status' => 'error',
52+
'message' => 'Feed cache refresh failed: ' . $e->getMessage()
53+
];
54+
}
55+
}
56+
],
3257
];

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "mastodon-feed",
33
"description": "Mastodon Feed plugin for Kirby",
44
"author": "Scott Boms <[email protected]>",
5-
"version": "1.1.1",
5+
"version": "1.1.2",
66
"type": "kirby-plugin",
77
"license": "MIT",
88
"scripts": {

src/components/MastodonFeed.vue

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,30 @@
33
<k-panel-inside>
44
<k-header class="k-site-view-header">Mastodon Feed
55
<k-button-group slot="buttons">
6+
<k-button
7+
icon="open"
8+
variant="filled"
9+
size="sm"
10+
title="Open Profile"
11+
@click="goToProfile"
12+
/>
13+
14+
<k-button
15+
icon="refresh"
16+
variant="filled"
17+
theme="blue-icon"
18+
size="sm"
19+
title="Refresh Feed"
20+
text="Refresh Feed"
21+
@click="refreshFeedCache"
22+
/>
23+
624
<k-button
725
icon="mastodon"
826
variant="filled"
927
theme="purple-icon"
1028
size="sm"
29+
title="Clear Cache"
1130
text="Clear Cache"
1231
@click="clearCache"
1332
/>
@@ -57,9 +76,18 @@
5776

5877
<div v-if="originalStatus(item)" class="k-item-content">
5978
<div class="k-item-title" v-html="originalStatus(item).content" />
60-
<p class="k-item-info">{{ formatDate(originalStatus(item).created_at || item.date) }}</p>
79+
<div class="k-mastodon-meta k-item-info">
80+
{{ formatDate(originalStatus(item).created_at || item.date) }}
81+
<span v-if="item.applicationName">• {{ item.applicationName }}</span>
82+
</div>
6183
</div>
6284

85+
<k-bar class="k-mastodon-item-details">
86+
<k-box icon="replies" style="--columns: 2; gap: 0.25rem; justify-content: center" :text="item.repliesCount" />
87+
<k-box icon="star" style="--columns: 2; gap: 0.25rem; justify-content: center" :text="item.favouritesCount" />
88+
<k-box icon="boost" style="--columns: 2; gap: 0.25rem; justify-content: center" :text="item.reblogsCount" />
89+
</k-bar>
90+
6391
</div>
6492
</div>
6593
</div>
@@ -69,7 +97,7 @@
6997
</template>
7098

7199
<script>
72-
import { clearMastodonCache } from "../helpers.js";
100+
import { clearMastodonCache, refreshFeed } from "../helpers.js";
73101
export default {
74102
name: 'MastodonFeed',
75103
props: {
@@ -130,6 +158,18 @@ export default {
130158
};
131159
},
132160
161+
async goToProfile() {
162+
if (!this.account.url) {
163+
this.$panel.notification.error('No Mastodon profile URL found');
164+
return;
165+
}
166+
167+
const url = this.account.url.startsWith('http')
168+
? this.account.url
169+
: `https://${this.account.url}`;
170+
window.open(url, '_blank');
171+
},
172+
133173
async clearCache() {
134174
this.loading = true;
135175
try {
@@ -138,14 +178,33 @@ export default {
138178
if (this.$reload) {
139179
await this.$reload(); // panel helper
140180
} else if (this.$view?.reload) {
141-
await this.$view.reload(); // older/newer variant
181+
await this.$view.reload(); // older/newer variant
182+
} else {
183+
location.reload(); // brute force fallback
184+
}
185+
} finally {
186+
this.loading = false;
187+
}
188+
},
189+
190+
async refreshFeedCache() {
191+
console.log('clicked refresh feed cache button');
192+
this.loading = true;
193+
try {
194+
await refreshFeed(this.$api, this.$panel);
195+
// refresh the view
196+
if (this.$reload) {
197+
await this.$reload(); // panel helper
198+
} else if (this.$view?.reload) {
199+
await this.$view.reload(); // older/newer variant
142200
} else {
143201
location.reload(); // brute force fallback
144202
}
145203
} finally {
146204
this.loading = false;
147205
}
148206
},
207+
149208
}
150209
}
151210
</script>
@@ -176,21 +235,13 @@ export default {
176235
margin-top: .2rem !important;
177236
}
178237
179-
.k-mastodon-toots {
180-
}
181-
182238
.k-mastodon-media {
183239
display: block;
184240
margin-bottom: .5rem;
185241
border-radius: var(--rounded);
186242
}
187243
188244
.k-mastodon-toot {
189-
background: var(--item-color-back);
190-
border-radius: var(--rounded);
191-
box-shadow: var(--item-shadow);
192-
min-height: var(--item-height);
193-
container-type: inline-size;
194245
position: relative;
195246
}
196247
@@ -212,4 +263,23 @@ export default {
212263
inline-size: 100%;
213264
overflow-wrap: break-word;
214265
}
215-
</style>
266+
267+
.k-mastodon-toot .k-item-content p {
268+
margin-bottom: var(--spacing-3);
269+
}
270+
271+
.k-mastodon-item-details {
272+
border-top: 1px solid light-dark(var(--color-gray-250), var(--color-gray-800));
273+
gap: 0.1rem;
274+
margin-top: var(--spacing-8);
275+
padding: var(--spacing-6) var(--spacing-2);
276+
position: absolute;
277+
bottom: 0;
278+
width: 100%;
279+
}
280+
281+
.k-mastodon-meta {
282+
padding-top: var(--spacing-1);
283+
padding-bottom: 4rem;
284+
}
285+
</style>

src/helpers.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,27 @@ export async function clearMastodonCache($api, $panel) {
2222
});
2323
}
2424
}
25+
26+
export async function refreshFeed($api, $panel) {
27+
try {
28+
const res = await $api.post('mastodon-feed/refresh');
29+
if (res.status === 'ok') {
30+
$panel.notification.success({
31+
message: "Mastodon feed refreshed",
32+
icon: "check",
33+
timeout: 5000
34+
});
35+
} else {
36+
$panel.notification.info({
37+
message: res.message || "Nothing to update",
38+
icon: "refresh",
39+
timeout: 5000
40+
});
41+
}
42+
} catch (e) {
43+
$panel.notification.error({
44+
message: e.message || "Feed refresh failed",
45+
timeout: 5000
46+
});
47+
}
48+
}

0 commit comments

Comments
 (0)