diff --git a/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx b/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx
index ba9e9514933852..303847d1ce7fbe 100644
--- a/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx
+++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.jsx
@@ -29,6 +29,7 @@ import { countableText } from '../util/counter';
import { CharacterCounter } from './character_counter';
import { ContentTypeButton } from './content_type_button';
import { EditIndicator } from './edit_indicator';
+import { FederationButton } from './federation_button';
import { NavigationBar } from './navigation_bar';
import { PollForm } from "./poll_form";
import { ReplyIndicator } from './reply_indicator';
@@ -302,6 +303,7 @@ class ComposeForm extends ImmutablePureComponent {
{!this.props.spoilerAlwaysOn && }
+
diff --git a/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx b/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx
new file mode 100644
index 00000000000000..b2773a28072525
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx
@@ -0,0 +1,39 @@
+import { useCallback } from 'react';
+
+import { useIntl, defineMessages } from 'react-intl';
+
+import ShareOffIcon from '@/material-icons/400-24px/share_off.svg?react';
+import { changeComposeAdvancedOption } from 'flavours/glitch/actions/compose';
+import { IconButton } from 'flavours/glitch/components/icon_button';
+import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
+
+const messages = defineMessages({
+ enable_local_only: { id: 'compose.federation.enable_local_only', defaultMessage: 'Disallow federation for this post' },
+ disable_local_only: { id: 'compose.federation.disable_local_only', defaultMessage: 'Allow federation for this post' },
+});
+
+export const FederationButton = () => {
+ const intl = useIntl();
+
+ const disabled = useAppSelector((state) => state.getIn(['compose', 'id']) !== null);
+ const active = useAppSelector((state) => state.getIn(['compose', 'advanced_options', 'do_not_federate']));
+
+ const dispatch = useAppDispatch();
+
+ const handleClick = useCallback(() => {
+ dispatch(changeComposeAdvancedOption('do_not_federate', !active));
+ }, [active, dispatch]);
+
+ return (
+
+ );
+};
diff --git a/app/javascript/flavours/glitch/locales/en.json b/app/javascript/flavours/glitch/locales/en.json
index 2856bab6a6e3ac..b170fdb7a4d767 100644
--- a/app/javascript/flavours/glitch/locales/en.json
+++ b/app/javascript/flavours/glitch/locales/en.json
@@ -17,6 +17,8 @@
"compose.advanced_formatting.disable_html": "Disable HTML advanced formatting",
"compose.advanced_formatting.disable_markdown": "Disable Markdown advanced formatting",
"compose.advanced_formatting.enable_markdown": "Enable Markdown advanced formatting",
+ "compose.federation.disable_local_only": "Allow federation for this post",
+ "compose.federation.enable_local_only": "Disallow federation for this post",
"compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}",
"compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}",
"compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}",
diff --git a/app/javascript/material-icons/400-24px/share_off-fill.svg b/app/javascript/material-icons/400-24px/share_off-fill.svg
new file mode 100644
index 00000000000000..3b6a05d11807e9
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/share_off-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/share_off.svg b/app/javascript/material-icons/400-24px/share_off.svg
new file mode 100644
index 00000000000000..00bb28659b5449
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/share_off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file