From 21ad36c4447cfb8803c20d596d18d84e53147e38 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Tue, 9 Sep 2025 06:42:43 +0200
Subject: [PATCH 01/12] Fix msg being displayed without passing by Lingui
---
src/components/shortcuts-settings.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx
index a7e6e48bd9..306c875602 100644
--- a/src/components/shortcuts-settings.jsx
+++ b/src/components/shortcuts-settings.jsx
@@ -893,7 +893,7 @@ function ImportExport({ shortcuts, onClose }) {
shortcut[name] ? (
<>
- {text}:{' '}
+ {_(text)}:{' '}
{type === 'checkbox'
? shortcut[name] === 'on'
? '✅'
From d0d2eb82debc57e9d7c168c296e1e074fb31e086 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Tue, 9 Sep 2025 06:56:19 +0200
Subject: [PATCH 02/12] Add bubble timeline support on Mastodon+Chuckya
instances
---
src/app.jsx | 3 +-
src/components/ICONS.jsx | 1 +
src/components/nav-menu.jsx | 8 +
src/components/shortcuts-settings.jsx | 60 ++++++-
src/locales/en.po | 219 ++++++++++++++------------
src/pages/public.jsx | 88 +++++++----
src/utils/supports.js | 2 +
7 files changed, 243 insertions(+), 138 deletions(-)
diff --git a/src/app.jsx b/src/app.jsx
index 7021c1b9e0..b57b15b6ce 100644
--- a/src/app.jsx
+++ b/src/app.jsx
@@ -603,7 +603,8 @@ function SecondaryRoutes({ isLoggedIn }) {
} />
} />
- } />
+ } />
+ } />
} />
} />
diff --git a/src/components/ICONS.jsx b/src/components/ICONS.jsx
index ffff4f5270..c3f91d65ec 100644
--- a/src/components/ICONS.jsx
+++ b/src/components/ICONS.jsx
@@ -187,4 +187,5 @@ export const ICONS = {
edit: () => import('@iconify-icons/mingcute/edit-4-line'),
'zoom-in': () => import('@iconify-icons/mingcute/zoom-in-line'),
'zoom-out': () => import('@iconify-icons/mingcute/zoom-out-line'),
+ star2: () => import('@iconify-icons/mingcute/star-2-line'),
};
diff --git a/src/components/nav-menu.jsx b/src/components/nav-menu.jsx
index 934ce5ec24..595c51acd5 100644
--- a/src/components/nav-menu.jsx
+++ b/src/components/nav-menu.jsx
@@ -349,6 +349,14 @@ function NavMenu(props) {
Local
+ {supports('@mastodon/bubble-timeline') && (
+
+ {' '}
+
+ Bubble
+
+
+ )}
{' '}
diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx
index 306c875602..bc16b11a03 100644
--- a/src/components/shortcuts-settings.jsx
+++ b/src/components/shortcuts-settings.jsx
@@ -48,7 +48,7 @@ const TYPE_TEXT = {
following: msg`Home / Following`,
notifications: msg`Notifications`,
list: msg`Lists`,
- public: msg`Public (Local / Federated)`,
+ public: msg`Local / Bubble / Federated`,
search: msg`Search`,
'account-statuses': msg`Account`,
bookmarks: msg`Bookmarks`,
@@ -67,9 +67,9 @@ const TYPE_PARAMS = {
],
public: [
{
- text: msg`Local only`,
- name: 'local',
- type: 'checkbox',
+ text: msg`Variant`,
+ name: 'variant',
+ type: 'variant',
},
{
text: msg`Instance`,
@@ -162,10 +162,27 @@ export const SHORTCUTS_META = {
},
public: {
id: 'public',
- title: ({ local }) => (local ? t`Local` : t`Federated`),
+ title: ({ variant }) =>
+ ({
+ local: t`Local`,
+ bubble: t`Bubble`,
+ federated: t`Federated`,
+ })[variant],
subtitle: ({ instance }) => instance || api().instance,
- path: ({ local, instance }) => `/${instance}/p${local ? '/l' : ''}`,
- icon: ({ local }) => (local ? 'building' : 'earth'),
+ path: ({ variant, instance }) => {
+ const suffix = {
+ local: '/l',
+ bubble: '/b',
+ federated: '',
+ }[variant];
+ return `/${instance}/p${suffix}`;
+ },
+ icon: ({ variant }) =>
+ ({
+ local: 'building',
+ bubble: 'star2',
+ federated: 'earth',
+ })[variant],
},
trending: {
id: 'trending',
@@ -665,6 +682,35 @@ function ShortcutForm({
);
}
+ if (type === 'variant') {
+ return (
+
+
+
+ );
+ }
+
return (
- {supports('@mastodon/bubble-timeline') && (
+ {(supports('@mastodon/bubble-timeline') ||
+ supports('@akkoma/bubble-timeline')) && (
{' '}
diff --git a/src/locales/en.po b/src/locales/en.po
index 2d7bcf8669..d9c267df6f 100644
--- a/src/locales/en.po
+++ b/src/locales/en.po
@@ -816,7 +816,7 @@ msgid "Error loading GIFs"
msgstr ""
#: src/components/keyboard-shortcuts-help.jsx:47
-#: src/components/nav-menu.jsx:376
+#: src/components/nav-menu.jsx:377
#: src/pages/catchup.jsx:1622
msgid "Keyboard shortcuts"
msgstr ""
@@ -1334,29 +1334,29 @@ msgstr ""
msgid "Trending"
msgstr ""
-#: src/components/nav-menu.jsx:356
+#: src/components/nav-menu.jsx:357
#: src/components/shortcuts-settings.jsx:168
#: src/components/shortcuts-settings.jsx:703
msgid "Bubble"
msgstr "Bubble"
-#: src/components/nav-menu.jsx:363
+#: src/components/nav-menu.jsx:364
#: src/components/shortcuts-settings.jsx:169
#: src/components/shortcuts-settings.jsx:706
msgid "Federated"
msgstr ""
-#: src/components/nav-menu.jsx:386
+#: src/components/nav-menu.jsx:387
msgid "Shortcuts / Columns…"
msgstr ""
-#: src/components/nav-menu.jsx:396
-#: src/components/nav-menu.jsx:410
+#: src/components/nav-menu.jsx:397
+#: src/components/nav-menu.jsx:411
msgid "Settings…"
msgstr ""
-#: src/components/nav-menu.jsx:440
-#: src/components/nav-menu.jsx:475
+#: src/components/nav-menu.jsx:441
+#: src/components/nav-menu.jsx:476
#: src/components/shortcuts-settings.jsx:50
#: src/components/shortcuts-settings.jsx:158
#: src/pages/list.jsx:127
@@ -1365,7 +1365,7 @@ msgstr ""
msgid "Lists"
msgstr ""
-#: src/components/nav-menu.jsx:448
+#: src/components/nav-menu.jsx:449
#: src/components/shortcuts.jsx:243
#: src/pages/list.jsx:139
msgid "All Lists"
diff --git a/src/utils/supports.js b/src/utils/supports.js
index a6f1022f32..073304e8f5 100644
--- a/src/utils/supports.js
+++ b/src/utils/supports.js
@@ -30,11 +30,22 @@ const platformFeatures = {
'@akkoma/local-visibility-post': containAkkoma,
};
+// Named features for which support is explicitly expressed by the instance
+const advertisedFeatures = {
+ '@akkoma/bubble-timeline': 'bubble_timeline',
+};
+
const supportsCache = {};
function supports(feature) {
try {
- let { version, domain } = getCurrentInstance();
+ let instanceData = getCurrentInstance();
+ let version = instanceData.version;
+ let domain = instanceData.domain;
+
+ // instanceData extension exclusive to Akkoma and Pleroma
+ let pleroma = instanceData?.pleroma;
+
let softwareName = getCurrentNodeInfo()?.software?.name || 'mastodon';
if (softwareName === 'hometown') {
@@ -49,6 +60,13 @@ function supports(feature) {
return (supportsCache[key] = platformFeatures[feature].test(version));
}
+ // use Pleroma / Akkoma's advertised feature list to see if a given feature is supported
+ if (pleroma) {
+ return (supportsCache[key] = pleroma.metadata.features.includes(
+ advertisedFeatures[feature],
+ ));
+ }
+
const range = features[feature];
if (!range) return false;
From d911fdf213ca3f840dce1402b6e3aedf95db0c7f Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 09:22:18 +0200
Subject: [PATCH 04/12] Replace `@mastodon/bubble-timeline` with
`@chuckya/bubble-timeline`
---
src/components/nav-menu.jsx | 2 +-
src/utils/supports.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/nav-menu.jsx b/src/components/nav-menu.jsx
index acf932012d..16afd998bb 100644
--- a/src/components/nav-menu.jsx
+++ b/src/components/nav-menu.jsx
@@ -349,7 +349,7 @@ function NavMenu(props) {
Local
- {(supports('@mastodon/bubble-timeline') ||
+ {(supports('@chuckya/bubble-timeline') ||
supports('@akkoma/bubble-timeline')) && (
{' '}
diff --git a/src/utils/supports.js b/src/utils/supports.js
index 073304e8f5..2571dc4778 100644
--- a/src/utils/supports.js
+++ b/src/utils/supports.js
@@ -22,7 +22,7 @@ const platformFeatures = {
'@mastodon/profile-edit': notContainPixelfed,
'@mastodon/profile-private-note': notContainPixelfed,
'@mastodon/pinned-posts': notContainPixelfed,
- '@mastodon/bubble-timeline': containChuckya,
+ '@chuckya/bubble-timeline': containChuckya,
'@pixelfed/trending': containPixelfed,
'@pixelfed/home-include-reblogs': containPixelfed,
'@pixelfed/global-feed': containPixelfed,
From 3a6e63bd40f2fb776ea1c020d97c7e6cb8563d61 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 09:29:41 +0200
Subject: [PATCH 05/12] Use destructuring to process results of
`getCurrentInstance()`
I'm not sure why I did that back then.
---
src/utils/supports.js | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/src/utils/supports.js b/src/utils/supports.js
index 2571dc4778..56a6bd46a2 100644
--- a/src/utils/supports.js
+++ b/src/utils/supports.js
@@ -39,12 +39,7 @@ const supportsCache = {};
function supports(feature) {
try {
- let instanceData = getCurrentInstance();
- let version = instanceData.version;
- let domain = instanceData.domain;
-
- // instanceData extension exclusive to Akkoma and Pleroma
- let pleroma = instanceData?.pleroma;
+ let { version, domain, pleroma } = getCurrentInstance();
let softwareName = getCurrentNodeInfo()?.software?.name || 'mastodon';
From 7d9c1e8e69fd59f7b9c3b951e79f1462bfc1b061 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 10:14:40 +0200
Subject: [PATCH 06/12] Create the `select` shortcut schema, and use it for
timeline variants
---
src/components/shortcuts-settings.jsx | 41 +++++++++++++++++----------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx
index bc16b11a03..9cedc6c9cd 100644
--- a/src/components/shortcuts-settings.jsx
+++ b/src/components/shortcuts-settings.jsx
@@ -69,7 +69,21 @@ const TYPE_PARAMS = {
{
text: msg`Variant`,
name: 'variant',
- type: 'variant',
+ type: 'select',
+ values: [
+ {
+ name: msg`Local`,
+ value: "local",
+ },
+ {
+ name: msg`Bubble`,
+ value: "bubble",
+ },
+ {
+ name: msg`Federated`,
+ value: "federated"
+ }
+ ]
},
{
text: msg`Instance`,
@@ -657,7 +671,7 @@ function ShortcutForm({
{TYPE_PARAMS[currentType]?.map?.(
- ({ text, name, type, placeholder, pattern, notRequired }) => {
+ ({ text, name, type, placeholder, pattern, notRequired, values }) => {
if (currentType === 'list') {
return (
@@ -682,29 +696,26 @@ function ShortcutForm({
);
}
- if (type === 'variant') {
+ else if (type === 'select') {
+ let options = values.map(({name, value}) => (
+
+ ))
+
return (
From d4e80838a3d2cb63c8dc156f7b3fb991644f2385 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 10:37:02 +0200
Subject: [PATCH 07/12] Fix path for useTitle not being selected correctly
---
src/pages/public.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/public.jsx b/src/pages/public.jsx
index c0eac58553..f97cb41554 100644
--- a/src/pages/public.jsx
+++ b/src/pages/public.jsx
@@ -34,7 +34,7 @@ function Public({ variant = 'federated', columnMode, ...props }) {
local: `/:instance?/p/l`,
bubble: `/:instance?/p/b`,
federated: `/:instance?/p`,
- };
+ }[variant];
useTitle(title, path);
// const navigate = useNavigate();
From e059a118587df77622d94f720c07ef065555868a Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 10:52:10 +0200
Subject: [PATCH 08/12] Use "Type" copy in the label for the timeline variant
---
src/components/shortcuts-settings.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx
index 9cedc6c9cd..0bb5e95f43 100644
--- a/src/components/shortcuts-settings.jsx
+++ b/src/components/shortcuts-settings.jsx
@@ -67,7 +67,7 @@ const TYPE_PARAMS = {
],
public: [
{
- text: msg`Variant`,
+ text: msg`Type`,
name: 'variant',
type: 'select',
values: [
From fadee1ea06d8584ae513eee2c4c4963a21962f29 Mon Sep 17 00:00:00 2001
From: Stefano Pigozzi
Date: Wed, 10 Sep 2025 11:22:31 +0200
Subject: [PATCH 09/12] Format code appropriately
---
src/components/shortcuts-settings.jsx | 32 +++++++++++++++------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx
index 0bb5e95f43..944aae8b64 100644
--- a/src/components/shortcuts-settings.jsx
+++ b/src/components/shortcuts-settings.jsx
@@ -73,17 +73,17 @@ const TYPE_PARAMS = {
values: [
{
name: msg`Local`,
- value: "local",
+ value: 'local',
},
{
name: msg`Bubble`,
- value: "bubble",
+ value: 'bubble',
},
{
name: msg`Federated`,
- value: "federated"
- }
- ]
+ value: 'federated',
+ },
+ ],
},
{
text: msg`Instance`,
@@ -671,7 +671,15 @@ function ShortcutForm({
{TYPE_PARAMS[currentType]?.map?.(
- ({ text, name, type, placeholder, pattern, notRequired, values }) => {
+ ({
+ text,
+ name,
+ type,
+ placeholder,
+ pattern,
+ notRequired,
+ values,
+ }) => {
if (currentType === 'list') {
return (
@@ -694,21 +702,17 @@ function ShortcutForm({
);
- }
-
- else if (type === 'select') {
- let options = values.map(({name, value}) => (
+ } else if (type === 'select') {
+ let options = values.map(({ name, value }) => (
- ))
+ ));
return (