From 05f5045648cc1232e1ec4176be6e149e328875f2 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 26 Mar 2022 14:23:29 -0500 Subject: [PATCH] Convert utils/features.ts to TypeScript --- .../normalizers/__tests__/instance-test.js | 1 + app/soapbox/normalizers/instance.ts | 1 + app/soapbox/utils/__tests__/features-test.js | 24 ++++++------- .../utils/{features.js => features.ts} | 35 ++++++++++++++----- package.json | 1 + yarn.lock | 5 +++ 6 files changed, 46 insertions(+), 21 deletions(-) rename app/soapbox/utils/{features.js => features.ts} (84%) diff --git a/app/soapbox/normalizers/__tests__/instance-test.js b/app/soapbox/normalizers/__tests__/instance-test.js index f5fd4f6af..918c8072a 100644 --- a/app/soapbox/normalizers/__tests__/instance-test.js +++ b/app/soapbox/normalizers/__tests__/instance-test.js @@ -23,6 +23,7 @@ describe('normalizeInstance()', () => { description: '', description_limit: 1500, email: '', + feature_quote: false, fedibird_capabilities: [], invites_enabled: false, languages: [], diff --git a/app/soapbox/normalizers/instance.ts b/app/soapbox/normalizers/instance.ts index 047e6a1e4..f43523d01 100644 --- a/app/soapbox/normalizers/instance.ts +++ b/app/soapbox/normalizers/instance.ts @@ -35,6 +35,7 @@ export const InstanceRecord = ImmutableRecord({ description: '', description_limit: 1500, email: '', + feature_quote: false, fedibird_capabilities: ImmutableList(), invites_enabled: false, languages: ImmutableList(), diff --git a/app/soapbox/utils/__tests__/features-test.js b/app/soapbox/utils/__tests__/features-test.js index 3e722e4ac..1531a83ab 100644 --- a/app/soapbox/utils/__tests__/features-test.js +++ b/app/soapbox/utils/__tests__/features-test.js @@ -1,4 +1,4 @@ -import { Map as ImmutableMap } from 'immutable'; +import { InstanceRecord } from 'soapbox/normalizers'; import { parseVersion, @@ -28,7 +28,7 @@ describe('parseVersion', () => { describe('getFeatures', () => { describe('emojiReacts', () => { it('is true for Pleroma 2.0+', () => { - const instance = ImmutableMap({ + const instance = InstanceRecord({ version: '2.7.2 (compatible; Pleroma 2.0.5-6-ga36eb5ea-plerasstodon+dev)', }); const features = getFeatures(instance); @@ -36,7 +36,7 @@ describe('getFeatures', () => { }); it('is false for Pleroma < 2.0', () => { - const instance = ImmutableMap({ + const instance = InstanceRecord({ version: '2.7.2 (compatible; Pleroma 1.1.50-42-g3d9ac6ae-develop)', }); const features = getFeatures(instance); @@ -44,7 +44,7 @@ describe('getFeatures', () => { }); it('is false for Mastodon', () => { - const instance = ImmutableMap({ version: '3.1.4' }); + const instance = InstanceRecord({ version: '3.1.4' }); const features = getFeatures(instance); expect(features.emojiReacts).toBe(false); }); @@ -52,19 +52,19 @@ describe('getFeatures', () => { describe('suggestions', () => { it('is true for Mastodon 2.4.3+', () => { - const instance = ImmutableMap({ version: '2.4.3' }); + const instance = InstanceRecord({ version: '2.4.3' }); const features = getFeatures(instance); expect(features.suggestions).toBe(true); }); it('is false for Mastodon < 2.4.3', () => { - const instance = ImmutableMap({ version: '2.4.2' }); + const instance = InstanceRecord({ version: '2.4.2' }); const features = getFeatures(instance); expect(features.suggestions).toBe(false); }); it('is false for Pleroma', () => { - const instance = ImmutableMap({ + const instance = InstanceRecord({ version: '2.7.2 (compatible; Pleroma 1.1.50-42-g3d9ac6ae-develop)', }); const features = getFeatures(instance); @@ -74,19 +74,19 @@ describe('getFeatures', () => { describe('trends', () => { it('is true for Mastodon 3.0.0+', () => { - const instance = ImmutableMap({ version: '3.0.0' }); + const instance = InstanceRecord({ version: '3.0.0' }); const features = getFeatures(instance); expect(features.trends).toBe(true); }); it('is false for Mastodon < 3.0.0', () => { - const instance = ImmutableMap({ version: '2.4.3' }); + const instance = InstanceRecord({ version: '2.4.3' }); const features = getFeatures(instance); expect(features.trends).toBe(false); }); it('is false for Pleroma', () => { - const instance = ImmutableMap({ + const instance = InstanceRecord({ version: '2.7.2 (compatible; Pleroma 1.1.50-42-g3d9ac6ae-develop)', }); const features = getFeatures(instance); @@ -96,13 +96,13 @@ describe('getFeatures', () => { describe('focalPoint', () => { it('is true for Mastodon 2.3.0+', () => { - const instance = ImmutableMap({ version: '2.3.0' }); + const instance = InstanceRecord({ version: '2.3.0' }); const features = getFeatures(instance); expect(features.focalPoint).toBe(true); }); it('is false for Pleroma', () => { - const instance = ImmutableMap({ + const instance = InstanceRecord({ version: '2.7.2 (compatible; Pleroma 1.1.50-42-g3d9ac6ae-develop)', }); const features = getFeatures(instance); diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.ts similarity index 84% rename from app/soapbox/utils/features.js rename to app/soapbox/utils/features.ts index 87aadaea4..1bb256172 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.ts @@ -6,11 +6,13 @@ import lt from 'semver/functions/lt'; import { custom } from 'soapbox/custom'; +import type { Instance } from 'soapbox/types/entities'; + // Import custom overrides, if exists const overrides = custom('features'); // Truthy array convenience function -const any = arr => arr.some(Boolean); +const any = (arr: Array): boolean => arr.some(Boolean); // For uglification export const MASTODON = 'Mastodon'; @@ -18,12 +20,12 @@ export const PLEROMA = 'Pleroma'; export const MITRA = 'Mitra'; export const TRUTHSOCIAL = 'TruthSocial'; -export const getFeatures = createSelector([instance => instance], instance => { +const getInstanceFeatures = (instance: Instance) => { const v = parseVersion(instance.get('version')); - const features = instance.getIn(['pleroma', 'metadata', 'features'], ImmutableList()); - const federation = instance.getIn(['pleroma', 'metadata', 'federation'], ImmutableMap()); + const features = instance.pleroma.getIn(['metadata', 'features'], ImmutableList()) as ImmutableList; + const federation = instance.pleroma.getIn(['metadata', 'federation'], ImmutableMap()) as ImmutableMap; - return Object.assign({ + return { media: true, privacyScopes: v.software !== TRUTHSOCIAL, spoilers: v.software !== TRUTHSOCIAL, @@ -112,7 +114,7 @@ export const getFeatures = createSelector([instance => instance], instance => { accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'), quotePosts: any([ v.software === PLEROMA && gte(v.version, '2.4.50'), - instance.get('feature_quote') === true, + instance.feature_quote === true, ]), birthdays: v.software === PLEROMA && gte(v.version, '2.4.50'), ethereumLogin: v.software === MITRA, @@ -121,11 +123,26 @@ export const getFeatures = createSelector([instance => instance], instance => { v.software === MASTODON && gte(v.compatVersion, '3.2.0'), v.software === PLEROMA && gte(v.version, '2.4.50'), ]), - }, overrides); + }; +}; + +type Features = ReturnType; + +export const getFeatures = createSelector([ + (instance: Instance) => instance, +], (instance): Features => { + const features = getInstanceFeatures(instance); + return Object.assign(features, overrides) as Features; }); -export const parseVersion = version => { - const regex = /^([\w\.]*)(?: \(compatible; ([\w]*) (.*)\))?$/; +interface Backend { + software: string | null, + version: string, + compatVersion: string, +} + +export const parseVersion = (version: string): Backend => { + const regex = /^([\w.]*)(?: \(compatible; ([\w]*) (.*)\))?$/; const match = regex.exec(version); if (match) { diff --git a/package.json b/package.json index ff9568cd7..4b8b7f358 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "@types/react-helmet": "^6.1.5", "@types/react-router-dom": "^5.3.3", "@types/react-toggle": "^4.0.3", + "@types/semver": "^7.3.9", "@types/uuid": "^8.3.4", "array-includes": "^3.0.3", "autoprefixer": "^10.4.2", diff --git a/yarn.lock b/yarn.lock index 4c7708e0c..15eb690b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2169,6 +2169,11 @@ dependencies: schema-utils "*" +"@types/semver@^7.3.9": + version "7.3.9" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" + integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== + "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"