From d28c7e8e9bea68b61d0c387c7c5c4b799443f2bf Mon Sep 17 00:00:00 2001 From: Andrew Wilson Date: Tue, 21 Jan 2025 21:14:35 -0600 Subject: [PATCH 1/8] Local posting for GoToSocial - fix for a bug in supports.js that compares version number to regexes based on software backend name - functionality to allow users on a GoToSocial instance to select "Local Instance Public" and "Local Instance Unlisted" options for Visibility in composer - both options send their specified visibility, but with the local_only bool parameter set to true --- src/components/compose.jsx | 20 ++++++++++++++++++++ src/data/features.json | 1 + src/utils/supports.js | 3 ++- src/utils/visibility-icons-map.js | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 2a4dca8fee..58cd61cb77 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -1126,6 +1126,16 @@ function Compose({ // params.inReplyToId = replyToStatus?.id || undefined; params.in_reply_to_id = replyToStatus?.id || undefined; } + if(supports('@gotosocial/local-posting')) { + if(params.visibility === "local-public") { + params.visibility = "public"; + params.local_only = true; + } + if(params.visibility === "local-unlisted") { + params.visibility = "unlisted"; + params.local_only = true; + } + } params = removeNullUndefined(params); console.log('POST', params); @@ -1237,9 +1247,19 @@ function Compose({ Local )} + {(supports('@gotosocial/local-posting')) && ( + + )} + {(supports('@gotosocial/local-posting')) && ( + + )} diff --git a/src/data/features.json b/src/data/features.json index 826fd98217..703d3de642 100644 --- a/src/data/features.json +++ b/src/data/features.json @@ -2,6 +2,7 @@ "@mastodon/edit-media-attributes": ">=4.1", "@mastodon/list-exclusive": ">=4.2", "@gotosocial/list-exclusive": ">=0.17", + "@gotosocial/local-posting": ">=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", diff --git a/src/utils/supports.js b/src/utils/supports.js index e240037a2c..426bb6b058 100644 --- a/src/utils/supports.js +++ b/src/utils/supports.js @@ -25,6 +25,7 @@ const platformFeatures = { '@pixelfed/global-feed': containPixelfed, '@pleroma/local-visibility-post': containPleroma, '@akkoma/local-visibility-post': containAkkoma, + '@gotosocial/local-posting': containGTS, }; const supportsCache = {}; @@ -43,7 +44,7 @@ function supports(feature) { if (supportsCache[key]) return supportsCache[key]; if (platformFeatures[feature]) { - return (supportsCache[key] = platformFeatures[feature].test(version)); + return (supportsCache[key] = platformFeatures[feature].test(softwareName)); } const range = features[feature]; diff --git a/src/utils/visibility-icons-map.js b/src/utils/visibility-icons-map.js index 835f740654..4576338e5a 100644 --- a/src/utils/visibility-icons-map.js +++ b/src/utils/visibility-icons-map.js @@ -4,4 +4,6 @@ export default { private: 'lock', direct: 'message', local: 'building', + 'local-public': 'building', + 'local-unlisted': 'building' }; From 727addbea6521d737fcc9b58d3487fa8ebc6dea7 Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Wed, 22 Jan 2025 21:11:52 -0600 Subject: [PATCH 2/8] Added the local badge --- src/components/status.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/status.jsx b/src/components/status.jsx index 9d1da49664..9e941c4afd 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -393,6 +393,7 @@ function Status({ // _filtered, // Non-Mastodon emojiReactions, + localOnly, } = status; const [languageAutoDetected, setLanguageAutoDetected] = useState(null); @@ -1939,6 +1940,13 @@ function Status({ {' '} )} + {localOnly && ( + <> +
+ Local +
{' '} + + )} {!withinContext && ( <> {isThread ? ( From f14aa2315163093f794c547b7335f04e12385962 Mon Sep 17 00:00:00 2001 From: Andrew Wilson Date: Sat, 25 Jan 2025 15:01:38 -0600 Subject: [PATCH 3/8] Local Posting UX Update - local posting is now specified with a different dropdown and has two options, federated and local-instance - removed Local Instance Public and Local Instance Unlisted options from Visibility dropdown - local posting control behaves like visibility wrt content warning control --- src/components/ICONS.jsx | 2 ++ src/components/compose.jsx | 52 ++++++++++++++++++---------- src/utils/local-posting-icons-map.js | 4 +++ 3 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 src/utils/local-posting-icons-map.js diff --git a/src/components/ICONS.jsx b/src/components/ICONS.jsx index 60fbb7c954..342284d823 100644 --- a/src/components/ICONS.jsx +++ b/src/components/ICONS.jsx @@ -175,4 +175,6 @@ export const ICONS = { 'user-x': () => import('@iconify-icons/mingcute/user-x-line'), minimize: () => import('@iconify-icons/mingcute/arrows-down-line'), celebrate: () => import('@iconify-icons/mingcute/celebrate-line'), + locked: () => import('@iconify-icons/mingcute/lock-fill'), + unlocked: () => import('@iconify-icons/mingcute/unlock-line'), }; diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 58cd61cb77..843f789547 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -53,6 +53,7 @@ import supports from '../utils/supports'; import useCloseWatcher from '../utils/useCloseWatcher'; import useInterval from '../utils/useInterval'; import visibilityIconsMap from '../utils/visibility-icons-map'; +import localPostingIconsMap from '../utils/local-posting-icons-map.js'; import AccountBlock from './account-block'; // import Avatar from './avatar'; @@ -259,6 +260,7 @@ function Compose({ const spoilerTextRef = useRef(); const [visibility, setVisibility] = useState('public'); const [sensitive, setSensitive] = useState(false); + const [localOnly, setLocalOnly] = useState('federated'); const [language, setLanguage] = useState( store.session.get('currentLanguage') || DEFAULT_LANG, ); @@ -694,6 +696,12 @@ function Compose({ const [showMentionPicker, setShowMentionPicker] = useState(false); const [showEmoji2Picker, setShowEmoji2Picker] = useState(false); const [showGIFPicker, setShowGIFPicker] = useState(false); + const supportsLocalPosting = supports('@gotosocial/local-posting'); + const [localPostingLabel, setLocalPostingLabel] = useState(''); + const [showLocalOnlyButton, setShowLocalOnlyButton] = useState(supportsLocalPosting); + if(supportsLocalPosting) { + setLocalPostingLabel(localOnly ? 'Local Instance' : 'Federated'); + } const [autoDetectedLanguages, setAutoDetectedLanguages] = useState(null); const [topSupportedLanguages, restSupportedLanguages] = useMemo(() => { @@ -1127,14 +1135,7 @@ function Compose({ params.in_reply_to_id = replyToStatus?.id || undefined; } if(supports('@gotosocial/local-posting')) { - if(params.visibility === "local-public") { - params.visibility = "public"; - params.local_only = true; - } - if(params.visibility === "local-unlisted") { - params.visibility = "unlisted"; - params.local_only = true; - } + params.local_only = localOnly === 'local-instance'; } params = removeNullUndefined(params); console.log('POST', params); @@ -1222,6 +1223,29 @@ function Compose({ /> {' '} + {showLocalOnlyButton && ( + + ) + }