Merge pull request #817 from graue/feature-detect

Support exclusive lists with GoToSocial 0.17
This commit is contained in:
Chee Aun 2024-11-12 12:35:38 +08:00 committed by GitHub
commit b70e31a517
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 84 additions and 22 deletions

View file

@ -24,7 +24,9 @@ function ListAddEdit({ list, onClose }) {
}
}
}, [editMode]);
const supportsExclusive = supports('@mastodon/list-exclusive');
const supportsExclusive =
supports('@mastodon/list-exclusive') ||
supports('@gotosocial/list-exclusive');
return (
<div class="sheet">

View file

@ -1,6 +1,7 @@
{
"@mastodon/edit-media-attributes": ">=4.1",
"@mastodon/list-exclusive": ">=4.2",
"@gotosocial/list-exclusive": ">=0.17",
"@mastodon/filtered-notifications": "~4.3 || >=4.3",
"@mastodon/fetch-multiple-statuses": "~4.3 || >=4.3",
"@mastodon/trending-link-posts": "~4.3 || >=4.3",

30
src/locales/en.po generated
View file

@ -408,7 +408,7 @@ msgstr ""
#: src/components/embed-modal.jsx:12
#: src/components/generic-accounts.jsx:142
#: src/components/keyboard-shortcuts-help.jsx:39
#: src/components/list-add-edit.jsx:33
#: src/components/list-add-edit.jsx:35
#: src/components/media-alt-modal.jsx:33
#: src/components/media-modal.jsx:352
#: src/components/notification-service.jsx:156
@ -452,7 +452,7 @@ msgid "No lists."
msgstr ""
#: src/components/account-info.jsx:1939
#: src/components/list-add-edit.jsx:37
#: src/components/list-add-edit.jsx:39
#: src/pages/lists.jsx:58
msgid "New list"
msgstr ""
@ -479,7 +479,7 @@ msgid "Unable to update profile."
msgstr ""
#: src/components/account-info.jsx:2155
#: src/components/list-add-edit.jsx:102
#: src/components/list-add-edit.jsx:104
msgid "Name"
msgstr ""
@ -500,7 +500,7 @@ msgid "Content"
msgstr ""
#: src/components/account-info.jsx:2223
#: src/components/list-add-edit.jsx:147
#: src/components/list-add-edit.jsx:149
#: src/components/shortcuts-settings.jsx:715
#: src/pages/filters.jsx:554
#: src/pages/notifications.jsx:934
@ -891,7 +891,7 @@ msgid "Error deleting draft! Please try again."
msgstr ""
#: src/components/drafts.jsx:127
#: src/components/list-add-edit.jsx:183
#: src/components/list-add-edit.jsx:185
#: src/components/status.jsx:1336
#: src/pages/filters.jsx:587
msgid "Delete…"
@ -1126,44 +1126,44 @@ msgstr ""
msgid "<0>Shift</0> + <1>Alt</1> + <2>k</2>"
msgstr ""
#: src/components/list-add-edit.jsx:37
#: src/components/list-add-edit.jsx:39
msgid "Edit list"
msgstr ""
#: src/components/list-add-edit.jsx:93
#: src/components/list-add-edit.jsx:95
msgid "Unable to edit list."
msgstr ""
#: src/components/list-add-edit.jsx:94
#: src/components/list-add-edit.jsx:96
msgid "Unable to create list."
msgstr ""
#: src/components/list-add-edit.jsx:122
#: src/components/list-add-edit.jsx:124
msgid "Show replies to list members"
msgstr ""
#: src/components/list-add-edit.jsx:125
#: src/components/list-add-edit.jsx:127
msgid "Show replies to people I follow"
msgstr ""
#: src/components/list-add-edit.jsx:128
#: src/components/list-add-edit.jsx:130
msgid "Don't show replies"
msgstr ""
#: src/components/list-add-edit.jsx:141
#: src/components/list-add-edit.jsx:143
msgid "Hide posts on this list from Home/Following"
msgstr ""
#: src/components/list-add-edit.jsx:147
#: src/components/list-add-edit.jsx:149
#: src/pages/filters.jsx:554
msgid "Create"
msgstr ""
#: src/components/list-add-edit.jsx:154
#: src/components/list-add-edit.jsx:156
msgid "Delete this list?"
msgstr ""
#: src/components/list-add-edit.jsx:173
#: src/components/list-add-edit.jsx:175
msgid "Unable to delete list."
msgstr ""

View file

@ -89,6 +89,7 @@ export async function initInstance(client, instance) {
domain,
configuration: { urls: { streaming } = {} } = {},
} = info;
const instances = store.local.getJSON('instances') || {};
if (uri || domain) {
instances[
@ -102,6 +103,34 @@ export async function initInstance(client, instance) {
instances[instance.toLowerCase()] = info;
}
store.local.setJSON('instances', instances);
let nodeInfo;
// GoToSocial requires we get the NodeInfo to identify server type
// spec: https://github.com/jhass/nodeinfo
try {
if (uri || domain) {
let urlBase = uri || `https://${domain}`;
const wellKnown = await (
await fetch(`${urlBase}/.well-known/nodeinfo`)
).json();
if (Array.isArray(wellKnown?.links)) {
const nodeInfoUrl = wellKnown.links.find(
(link) =>
typeof link.rel === 'string' &&
link.rel.startsWith('http://nodeinfo.diaspora.software/ns/schema/'),
)?.href;
if (nodeInfoUrl && nodeInfoUrl.startsWith(urlBase)) {
nodeInfo = await (await fetch(nodeInfoUrl)).json();
}
}
}
} catch (e) {}
const nodeInfos = store.local.getJSON('nodeInfos') || {};
if (nodeInfo) {
nodeInfos[instance.toLowerCase()] = nodeInfo;
}
store.local.setJSON('nodeInfos', nodeInfos);
// This is a weird place to put this but here's updating the masto instance with the streaming API URL set in the configuration
// Reason: Streaming WebSocket URL may change, unlike the standard API REST URLs
const supportsWebSocket = 'WebSocket' in window;

View file

@ -115,6 +115,20 @@ export function getCurrentInstance() {
}
}
let currentNodeInfo = null;
export function getCurrentNodeInfo() {
if (currentNodeInfo) return currentNodeInfo;
try {
const account = getCurrentAccount();
const nodeInfos = store.local.getJSON('nodeInfos') || {};
const instanceURL = account.instanceURL.toLowerCase();
return (currentNodeInfo = nodeInfos[instanceURL] || {});
} catch (e) {
console.error(e);
return {};
}
}
// Massage these instance configurations to match the Mastodon API
// - Pleroma
function getInstanceConfiguration(instance) {

View file

@ -2,13 +2,14 @@ import { satisfies } from 'compare-versions';
import features from '../data/features.json';
import { getCurrentInstance } from './store-utils';
import { getCurrentInstance, getCurrentNodeInfo } from './store-utils';
// Non-semver(?) UA string detection
const containPixelfed = /pixelfed/i;
const notContainPixelfed = /^(?!.*pixelfed).*$/i;
const containPleroma = /pleroma/i;
const containAkkoma = /akkoma/i;
const containGTS = /gotosocial/i;
const platformFeatures = {
'@mastodon/lists': notContainPixelfed,
'@mastodon/filters': notContainPixelfed,
@ -25,11 +26,19 @@ const platformFeatures = {
'@pleroma/local-visibility-post': containPleroma,
'@akkoma/local-visibility-post': containAkkoma,
};
const supportsCache = {};
function supports(feature) {
try {
const { version, domain } = getCurrentInstance();
let { version, domain } = getCurrentInstance();
let softwareName = getCurrentNodeInfo()?.software?.name || 'mastodon';
if (softwareName === 'hometown') {
// Hometown is a Mastodon fork and inherits its features
softwareName = 'mastodon';
}
const key = `${domain}-${feature}`;
if (supportsCache[key]) return supportsCache[key];
@ -39,7 +48,14 @@ function supports(feature) {
const range = features[feature];
if (!range) return false;
return (supportsCache[key] = satisfies(version, range, {
// '@mastodon/blah' => 'mastodon'
const featureSoftware = feature.match(/^@([a-z]+)\//)[1];
const doesSoftwareMatch = featureSoftware === softwareName.toLowerCase();
return (supportsCache[key] =
doesSoftwareMatch &&
satisfies(version, range, {
includePrerelease: true,
loose: true,
}));