diff --git a/src/components/list-add-edit.jsx b/src/components/list-add-edit.jsx
index d9a21a4b..8630d712 100644
--- a/src/components/list-add-edit.jsx
+++ b/src/components/list-add-edit.jsx
@@ -24,7 +24,7 @@ function ListAddEdit({ list, onClose }) {
}
}
}, [editMode]);
- const supportsExclusive = supports('@mastodon/list-exclusive');
+ const supportsExclusive = supports('@mastodon/list-exclusive') || supports('@gotosocial/list-exclusive');
return (
diff --git a/src/data/features.json b/src/data/features.json
new file mode 100644
index 00000000..7376418b
--- /dev/null
+++ b/src/data/features.json
@@ -0,0 +1,9 @@
+{
+ "@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",
+ "@mastodon/grouped-notifications": "~4.3 || >=4.3"
+}
diff --git a/src/utils/api.js b/src/utils/api.js
index c2f742ad..4ea12ddc 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -89,29 +89,26 @@ export async function initInstance(client, instance) {
configuration: { urls: { streaming } = {} } = {},
} = info;
- 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 wellKnownResponse = await fetch(`${urlBase}/.well-known/nodeinfo`);
- if (wellKnownResponse.ok) {
- const wellKnown = await wellKnownResponse.json();
- if (wellKnown && 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)) {
- const nodeInfoResponse = await fetch(nodeInfoUrl);
- nodeInfo = await nodeInfoResponse.json();
+ 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)) {
+ const nodeInfo = await (await fetch(nodeInfoUrl)).json();
+ if (typeof nodeInfo?.software?.name === 'string') {
+ info.software_name = nodeInfo.software.name;
}
}
}
}
} catch (e) {}
- if (nodeInfo) {
- info.nodeInfo = nodeInfo;
- }
console.log(info);
const instances = store.local.getJSON('instances') || {};
diff --git a/src/utils/store-utils.js b/src/utils/store-utils.js
index c2caf9e5..cc236215 100644
--- a/src/utils/store-utils.js
+++ b/src/utils/store-utils.js
@@ -163,5 +163,5 @@ export function getVapidKey() {
export function isMediaFirstInstance() {
const instance = getCurrentInstance();
- return instance.nodeInfo?.software?.name === 'pixelfed';
+ return /pixelfed/i.test(instance?.version);
}
diff --git a/src/utils/supports.js b/src/utils/supports.js
index 8721d925..07b1d54b 100644
--- a/src/utils/supports.js
+++ b/src/utils/supports.js
@@ -1,82 +1,57 @@
import { satisfies } from 'compare-versions';
+import features from '../data/features.json';
+
import { getCurrentInstance } 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/edit-media-attributes': [['mastodon', '>=4.1']],
- '@mastodon/list-exclusive': [
- ['mastodon', '>=4.2'],
- ['gotosocial', '>=0.17'],
- ],
- '@mastodon/filtered-notifications': [['mastodon', '>=4.3']],
- '@mastodon/fetch-multiple-statuses': [['mastodon', '>=4.3']],
- '@mastodon/trending-link-posts': [['mastodon', '>=4.3']],
- '@mastodon/grouped-notifications': [['mastodon', '>=4.3']],
- '@mastodon/lists': [['!pixelfed']],
- '@mastodon/filters': [['!pixelfed']],
- '@mastodon/mentions': [['!pixelfed']],
- '@mastodon/trending-hashtags': [['!pixelfed']],
- '@mastodon/trending-links': [['!pixelfed']],
- '@mastodon/post-bookmark': [['!pixelfed']],
- '@mastodon/post-edit': [['!pixelfed']],
- '@mastodon/profile-edit': [['!pixelfed']],
- '@mastodon/profile-private-note': [['!pixelfed']],
- '@pixelfed/trending': [['pixelfed']],
- '@pixelfed/home-include-reblogs': [['pixelfed']],
- '@pixelfed/global-feed': [['pixelfed']],
- '@pleroma/local-visibility-post': [['pleroma']],
- '@akkoma/local-visibility-post': [['akkoma']],
+ '@mastodon/lists': notContainPixelfed,
+ '@mastodon/filters': notContainPixelfed,
+ '@mastodon/mentions': notContainPixelfed,
+ '@mastodon/trending-hashtags': notContainPixelfed,
+ '@mastodon/trending-links': notContainPixelfed,
+ '@mastodon/post-bookmark': notContainPixelfed,
+ '@mastodon/post-edit': notContainPixelfed,
+ '@mastodon/profile-edit': notContainPixelfed,
+ '@mastodon/profile-private-note': notContainPixelfed,
+ '@pixelfed/trending': containPixelfed,
+ '@pixelfed/home-include-reblogs': containPixelfed,
+ '@pixelfed/global-feed': containPixelfed,
+ '@pleroma/local-visibility-post': containPleroma,
+ '@akkoma/local-visibility-post': containAkkoma,
};
const supportsCache = {};
function supports(feature) {
- const specs = platformFeatures[feature];
- if (!specs) return false;
-
try {
- let { version, domain, nodeInfo } = getCurrentInstance();
+ let { version, domain, software_name } = getCurrentInstance();
const key = `${domain}-${feature}`;
if (supportsCache[key]) return supportsCache[key];
- let software = 'mastodon';
- if (
- nodeInfo && nodeInfo.software && typeof nodeInfo.software.version === 'string'
- && typeof nodeInfo.software.name === 'string'
- ) {
- software = nodeInfo.software.name.toLowerCase();
- version = nodeInfo.software.version;
+ if (platformFeatures[feature]) {
+ return (supportsCache[key] = platformFeatures[feature].test(version));
}
- const isSupported = specs.some((spec) => versionSatisfies(software, version, spec));
- return (supportsCache[key] = isSupported);
+ const range = features[feature];
+ if (!range) return false;
+ return (supportsCache[key] = (
+ containGTS.test(feature) === containGTS.test(software_name)
+ && satisfies(version, range, {
+ includePrerelease: true,
+ loose: true,
+ })
+ ));
} catch (e) {
return false;
}
}
-function versionSatisfies(software, version, [softwareSpec, versionSpec]) {
- let softwareMatches;
-
- // Inverted spec, like !pixelfed
- if (softwareSpec.startsWith('!')) {
- softwareMatches = software !== softwareSpec.slice(1);
- } else {
- softwareMatches = (
- software === softwareSpec || (
- // Hometown inherits Mastodon features
- software === 'hometown' && softwareSpec === 'mastodon'
- )
- );
- }
-
- return softwareMatches && (
- versionSpec == null || satisfies(version, versionSpec, {
- includePrerelease: true,
- loose: true,
- })
- );
-}
-
export default supports;